OpenCV2:小学篇 图像灰度变换技术-阈值化处理

秒速五厘米 2021-10-30 03:32 444阅读 0赞

一.简介

在处理图像中,二值化图像(只含灰度值0或1)比灰度图像和彩色图像的计算速度最快

一副图像包括目标背景噪声等想要提取目标物体,通常是采用灰度变换的阈(yu)值化操作

图像的阈值化操作就是将图像像素点分布规律,设定阈值进行像素点分割,进而得到图像的二值图像

图像阈值化的方法有:经典OTSU 固定阈值 自适应阈值 双阈值 半阈值 操作

二.OTSU阈值化

OTSU算法是在1979年提出的一种寻找图像阈值的最大类间方差算法

OTSU算法的步骤:

(1) 统计灰度级中每个像素在整幅图像中的个数

(2) 计算每个像素在整幅图像的概率分布

(3) 对灰度级进行遍历搜索,计算当前灰度值下前景背景类间概率

(4) 通过目标函数计算出类内与类间方差下对应的阈值

  1. #include <stdio.h>
  2. #include <string>
  3. #include "opencv2/highgui/highgui.hpp"
  4. #include "opencv2/opencv.hpp"
  5. using namespace std;
  6. using namespace cv;
  7. // 大均法函数实现
  8. int OTSU(cv::Mat srcImage)
  9. {
  10. int nCols = srcImage.cols;
  11. int nRows = srcImage.rows;
  12. int threshold = 0;
  13. // 初始化统计参数
  14. int nSumPix[256];
  15. float nProDis[256];
  16. for (int i = 0; i < 256; i++)
  17. {
  18. nSumPix[i] = 0;
  19. nProDis[i] = 0;
  20. }
  21. // 统计灰度级中每个像素在整幅图像中的个数
  22. int temp;
  23. for (int i = 0; i < nRows; i++)
  24. {
  25. for (int j = 0; j < nCols; j++)
  26. {
  27. temp = srcImage.at<uchar>(i, j);
  28. if((temp < 256) && (temp >= 0))
  29. nSumPix[temp]++;
  30. }
  31. }
  32. // 计算每个灰度级占图像中的概率分布
  33. for (int i = 0; i < 256; i++)
  34. {
  35. nProDis[i] = (float)nSumPix[i] / (nCols * nRows);
  36. }
  37. // 遍历灰度级 [0, 255],计算出最大类间方差下的阈值
  38. float w0, w1, u0_temp, u1_temp, u0, u1, delta_temp;
  39. double delta_max = 0.0;
  40. for (int i = 0; i < 256; i++)
  41. {
  42. // 初始化相关参数
  43. w0 = w1 = u0_temp = u1_temp = u0 = u1 =delta_temp = 0;
  44. for (int j = 0; j < 256; j++)
  45. {
  46. // 背景部分
  47. if (j <= i)
  48. {
  49. // 当前 i 为分割阈值,第一类总的概率
  50. w0 += nProDis[j];
  51. u0_temp += j * nProDis[j];
  52. }
  53. // 前景部分
  54. else
  55. {
  56. // 当前 i 为分割阈值,第一类总的概率
  57. w1 += nProDis[j];
  58. u1_temp += j * nProDis[j];
  59. }
  60. }
  61. // 分别计算各类的平均灰度
  62. u0 = u0_temp / w0;
  63. u1 = u1_temp / w1;
  64. delta_temp = (float)(w0 * w1 * pow((u0 - u1), 2));
  65. // 依次找到最大类间方差下的阈值
  66. if(delta_temp > delta_max)
  67. {
  68. delta_max = delta_temp;
  69. threshold = i;
  70. }
  71. }
  72. return threshold;
  73. }
  74. int main()
  75. {
  76. // 图像读取及判断
  77. cv::Mat srcImage = cv::imread("a.jpg");
  78. if(!srcImage.data)
  79. return 1;
  80. // 灰度转换
  81. cv::Mat srcGray;
  82. cv::cvtColor(srcImage, srcGray, CV_RGB2GRAY);
  83. cv::imshow("srcGray", srcGray);
  84. // 调用OTSU二值化算法得到阈值
  85. int ostuThreshold = OTSU(srcGray);
  86. std::cout << ostuThreshold << std::endl;
  87. // 定义输出结果图像
  88. cv::Mat otsuResultImage = cv::Mat::zeros(srcGray.rows, srcGray.cols, CV_8UC1);
  89. // 利用得到的阈值实现二值化操作
  90. for (int i = 0; i < srcGray.rows; i++)
  91. {
  92. for (int j = 0; j < srcGray.cols; j++)
  93. {
  94. // 满足大于阈值ostuThreshold置于255
  95. if (srcGray.at<uchar>(i, j) > ostuThreshold)
  96. otsuResultImage.at<uchar>(i, j) = 255;
  97. else
  98. otsuResultImage.at<uchar>(i, j) = 0;
  99. }
  100. }
  101. cv::imshow("otsuResultImage", otsuResultImage);
  102. cv::waitKey(0);
  103. return 0;
  104. }

三.固定阈值

opencv提供了阈值化函数threshold(),用在单通道图像(多通道转单通道)中固定阈值化处理,得到二值化灰度图像

double threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type)

  • src

    源图像

  • dst

    输出图像

  • thresh

    表示阈值设置

  • maxval

    表示预设最大值

  • type    

    表示阈值化处理的类型

  1. #include "opencv2/imgproc/imgproc.hpp"
  2. #include "opencv2/highgui/highgui.hpp"
  3. int main()
  4. {
  5. // 读取源图像及判断
  6. cv::Mat srcImage = cv::imread("a.jpg");
  7. if (!srcImage.data)
  8. return 1;
  9. // 转化为灰度图像
  10. cv::Mat srcGray;
  11. cv::cvtColor(srcImage, srcGray, CV_RGB2GRAY);
  12. cv::imshow("srcGray", srcGray);
  13. cv::Mat dstImage;
  14. // 初始化阈值参数
  15. int thresh = 130;
  16. //初始化阈值处理的类型
  17. /*
  18. 0:二进制阈值
  19. 1:反二进制阈值
  20. 2:截断阈值
  21. 3:0阈值
  22. 4:反0阈值
  23. */
  24. int threshType = 0;
  25. // 预设最大值
  26. const int maxVal = 255;
  27. // 固定阈值化操作
  28. cv::threshold(srcGray, dstImage, thresh, maxVal, threshType);
  29. cv::imshow("stdImage", dstImage);
  30. cv::waitKey(0);
  31. return 0;
  32. }

四.自适应阈值

OpenCV提供了自适应阈值化函数adaptiveThreshold()

void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)

  1. #include "opencv2/imgproc/imgproc.hpp"
  2. #include "opencv2/highgui/highgui.hpp"
  3. int main()
  4. {
  5. // 图像读取及判断
  6. cv::Mat srcImage = cv::imread("a.jpg");
  7. if (!srcImage.data)
  8. return -1;
  9. // 灰度转换
  10. cv::Mat srcGray;
  11. cv::cvtColor(srcImage, srcGray, CV_RGB2GRAY);
  12. cv::imshow("srcGray", srcGray);
  13. cv::Mat dstImage;
  14. // 初始化自适应阈值参数
  15. int blockSize = 5;
  16. int constValue = 10;
  17. const int maxVal = 255;
  18. // 自适应阈值算法
  19. int adaptiveMethod = 0;
  20. int thresholdType = 1;
  21. // 图像自适应阈值操作
  22. cv::adaptiveThreshold(srcGray, dstImage, maxVal, adaptiveMethod, thresholdType, blockSize, constValue);
  23. cv::imshow("dstImage", dstImage);
  24. cv::waitKey(0);
  25. return 0;
  26. }

五.双阈值

六.半阈值

转载于:https://www.cnblogs.com/k5bg/p/11103009.html

发表评论

表情:
评论列表 (有 0 条评论,444人围观)

还没有评论,来说两句吧...

相关阅读