当前位置:   article > 正文

使用Opencv绘制灰度直方图/对比_c++ opencv使用的灰度图是怎么进行比对的

c++ opencv使用的灰度图是怎么进行比对的

一.所需结构体

CvHistogram

结构体原型:

  1. typedef struct CvHistogram {
  2. int type; /* 直方图类型 */
  3. CvArr* bins;  /* 直方图数据 */
  4. float thresh[CV-MAX-DIM][2]; /* 每一维的直方块边界数组 */
  5. float** thresh2; /* 非均匀直方图 */
  6. CvMatND mat; /* 阵列柱状图的嵌入式矩阵头*/
  7. } CvHistogram;

二.所需函数

1.cvCalcHist

函数功能:用于计算图像直方图

函数原型:

void  cvCalcHist( IplImage** image, CvHistogram* hist,int accumulate = 0,const CvArr* mask = NULL );

参数介绍:

  1. IplImage** image: 要计算直方图的图像指针,如果要累加直方图输入图像颜色深度必须一致
  2. CvHistogram* hist: 输出参数,计算出来的直方图。
  3. int accumulate: 表示是否对传入的 hist 清零。不清零的话可以将多幅图像的直方图累加,0代表清零,非0代表不清零!
  4. const CvArr* mask: 掩码,如果mask不为空,那么它必须是一个8位(CV_8U)的数组,并且它的大小的和输入的图像的大小相同,值非 0 的点将用来计算直方图。

返回值:无

2.CvCreateHist

函数功能:用于创建直方图

函数原型:

CvHistogram*  cvCreateHist( int dims, int* sizes, int type,float** ranges = NULL,int uniform = 1);

参数介绍:

  1. int dims: 表示图像是几维空间,即一般彩色图像是3通道的,dim=3;而灰度图是1通道的,dim=1,如果带有透明度的图像即RGBA则dim=4
  2. int* sizes: //直方图维数尺寸,size数组的长度为dims,每个数表示分配给对应维数的bin的个数。如dims=3,则size中用[s1,s2,s3]分别指定每维bin的个数。
  3. int type: 直方图的表示格式: CV_HIST_ARRAY 意味着直方图数据表示为多维密集数组, CV_HIST_TREE 意味着直方图数据表示为多维稀疏数组
  4. float** ranges:        表示方块范围,假设该值设置为0-255意思就是说将像素点压缩到0-255个元素之间(压缩方法是叠加,列如像素点有1024个那么会将1024个像素点的每个值相加在一块放到size组中,比如将10个像素点的值叠加在一块,然后放到对应的size组中!),并将这0-255个元素分别分布到对应的size中!
  5. int uniform: 归一化标识,如果不为0,bin均匀处理ranges的取值范围,为0,根据ranges的设置非均匀处理对应范围的直方块

 

返回值:成功返回一个指向堆中CvHistogram结构体的CvHistogram指针

3.cvGetMinMaxHistValue:

函数功能:用于统计直方图中最小值和最大值

函数原型:

void cvGetMinMaxHistValue( const CvHistogram* hist, float* min_value, float* max_value,int* min_idx = NULL,int* max_idx = NULL);

参数介绍:

  1. const CvHistogram* hist:         要统计的直方图
  2. float* min_value: 直方图最小值的指针 
  3. float* max_value: 直方图最大值的指针 
  4. int* min_idx: 数组中最小坐标的指针 
  5. int* max_idx: 数组中最大坐标的指针 

返回值:无

4.cvConvertScale

函数功能:按比例缩放bin

函数原型:

void  cvConvertScale( const CvArr* src, CvArr* dst,double scale = 1,double shift = 0);

参数介绍:

  1. const CvArr* src: 输入数组
  2. CvArr* dst: 输出数组
  3. double scale: 比例因子
  4. double shift: 该加数与输入元素相加并按比例缩放到输出数组的元素上

返回值:无

5.cvReleaseHist

函数功能:释放直方图

函数原型:

void cvReleaseHist( CvHistogram**hist); 

参数介绍:

CvHistogram**hist :	直方图指针

返回值:无

二. 编写绘制灰度图像的直方图代码

准备工作已经完成,下面开始正式代码编写

2.1 准备工作

准备一张用于测试的图像文件,图像文件格式任意!

这里我的是jpg格式的图像文件

 

如需要可自行保存到本地

 

2.2 编写代码,加载测试图到内存

  1. //打开测试图
  2. IplImage * image = cvLoadImage("D:\\test.jpg",0); //将本地测试图导入到程序堆中
  3. if (image == NULL){ //判断是否打开成功
  4. printf("错误:无法打开该图像,图像文件路径不正确!");
  5. return -1;
  6. }

2.2 创建一个直方图

  1. //创建一个直方图
  2. int arr_size = 255; //定义一个变量用于表示直方图行宽
  3. float hranges_arr[] = { 0, 255 }; //图像方块范围数组
  4. float *phranges_arr = hranges_arr; //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参
  5. CvHistogram *hist = cvCreateHist(1, &arr_size, CV_HIST_ARRAY, &phranges_arr, 1); //创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化

2.3 创建一个空白图像用来绘制直方图

  1. //创建一个空白图像用于绘制直方图
  2. IplImage *histimg = cvCreateImage(cvSize(320, 200), 8, 3);
  3. cvZero(histimg);    //清空histimag-imagedata数据

 

2.4 计算图像直方图  

  1. //计算图像直方图大小
  2. cvCalcHist(&image, hist, 0, 0);

2.5 缩放直方图尺寸

  1. //直方图根据size分组然后根据ranges取值范围来统计图像像素点范围,也就是说ranges为0-255则将图像中像素值叠加在一起(叠加成MIN:0、MIX:255)组并分组到对应的size维中,所以size维里的每个元素非常大,所以要按比例缩小
  2. float max_val; //用于存储获取到的最大值cvGetMinMaxHistValue(hist, 0, &max_val, 0, 0); //获取直方图最大值
  3. cvConvertScale(hist->bins,hist->bins, max_val ? 255. / max_val : 0., 0); //按比例缩小直方图

 

2.6 绘制直方图

 

  1. //开始绘制直方图
  2. int bin_w;
  3. bin_w = histimg->width / arr_size; //得到开始绘制点位置
  4. for (int i = 0; i < arr_size; i++)
  5. {
  6. double val = (cvGetReal1D(hist->bins, i)*histimg->height / 255);//获取矩阵元素值,并转换为对应高度
  7. CvScalar color = CV_RGB(255, 255, 0); cvRectangle(histimg, cvPoint(i*bin_w, histimg->height),
  8. cvPoint((i + 1)*bin_w, (int)(histimg->height - val)),
  9. color, 1, 8, 0);
  10. }

2.7 将直方图显示出来

  1. //显示结果
  2. cvShowImage("1", image); //原图
  3. cvShowImage("2", histimg); //绘制出来的直方图
  4. cvWaitKey(0); //消息循环

运行结果:

完整代码:

  1. //打开测试图
  2. IplImage * image = cvLoadImage("D:\\3.jpg", 0); //将本地测试图导入到程序堆中
  3. if (image == NULL){ //判断是否打开成功
  4. printf("错误:无法打开该图像,图像文件路径不正确!");
  5. return -1;
  6. }
  7. //创建一个直方图
  8. int arr_size = 255; //定义一个变量用于表示直方图行宽
  9. float hranges_arr[] = { 0, 255 }; //图像方块范围数组
  10. float *phranges_arr = hranges_arr; //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参
  11. CvHistogram *hist = cvCreateHist(1, &arr_size, CV_HIST_ARRAY, &phranges_arr, 1); //创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化
  12. //创建一个空白图像用于绘制直方图
  13. IplImage *histimg = cvCreateImage(cvSize(320, 200), 8, 3);
  14. cvZero(histimg);//清空histimag-imagedata数据
  15. //计算图像直方图大小
  16. cvCalcHist(&image, hist, 0, 0);
  17. //直方图根据size分组然后根据ranges取值范围来统计图像像素点范围,也就是说ranges为0-255则将图像中像素值叠加在一起(叠加成MIN:0、MIX:255)组并分组到对应的size维中,所以size维里的每个元素非常大,所以要按比例缩小
  18. float max_val; //用于存储获取到的最大值
  19. cvGetMinMaxHistValue(hist, 0, &max_val, 0, 0); //获取直方图最大值
  20. cvConvertScale(hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0); //按比例缩小直方图
  21. //开始绘制直方图
  22. int bin_w;
  23. bin_w = histimg->width / arr_size;//得到开始绘制点位置
  24. for (int i = 0; i < arr_size; i++)
  25. {
  26. double val = (cvGetReal1D(hist->bins, i)*histimg->height / 255); //获取矩阵元素值,并转换为对应高度
  27. CvScalar color = CV_RGB(255, 255, 0); cvRectangle(histimg, cvPoint(i*bin_w, histimg->height),
  28. cvPoint((i + 1)*bin_w, (int)(histimg->height - val)),
  29. color, 1, 8, 0);
  30. }
  31. //显示结果
  32. cvShowImage("1", image); //灰度原图
  33. cvShowImage("2", histimg); //绘制出来的直方图
  34. cvWaitKey(0); //消息循环

三. 基于直方图颜色数据的对比

1. 所需函数

1.1cvCompareHist

函数功能:用于对比直方图bins数据,并将对比结果以double类型返回

函数原型:

  1. double cvCompareHist( const CvHistogram* hist1,const CvHistogram* hist2,int method);

参数介绍:

  1. const CvHistogram* hist1: 模板图
  2. const CvHistogram* hist2: 要对比的图片
  3. int method : 对比方法可取宏:
  4. #define CV_COMP_CORREL 0 //值越大匹配度越高
  5. #define CV_COMP_CHISQR 1 //值越小匹配度越高
  6. #define CV_COMP_INTERSECT 2 //(归一化)值越大匹配度越高
  7. #define CV_COMP_BHATTACHARYYA 3 //(归一化)值越小匹配度越高

返回值:根据method参数的值返回不同的匹配值!

2. 准备两张图片

3.开始编写代码

3.1 将比对图加载到内存

  1. //加载比对图
  2. IplImage * image = cvLoadImage("D:\\1.jpg", 0); //将本地模板图导入到程序堆中
  3. if (image == NULL){ //判断是否打开成功
  4. printf("错误:无法打开该图像,图像文件路径不正确!");
  5. return -1;
  6. }
  7. IplImage * image1 = cvLoadImage("D:\\2.jpg", 0); //将本地对比图导入到程序堆中
  8. if (image1 == NULL){ //判断是否打开成功
  9. printf("错误:无法打开该图像,图像文件路径不正确!");
  10. return -1;
  11. }

3.2 创建两个直方图

  1. //创建两个直方图用于存储模板和对比图的bin
  2. //创建模板直方图
  3. int arr_size = 255; //定义一个变量用于表示直方图行宽
  4. float hranges_arr[] = { 0, 255 }; //图像方块范围数组
  5. float *phranges_arr = hranges_arr; //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参
  6. //创建对比图的直方图
  7. CvHistogram *hist = cvCreateHist(1, &arr_size, CV_HIST_ARRAY, &phranges_arr, 1);//创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化
  8. int arr_size1 = 255; //定义一个变量用于表示直方图行宽
  9. float hranges_arr1[] = { 0, 255 }; //图像方块范围数组
  10. float *phranges_arr1 = hranges_arr1; //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参
  11. CvHistogram *hist1 = cvCreateHist(1, &arr_size1, CV_HIST_ARRAY, &phranges_arr1, 1);//创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化3.3 计算两张图像的直方图

3.3 计算直方图大小

  1. //计算图像的直方图大小,并保存到hist与hist1结构体中
  2. cvCalcHist(&image, hist, 0, 0);
  3. cvCalcHist(&image1, hist1, 0, 0);

3.4 对比直方图

  1. //将计算后图像直方图与对比图进行比较,并将比较结果保存到Copare变量中
  2. double Compare = cvCompareHist(hist, hist1, 0); //使用CV_COMP_CORREL方法进行对比

3.5 将图像与对比结果显示出来

  1. //将图像与对比结果显示出来
  2. //创建窗口
  3. cvNamedWindow("image_mode",0);//模板窗口
  4. cvNamedWindow("image1",0);//对比图像窗口
  5. //显示图像
  6. cvShowImage("image_mode", image);
  7. cvShowImage("image1", image1);
  8. //打印对比结果:
  9. printf("对比结果为:%lf", Compare);
  10. cvWaitKey(0); //消息循环

运行结果:

可以看到相似度很高

完整代码:

  1. //加载比对图
  2. IplImage * image = cvLoadImage("D:\\1.jpg", 0); //将本地模板图导入到程序堆中
  3. if (image == NULL){ //判断是否打开成功
  4. printf("错误:无法打开该图像,图像文件路径不正确!");
  5. return -1;
  6. }
  7. IplImage * image1 = cvLoadImage("D:\\2.jpg", 0); //将本地对比图导入到程序堆中
  8. if (image1 == NULL){ //判断是否打开成功
  9. printf("错误:无法打开该图像,图像文件路径不正确!");
  10. return -1;
  11. }
  12. //创建两个直方图用于存储模板和对比图的bin
  13. //创建模板直方图
  14. int arr_size = 255; //定义一个变量用于表示直方图行宽
  15. float hranges_arr[] = { 0, 255 }; //图像方块范围数组
  16. float *phranges_arr = hranges_arr; //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参
  17. //创建对比图的直方图
  18. CvHistogram *hist = cvCreateHist(1, &arr_size, CV_HIST_ARRAY, &phranges_arr, 1);//创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化
  19. int arr_size1 = 255; //定义一个变量用于表示直方图行宽
  20. float hranges_arr1[] = { 0, 255 }; //图像方块范围数组
  21. float *phranges_arr1 = hranges_arr1; //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参
  22. CvHistogram *hist1 = cvCreateHist(1, &arr_size1, CV_HIST_ARRAY, &phranges_arr1, 1);//创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化3.3 计算两张图像的直方图
  23. //计算图像的直方图大小,并保存到hist与hist1结构体中
  24. cvCalcHist(&image, hist, 0, 0);
  25. cvCalcHist(&image1, hist1, 0, 0);
  26. //将计算后图像直方图与对比图进行比较,并将比较结果保存到Copare变量中
  27. double Compare = cvCompareHist(hist, hist1, 0); //使用CV_COMP_CORREL方法进行对比
  28. //将图像与对比结果显示出来
  29. //创建窗口
  30. cvNamedWindow("image_mode",0);//模板窗口
  31. cvNamedWindow("image1",0);//对比图像窗口
  32. //显示图像
  33. cvShowImage("image_mode", image);
  34. cvShowImage("image1", image1);
  35. //打印对比结果:
  36. printf("对比结果为:%lf", Compare);
  37. cvWaitKey(0); //消息循环

试试看,修改以上代码,打印结果时将直方图也一并绘制出来

在cvWaitKey代码前加入如下代码:

  1. //直方图根据size分组然后根据ranges取值范围来统计图像像素点范围,也就是说ranges为0-255则将图像中像素值叠加在一起(叠加成MIN:0、MIX:255)组并分组到对应的size维中,所以size维里的每个元素非常大,所以要按比例缩小
  2. //缩小模板直方图bin
  3. float max_val; //用于存储获取到的最大值
  4. cvGetMinMaxHistValue(hist, 0, &max_val, 0, 0); //获取直方图最大值
  5. cvConvertScale(hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0); //按比例缩小直方图
  6. //缩小对比直方图bin
  7. float max_val1; //用于存储获取到的最大值
  8. cvGetMinMaxHistValue(hist1, 0, &max_val1, 0, 0); //获取直方图最大值
  9. cvConvertScale(hist1->bins, hist1->bins, max_val1 ? 255. / max_val1 : 0., 0); //按比例缩小
  10. IplImage *histimg = cvCreateImage(cvSize(320, 200), 8, 3); //模板图的直方图
  11. IplImage *histimg1 = cvCreateImage(cvSize(320, 200), 8, 3); //对比图的直方图
  12. //绘制模板直方图
  13. int bin_w;
  14. bin_w = histimg->width / arr_size;//得到开始绘制点位置
  15. for (int i = 0; i < arr_size; i++)
  16. {
  17. double val = (cvGetReal1D(hist->bins, i)*histimg->height / 255); //获取矩阵元素值,并转换为对应高度
  18. CvScalar color = CV_RGB(255, 255, 0); cvRectangle(histimg, cvPoint(i*bin_w, histimg->height),
  19. cvPoint((i + 1)*bin_w, (int)(histimg->height - val)),
  20. color, 1, 8, 0);
  21. }
  22. //绘制对比图直方图
  23. int bin_w1;
  24. bin_w1 = histimg1->width / arr_size1;//得到开始绘制点位置
  25. for (int i = 0; i < arr_size1; i++)
  26. {
  27. double val = (cvGetReal1D(hist1->bins, i)*histimg1->height / 255); //获取矩阵元素值,并转换为对应高度
  28. CvScalar color = CV_RGB(255, 255, 0); cvRectangle(histimg1, cvPoint(i*bin_w1, histimg1->height),
  29. cvPoint((i + 1)*bin_w1, (int)(histimg1->height - val)),
  30. color, 1, 8, 0);
  31. }
  32. //将直方图显示出来
  33. cvShowImage("1", histimg); //显示模板直方图
  34. cvShowImage("2", histimg1);//显示对比直方图

运行结果:

修改后的完整代码:

  1. //加载比对图
  2. IplImage * image = cvLoadImage("D:\\1.jpg",0); //将本地模板图导入到程序堆中
  3. if (image == NULL){ //判断是否打开成功
  4. printf("错误:无法打开该图像,图像文件路径不正确!");
  5. return -1;
  6. }
  7. IplImage * image1 = cvLoadImage("D:\\2.jpg",0); //将本地对比图导入到程序堆中
  8. if (image1 == NULL){ //判断是否打开成功
  9. printf("错误:无法打开该图像,图像文件路径不正确!");
  10. return -1;
  11. }
  12. //创建两个直方图用于存储模板和对比图的bin
  13. //创建模板直方图
  14. int arr_size = 255; //定义一个变量用于表示直方图行宽
  15. float hranges_arr[] = { 0, 255 }; //图像方块范围数组
  16. float *phranges_arr = hranges_arr; //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参
  17. //创建对比图的直方图
  18. CvHistogram *hist = cvCreateHist(1, &arr_size, CV_HIST_ARRAY, &phranges_arr, 3);//创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化
  19. int arr_size1 = 255; //定义一个变量用于表示直方图行宽
  20. float hranges_arr1[] = { 0, 255 }; //图像方块范围数组
  21. float *phranges_arr1 = hranges_arr1; //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参
  22. CvHistogram *hist1 = cvCreateHist(1, &arr_size1, CV_HIST_ARRAY, &phranges_arr1, 3);//创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化3.3 计算两张图像的直方图
  23. //计算图像的直方图大小,并保存到hist与hist1结构体中
  24. cvCalcHist(&image, hist, 0, 0);
  25. cvCalcHist(&image1, hist1, 0, 0);
  26. //将计算后图像直方图与对比图进行比较,并将比较结果保存到Copare变量中
  27. double Compare = cvCompareHist(hist, hist1, 0); //使用CV_COMP_CORREL方法进行对比
  28. //将图像与对比结果显示出来
  29. //创建窗口
  30. cvNamedWindow("image_mode",0);
  31. cvNamedWindow("image1",0);
  32. //显示图像
  33. cvShowImage("image_mode", image);
  34. cvShowImage("image1", image1);
  35. //打印对比结果:
  36. printf("对比结果为:%lf", Compare);
  37. //直方图根据size分组然后根据ranges取值范围来统计图像像素点范围,也就是说ranges为0-255则将图像中像素值叠加在一起(叠加成MIN:0、MIX:255)组并分组到对应的size维中,所以size维里的每个元素非常大,所以要按比例缩小
  38. //缩小模板直方图bin
  39. float max_val; //用于存储获取到的最大值
  40. cvGetMinMaxHistValue(hist, 0, &max_val, 0, 0); //获取直方图最大值
  41. cvConvertScale(hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0); //按比例缩小直方图
  42. //缩小对比直方图bin
  43. float max_val1; //用于存储获取到的最大值
  44. cvGetMinMaxHistValue(hist1, 0, &max_val1, 0, 0); //获取直方图最大值
  45. cvConvertScale(hist1->bins, hist1->bins, max_val1 ? 255. / max_val1 : 0., 0); //按比例缩小
  46. IplImage *histimg = cvCreateImage(cvSize(320, 200), 8, 3); //模板图的直方图
  47. IplImage *histimg1 = cvCreateImage(cvSize(320, 200), 8, 3); //对比图的直方图
  48. //绘制模板直方图
  49. int bin_w;
  50. bin_w = histimg->width / arr_size;//得到开始绘制点位置
  51. for (int i = 0; i < arr_size; i++)
  52. {
  53. double val = (cvGetReal1D(hist->bins, i)*histimg->height / 255); //获取矩阵元素值,并转换为对应高度
  54. CvScalar color = CV_RGB(255, 255, 0); cvRectangle(histimg, cvPoint(i*bin_w, histimg->height),
  55. cvPoint((i + 1)*bin_w, (int)(histimg->height - val)),
  56. color, 1, 8, 0);
  57. }
  58. //绘制对比图直方图
  59. int bin_w1;
  60. bin_w1 = histimg1->width / arr_size1;//得到开始绘制点位置
  61. for (int i = 0; i < arr_size1; i++)
  62. {
  63. double val = (cvGetReal1D(hist1->bins, i)*histimg1->height / 255); //获取矩阵元素值,并转换为对应高度
  64. CvScalar color = CV_RGB(255, 255, 0); cvRectangle(histimg1, cvPoint(i*bin_w1, histimg1->height),
  65. cvPoint((i + 1)*bin_w1, (int)(histimg1->height - val)),
  66. color, 1, 8, 0);
  67. }
  68. cvShowImage("1", histimg); //显示模板直方图
  69. cvShowImage("2", histimg1);//显示对比直方图
  70. cvWaitKey(0); //消息循环

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

闽ICP备14008679号