当前位置:   article > 正文

C++OpenCV系统学习(11)——直方图、均衡化、直方图计算、直方图比较、直方图方向投影_局部直方图均衡化 c++

局部直方图均衡化 c++

目录

 

1.概念

1.1直方图概念

​ 1.2直方图均衡化概念

 2.直方图计算

2.1直方图概念扩展

 2.2 画三通道直方图

 3.直方图的比较

3.1Correlation 相关性比较

 3.2Chi-Square 卡方比较

 3.3intersection十字交叉性

3.4Bhattacharyya distance 巴氏距离​

3.5相关API

3.6案例分析

4.直方图的反向投影(back projection)

4.1反向投影概述

4.2反向投影步骤

4.3实现步骤及相关API

4.4 代码演示


1.概念

1.1直方图概念

 1.2直方图均衡化概念

 图像直方图均衡化的实现:

直方图均衡化API:

 直方图均衡化案例

  1. void MyApi::histogramEqualize(Mat& image)
  2. {
  3. Mat gray_image,dst;
  4. cvtColor(image, gray_image, COLOR_BGR2GRAY);
  5. imshow("灰度图", gray_image);
  6. equalizeHist(gray_image, dst);
  7. imshow("直方图均衡化后图像", dst);
  8. }

 上图分别是原图、灰度图、直方图均衡化后的图

 2.直方图计算

2.1直方图概念扩展

 

 2.2 画三通道直方图

  1. void MyApi::histogram_cal(Mat& image)
  2. {
  3. //1.把多通道的图像分离单通道
  4. vector<Mat> bgr_planes;
  5. split(image, bgr_planes);
  6. //imshow("单个通道",bgr_planes[0]);//我们可以输出bgr中的b通道的图像
  7. //2.计算直方图
  8. int histSize = 256;
  9. float range[] = { 0,256 };
  10. const float* histRanges = {range};
  11. Mat b_hist, g_hist, r_hist;
  12. calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRanges, true, false);
  13. calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRanges, true, false);
  14. calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRanges, true, false);
  15. //归一化:为了避免有些像素值的统计值很大,因此为了方便观察归一化到一定的范围内
  16. int hist_h = 400;
  17. int hist_w = 512;
  18. int bin_w = hist_w / histSize;
  19. Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
  20. normalize(b_hist, b_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
  21. normalize(g_hist, g_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
  22. normalize(r_hist, r_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
  23. //绘制直方图
  24. for (int i = 1; i < histSize; i++)
  25. {
  26. line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(b_hist.at<float>(i - 1))),
  27. Point((i)*bin_w, hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, LINE_AA);
  28. line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(g_hist.at<float>(i - 1))),
  29. Point((i)*bin_w, hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, LINE_AA);
  30. line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(r_hist.at<float>(i - 1))),
  31. Point((i)*bin_w, hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, LINE_AA);
  32. }
  33. imshow("彩色图像直方图", histImage);
  34. }

 3.直方图的比较

对于输入的两张图像计算得到直方图H1与H2,归一化到相同的尺度空间(图像大小要一致)然后可以通过计算H1与H2之间的距离得到两个直方图的相似程度,进而比较图像本身的相似程度。openCV提供了比较方法有四种:

  • Correlation 相关性比较
  • Chi-Square 卡方比较
  • intersection十字交叉性
  • Bhattacharyya distance 巴氏距离

3.1Correlation 相关性比较

 3.2Chi-Square 卡方比较

 3.3intersection十字交叉性

3.4Bhattacharyya distance 巴氏距离

3.5相关API

opencv4中compareHist中的method是改为如下:

相关性比较(HISTCMP_CORREL)值越接近1,相关性越高;越接近0,相关性越低;
卡方比较(HISTCMP_CHISQR)值越小越接近,为0时相似度最高;
巴氏距离(HISTCMP_BHATTACHARYYA),完全匹配为 0,完全不匹配为1

3.6案例分析

源文件函数如下:

  1. string convertToString(double d)//double类型转为string类型
  2. {
  3. ostringstream os;
  4. if (os << d)
  5. return os.str();
  6. return "invalid convertsion";
  7. }
  8. void MyApi::histogram_comp(Mat& image, Mat& test1, Mat& test2)
  9. {
  10. //图像颜色空间转到HSV空间
  11. cvtColor(image, image, COLOR_BGR2HSV);
  12. cvtColor(test1, test1, COLOR_BGR2HSV);
  13. cvtColor(test2, test2, COLOR_BGR2HSV);
  14. //设置两个灰度等级
  15. int h_bins = 50;
  16. int s_bins = 60;
  17. int histSize[] = {h_bins,s_bins};
  18. float h_ranges[] = { 0, 180 };
  19. float s_ranges[] = { 0, 256 };
  20. const float* ranges[] = {h_ranges,s_ranges};
  21. int channels[] = { 0,1 };
  22. MatND hist_image;
  23. MatND hist_test1;
  24. MatND hist_test2;
  25. //计算直方图
  26. calcHist(&image, 1, channels, Mat(), hist_image, 2, histSize, ranges, true, false);
  27. normalize(hist_image, hist_image, 0, 1, NORM_MINMAX, -1, Mat());
  28. calcHist(&test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false);
  29. normalize(hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat());
  30. calcHist(&test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false);
  31. normalize(hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat());
  32. //相互比较
  33. double imageimgae = compareHist(hist_image, hist_image, HISTCMP_CORREL);
  34. double imagetest1 = compareHist(hist_image, hist_test1, HISTCMP_CORREL);
  35. double imagetest2 = compareHist(hist_image, hist_test2, HISTCMP_CORREL);
  36. double test1test2 = compareHist(hist_test1, hist_test2, HISTCMP_CORREL);
  37. printf("test1与test2比较的相关性指标为:%f", test1test2);
  38. putText(image, convertToString(imageimgae), Point(50, 50), FONT_HERSHEY_COMPLEX,
  39. 1, Scalar(0, 0, 255), 2, LINE_AA);
  40. putText(test1, convertToString(imagetest1), Point(50, 50), FONT_HERSHEY_COMPLEX,
  41. 1, Scalar(0, 0, 255), 2, LINE_AA);
  42. putText(test2, convertToString(imagetest2), Point(50, 50), FONT_HERSHEY_COMPLEX,
  43. 1, Scalar(0, 0, 255), 2, LINE_AA);
  44. namedWindow("image", WINDOW_AUTOSIZE);
  45. namedWindow("test1", WINDOW_AUTOSIZE);
  46. namedWindow("test2", WINDOW_AUTOSIZE);
  47. imshow("image", image);
  48. imshow("test1", test1);
  49. imshow("test2", test2);
  50. }

 测试函数如下:

  1. #include<opencv2/opencv.hpp>
  2. #include<iostream>
  3. #include"myApi.h"
  4. using namespace cv;
  5. using namespace std;
  6. int main(int argc, char** argv) {
  7. Mat src = imread("F:\\testImage\\test.png");
  8. if (src.empty()) {
  9. printf("could not load image...");
  10. return -1;
  11. }
  12. //如果图像过于大,不能完全显示整张图像可以使用namedWindow()可以实现对图像的自由缩放
  13. //namedWindow("input_window", WINDOW_FREERATIO);
  14. //imshow("input_window", src);
  15. Mat test1 = imread("F:\\testImage\\test1.png");
  16. Mat test2 = imread("F:\\testImage\\test2.png");
  17. MyApi ma;
  18. ma.histogram_comp(src,test1,test2);
  19. waitKey(0);
  20. return 0;
  21. }

 从左到右分别是image与test1比较的相似性、与test2比较的相似性、与image比较的相似性

4.直方图的反向投影(back projection)

4.1反向投影概述

4.2反向投影步骤

  1. 建立直方图模型
  2. 计算待测图像直方图并映射到模型中
  3. 从模型反向计算生成图像

4.3实现步骤及相关API

  1. 加载图片imread
  2. 将图像从RGB色彩空间转换到HSV色彩空间cvtcolor
  3. 计算直方图和归一化calcHist与normalize
  4. Mat与MatND其中Mat表示二维数据,MatND表示三维或者多维数据,此处均可以用Mat表示
  5. 计算反向投影图像calcBackProject

4.4 代码演示

mixChannels()参数说明:

void mixChannels(
const Mat* src, //输入数组或向量矩阵,所有矩阵的大小和深度必须相同。
size_t nsrcs, //矩阵的数量
Mat* dst, //输出数组或矩阵向量,大小和
深度必须与src[0]相同
size_t ndsts,//矩阵的数量
const int* fromTo,//指定被复制通道与要复制到的位置组成的索引对
size_t npairs //fromTo中索引对的数目
);

  1. #define INPUT_TITLE "Input Image"
  2. #define OUTPUT_TITLE "Back Projection"
  3. #define HIST_TITLE "Histogram"
  4. #include<iostream>
  5. #include<opencv2\opencv.hpp>
  6. using namespace std;
  7. using namespace cv;
  8. /*———————————本代码所需变量定义及初始化——————————— */
  9. Mat src, hsv_src, hue, backProjectionImg;
  10. int bins = 12;
  11. int nchannels[] = { 0,0 };
  12. /*—————————————本代码所需函数声明————————————— */
  13. void Hist_And_BackProjection(int, void*);
  14. int main() {
  15. /*—————————————全局变量的赋值————————————— */
  16. //1.图像载入
  17. src = imread("D:/hand.jpg");
  18. if (!src.data)
  19. {
  20. cout << "ERROR : could not load image.\n";
  21. return -1;
  22. }
  23. //2.将图像转化为HSV图像
  24. cvtColor(src, hsv_src, CV_BGR2HSV);
  25. //3.创建一个图像
  26. hue.create(hsv_src.size(), hsv_src.depth());
  27. //窗口命名
  28. namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);
  29. namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
  30. namedWindow(HIST_TITLE, CV_WINDOW_AUTOSIZE);
  31. //从输入图像中拷贝某通道到输出图像中特定的通道
  32. mixChannels(&hsv_src, 1, &hue, 1, nchannels, 1);
  33. //动态调整直方图的 bins ,并做反向投影
  34. createTrackbar("Histogram Bins", INPUT_TITLE, &bins, 180, Hist_And_BackProjection);
  35. Hist_And_BackProjection(0, 0);
  36. imshow(INPUT_TITLE, src);
  37. waitKey(0);
  38. return 0;
  39. }
  40. /*—————————————本代码所需函数实现————————————— */
  41. void Hist_And_BackProjection(int, void*) {
  42. //局部变量
  43. float range[] = { 0,180 };
  44. const float *histRanges = { range };
  45. int hist_h = 400;
  46. int hist_w = 400;
  47. int bin_w = hist_w / bins;
  48. Mat h_hist;
  49. Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
  50. //直方图计算及归一化处理
  51. calcHist(&hue, 1, 0, Mat(), h_hist, 1, &bins, &histRanges, true, false);
  52. normalize(h_hist, h_hist, 0, 255, NORM_MINMAX, -1, Mat());
  53. //直方图反向投影
  54. calcBackProject(&hue, 1, 0, h_hist, backProjectionImg, &histRanges, 1, true);
  55. //画直方图分部图
  56. for (int i = 0; i < bins; i++)
  57. {
  58. /*rectangle(histImage,
  59. Point((i - 1)*bin_w, (hist_h - cvRound(h_hist.at<float>(i - 1)*(400 / 255)))),
  60. Point(i*bin_w, (hist_h - cvRound(h_hist.at<float>(i)*(400 / 255)))),
  61. Scalar(0, 0, 255),
  62. -1);*/
  63. rectangle(histImage,
  64. Point((i - 1)*bin_w, (hist_h - cvRound(h_hist.at<float>(i - 1)*(400 / 255)))),
  65. Point(i*bin_w, hist_h),
  66. Scalar(0, 0, 255),
  67. -1);
  68. }
  69. imshow(OUTPUT_TITLE, backProjectionImg);
  70. imshow(HIST_TITLE, histImage);
  71. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/46640
推荐阅读
相关标签
  

闽ICP备14008679号