前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【图像处理100问】图像处理之各种像素操作效果(上)

【图像处理100问】图像处理之各种像素操作效果(上)

作者头像
周旋
发布2020-07-14 10:28:51
5520
发布2020-07-14 10:28:51
举报
文章被收录于专栏:行走的机械人行走的机械人

学校把很多考试都放在暑假考了,我们专业有6科,分布在一个月内。又要备赛数学建模,快乐暑假已经被榨干了... ...

所以只能利用碎片时间更一篇上次给大家介绍的《视觉图像处理100问》了,因为有原作者写好的代码,所以比较节省时间。关于这个具体资料看上篇文章:

【资源分享1】日本同行整理的视觉处理100问

最近在筹划一篇详解分水岭算法的文章,大家等等吧~

问题一:通道交换

这道题如果用opencv的cvtColor函数写很简单,cvtColor函数可以在绝大部分格式之间转换,具体见下图(截自毛星云《opencv3编程入门》):

我们基于像素操作,自定义一个函数channel_swap()来实现BGR->RGB转换的功能:

// 【1】通道转换
cv::Mat channel_swap(cv::Mat img) {
  // get height and width
  int width = img.cols;
  int height = img.rows;

  // prepare output
  cv::Mat out = cv::Mat::zeros(height, width, CV_8UC3);

  // each y, x
  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      // R -> B
      out.at<cv::Vec3b>(y, x)[0] = img.at<cv::Vec3b>(y, x)[2];
      // B -> R
      out.at<cv::Vec3b>(y, x)[2] = img.at<cv::Vec3b>(y, x)[0];
      // G -> G
      out.at<cv::Vec3b>(y, x)[1] = img.at<cv::Vec3b>(y, x)[1];
    }
  }
  return out;
}

程序很简单,就是逐像素主通道进行变换就可以了。

对比opencv的API:cvtColor和自定义函数的运行效果:

问题二:图像转灰度图

RGB转灰度图就是根据上图公式,同样可以根据像素操作来实现:

//【2】BGR -> Gray
cv::Mat BGR2GRAY(cv::Mat img) {
  // get height and width
  int width = img.cols;
  int height = img.rows;

  // prepare output
  cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);

  // each y, x
  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      // BGR -> Gray
      out.at<uchar>(y, x) = 0.2126 * (float)img.at<cv::Vec3b>(y, x)[2] \
        + 0.7152 * (float)img.at<cv::Vec3b>(y, x)[1] \
        + 0.0722 * (float)img.at<cv::Vec3b>(y, x)[0];
    }
  }
  return out;
}

问题三:图像二值化(THresholding)

二值化原理很简单了,利用像素操作加if判断就可以实现:

// Gray -> Binary
cv::Mat Binarize(cv::Mat gray, int th){
  int width = gray.cols;
  int height = gray.rows;

  // prepare output
  cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);

  // each y, x
  for (int y = 0; y < height; y++){
    for (int x = 0; x < width; x++){
      // Binarize
      if (gray.at<uchar>(y, x) > th){
        out.at<uchar>(y, x) = 255;
      } else {
        out.at<uchar>(y, x) = 0;
      }
    }
  }
  return out;
}

下面对比一下opencv的Threshold()函数和我们自定义函数Binarize()函数:

int main()
{
  Mat srcImage, grayImage,dstImage;

  srcImage = imread("御坂美琴/1.png");//读取图像
  imshow("原图BGR", srcImage);
  cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);//转灰度
  threshold(grayImage, dstImage, 125, 255, THRESH_BINARY);

  imshow("threshold函数阈值化", dstImage);

  Mat out = Binarize(grayImage,125);
  imshow("自定义函数阈值化", out);//自定义函数

  waitKey();
  return 0;
}

问题四:大津二值化算法(Otsu's Method)

// Gray -> Binary 输入图像为灰度图
cv::Mat Binarize_Otsu(cv::Mat gray){
  int width = gray.cols;
  int height = gray.rows;

  // determine threshold
  double w0 = 0, w1 = 0;  //被阈值 t分开的两个类中的像素数占总像素数的比率(满足相加等于1 )
  double m0 = 0, m1 = 0; //是这两个类的像素值的平均值
  double max_sb = 0, sb = 0;
  int th = 0;
  int val;

  // 遍历阈值t的可能值寻求最大值
  for (int t = 0; t < 255; t++){
    w0 = 0;
    w1 = 0;
    m0 = 0;
    m1 = 0;
    for (int y = 0; y < height; y++){  //遍历图像像素点
      for (int x = 0; x < width; x++){
        val = (int)(gray.at<uchar>(y, x)); //获取该点的灰度值

        if (val < t){
          w0++;
          m0 += val;
        } else {
          w1++;
          m1 += val;
        }
      }
    }

    m0 /= w0;//计算大于,小于阈值t的两类像素的像素值的平均值m0 ,m1
    m1 /= w1;
    w0 /= (height * width);//计算大于,小于阈值t的两类像素的个数占总个数的比例w0,w1
    w1 /= (height * width);
    sb = w0 * w1 * pow((m0 - m1), 2); //计算sb的平方

    if(sb > max_sb){ //更新最大值
      max_sb = sb;
      th = t;
    }
  }

  std::cout << "threshold:" << th << std::endl;//打印阈值

  //获取阈值后,对图像进行阈值化
  // prepare output
  cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);

  // each y, x
  for (int y = 0; y < height; y++){
    for (int x = 0; x < width; x++){
      // Binarize
      if (gray.at<uchar>(y, x) > th){
        out.at<uchar>(y, x) = 255;
      } else {
        out.at<uchar>(y, x) = 0;
      }

    }
  }

  return out;
}

处理效果:

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-07-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Opencv视觉实践 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档