【练习7.2】直方图归一化cvNormalizeHist、匹配cvCompareHist及各种匹配方法

 

提纲
题目要求
程序代码
结果图片
要言妙道

 

 

 

  

 

题目要求:

 使用三种光照条件下的手的图像,利用cvCalcHist来获得直方图

a、获得图像HSV三维直方图

b、匹配三种光照条件下的直方图,使用所有的匹配方法,测试bin的值为2, 8, 16, 32, 256的情况

 

程序代码:

 

 1 // OpenCVExerciseTesting.cpp : 定义控制台应用程序的入口点。
 2 //
 3 //D:\\Work\\Work_Programming\\Source\\Image\\lena.jpg
 4 
 5 #include "stdafx.h"
 6 #include <cv.h>
 7 #include <highgui.h>
 8 #include <iostream>
 9 
10 #include <opencv2/legacy/legacy.hpp>
11 //#pragma comment(lib, "opencv_legacy2411.lib")
12 
13 using namespace cv;
14 using namespace std;
15 
16 //函数声明-->--->-->--->-->--->-->--->//
17 
18 
19 //<--<--<--<--<--<--<--<--<--函数声明//
20 
21 int _tmain(int argc, _TCHAR* argv[])
22 {
23     char * soutceFile = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample3.jpg";
24     IplImage * image_Source = cvLoadImage(soutceFile, CV_LOAD_IMAGE_UNCHANGED);
25     assert(image_Source);
26 
27     IplImage *image_HSV = cvCreateImage(cvGetSize(image_Source), IPL_DEPTH_8U, 3);
28     cvCvtColor(image_Source, image_HSV, CV_BGR2HSV);
29     IplImage * image_h = cvCreateImage(cvGetSize(image_HSV), IPL_DEPTH_8U, 1);
30     IplImage * image_s = cvCreateImage(cvGetSize(image_HSV), IPL_DEPTH_8U, 1);
31     IplImage * image_v = cvCreateImage(cvGetSize(image_HSV), IPL_DEPTH_8U, 1);
32     cvCvtPixToPlane(image_HSV, image_h, image_s, image_v, NULL);
33 
34     CvHistogram * histgram_3D;
35 
36     const int dims = 3;
37     int bin_2 = 2;
38     int bin_16 = 16;
39     int bin_256 = 256;
40 
41     int hist_sizes[dims] = { bin_2, bin_2, bin_2 };
42     int hist_type = CV_HIST_ARRAY;
43     float h_range[] = { 0, 180 };
44     float s_range[] = { 0, 255 };
45     float v_range[] = { 0, 255 };
46     float *hist_ranges[dims] = { h_range, s_range, v_range };
47 
48     histgram_3D = cvCreateHist(dims, hist_sizes, hist_type, hist_ranges, 1);
49 
50     IplImage *allImagePlane[dims] = { image_h, image_s, image_v };
51 
52     cvCalcHist(allImagePlane, histgram_3D);
53      
54     system("pause");
55 
56     cvWaitKey();
57     cvReleaseImage(&image_Source);
58     cvDestroyAllWindows();
59 
60     return 0;
61 }
62 
63 void DrawHistogram(IplImage * image_hist, const CvHistogram * histogram)
64 {
65 
66 
67 }
68 
69 
70  
题目a代码

 

 

  1 // OpenCVExerciseTesting.cpp : 定义控制台应用程序的入口点。
  2 //
  3 //D:\\Work\\Work_Programming\\Source\\Image\\lena.jpg
  4 
  5 #include "stdafx.h"
  6 #include <cv.h>
  7 #include <highgui.h>
  8 #include <iostream>
  9 
 10 #include <opencv2/legacy/legacy.hpp>
 11 //#pragma comment(lib, "opencv_legacy2411.lib")
 12 
 13 using namespace cv;
 14 using namespace std;
 15 
 16 //函数声明-->--->-->--->-->--->-->--->//
 17 
 18 CvHistogram * Create3DHistogram(const int dims, int bins);
 19 void CreateSingleImage(IplImage * image_Src, IplImage **image_r, IplImage **image_g, IplImage **image_b);
 20 void DrawHistogram(IplImage ** image_hist, const CvHistogram * histogram, int scaleValue);
 21 
 22 //<--<--<--<--<--<--<--<--<--函数声明//
 23 
 24 int _tmain(int argc, _TCHAR* argv[])
 25 {
 26     const char * soutceFile_InDoor = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample3.jpg";
 27     const char * soutceFile_OutDoor = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample2.jpg";
 28     const char * soutceFile_OutDoorSun = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample1.jpg";
 29 
 30     IplImage * image_Source_Indoor = cvLoadImage(soutceFile_InDoor, CV_LOAD_IMAGE_UNCHANGED);
 31     assert(image_Source_Indoor);
 32     IplImage * image_Source_Outdoor = cvLoadImage(soutceFile_OutDoor, CV_LOAD_IMAGE_UNCHANGED);
 33     assert(image_Source_Outdoor);
 34     IplImage * image_Source_OutdoorSun = cvLoadImage(soutceFile_OutDoorSun, CV_LOAD_IMAGE_UNCHANGED);
 35     assert(image_Source_OutdoorSun);
 36 
 37     IplImage * image_r;
 38     IplImage * image_g;
 39     IplImage * image_b;
 40 
 41     CvHistogram * histgram_3D_InDoor;
 42     CvHistogram * histgram_3D_OutDoor;
 43     CvHistogram * histgram_3D_OutDoorSun;
 44 
 45     double histCompare;
 46 
 47     const int dims = 3;
 48     int bin_N[] = { 2, 8, 16, 32, 256 };
 49     size_t length_bin_N = sizeof(bin_N) / sizeof(bin_N[0]);
 50 
 51     for (size_t i = 0; i < length_bin_N; ++i)
 52     {
 53         //室内直方图
 54         CreateSingleImage(image_Source_Indoor, &image_r, &image_g, &image_b);
 55         cvCvtPixToPlane(image_Source_Indoor, image_r, image_g, image_b, NULL);
 56         IplImage *allImagePlane[3] = { image_r, image_g, image_b };
 57 
 58         histgram_3D_InDoor = Create3DHistogram(dims, bin_N[i]);
 59         cvCalcHist(allImagePlane, histgram_3D_InDoor);
 60         cvNormalizeHist(histgram_3D_InDoor, 1.0);
 61 
 62         cvReleaseImage(&image_r);
 63         cvReleaseImage(&image_g);
 64         cvReleaseImage(&image_b);
 65 
 66         //室外直方图
 67         CreateSingleImage(image_Source_Outdoor, &image_r, &image_g, &image_b);
 68         cvCvtPixToPlane(image_Source_Outdoor, image_r, image_g, image_b, NULL);
 69         allImagePlane[0] = image_r;
 70         allImagePlane[1] = image_g;
 71         allImagePlane[2] = image_b;
 72 
 73         histgram_3D_OutDoor = Create3DHistogram(dims, bin_N[i]);
 74         cvCalcHist(allImagePlane, histgram_3D_OutDoor);
 75         cvNormalizeHist(histgram_3D_OutDoor, 1.0);
 76 
 77         cvReleaseImage(&image_r);
 78         cvReleaseImage(&image_g);
 79         cvReleaseImage(&image_b);
 80 
 81         //室外阳光直方图
 82         CreateSingleImage(image_Source_OutdoorSun, &image_r, &image_g, &image_b);
 83         cvCvtPixToPlane(image_Source_OutdoorSun, image_r, image_g, image_b, NULL);
 84         allImagePlane[0] = image_r;
 85         allImagePlane[1] = image_g;
 86         allImagePlane[2] = image_b;
 87 
 88         histgram_3D_OutDoorSun = Create3DHistogram(dims, bin_N[i]);
 89         cvCalcHist(allImagePlane, histgram_3D_OutDoorSun);
 90         cvNormalizeHist(histgram_3D_OutDoorSun, 1.0);
 91 
 92         cvReleaseImage(&image_r);
 93         cvReleaseImage(&image_g);
 94         cvReleaseImage(&image_b);
 95 
 96         if (bin_N[i] == 8)
 97         {
 98             cvNamedWindow("bin等于8时的室内直方图", CV_WINDOW_AUTOSIZE);
 99             cvNamedWindow("bin等于8时的室外直方图", CV_WINDOW_AUTOSIZE);
100             cvNamedWindow("bin等于8时的室外阳光直方图", CV_WINDOW_AUTOSIZE);
101 
102             IplImage *histImage_Indoor;
103             IplImage *histImage_Outdoor;
104             IplImage *histImage_OutdoorSun;
105 
106             DrawHistogram(&histImage_Indoor, histgram_3D_InDoor, 1000);
107             cvShowImage("bin等于8时的室内直方图", histImage_Indoor);
108             cvReleaseImage(&histImage_Indoor);
109 
110             DrawHistogram(&histImage_Outdoor, histgram_3D_OutDoor, 1000);
111             cvShowImage("bin等于8时的室外直方图", histImage_Outdoor);
112             cvReleaseImage(&histImage_Outdoor);
113 
114             DrawHistogram(&histImage_OutdoorSun, histgram_3D_OutDoorSun, 1000);
115             cvShowImage("bin等于8时的室外阳光直方图", histImage_OutdoorSun);
116             cvReleaseImage(&histImage_OutdoorSun);
117         }
118             
119         //输出匹配结果
120         cout << "--  bin为"<<bin_N[i]<<"  --  " << endl;
121         cout << "===============================================================================" << endl;
122 
123         cout << "CV_COMP_CORREL方法:数值越大越匹配,范围:完全匹配:1,完全不匹配:-1,无关联:0" << endl;
124         cout << "-------------------------------------------------------------------------------" << endl;
125         histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoor, CV_COMP_CORREL);
126         cout << "InDoor与OutDoor    :" << histCompare << endl;
127         histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoorSun, CV_COMP_CORREL);
128         cout << "InDoor与OutDoorSun :" << histCompare << endl;
129         histCompare = cvCompareHist(histgram_3D_OutDoor, histgram_3D_OutDoorSun, CV_COMP_CORREL);
130         cout << "OutDoor与OutDoorSun:" << histCompare << endl;
131 
132         cout << endl;
133 
134         cout << "CV_COMP_CHISQR方法:数值越小越匹配,范围:0到无穷大" << endl;
135         cout << "-------------------------------------------------------------------------------" << endl;
136         histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoor, CV_COMP_CHISQR);
137         cout << "InDoor与OutDoor    :" << histCompare << endl;
138         histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoorSun, CV_COMP_CHISQR);
139         cout << "InDoor与OutDoorSun :" << histCompare << endl;
140         histCompare = cvCompareHist(histgram_3D_OutDoor, histgram_3D_OutDoorSun, CV_COMP_CHISQR);
141         cout << "OutDoor与OutDoorSun:" << histCompare << endl;
142 
143         cout << endl;
144 
145         cout << "CV_COMP_INTERSECT方法:低分代表坏的匹配,范围:如果两个直方图都被归一化到1,则0~1" << endl;
146         cout << "-------------------------------------------------------------------------------" << endl;
147         histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoor, CV_COMP_INTERSECT);
148         cout << "InDoor与OutDoor    :" << histCompare << endl;
149         histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoorSun, CV_COMP_INTERSECT);
150         cout << "InDoor与OutDoorSun :" << histCompare << endl;
151         histCompare = cvCompareHist(histgram_3D_OutDoor, histgram_3D_OutDoorSun, CV_COMP_INTERSECT);
152         cout << "OutDoor与OutDoorSun:" << histCompare << endl;
153 
154         cout << endl;
155 
156         cout << "CV_COMP_BHATTACHARYYA方法:低分代表好的匹配,范围:0~1" << endl;
157         cout << "-------------------------------------------------------------------------------" << endl;
158         histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoor, CV_COMP_BHATTACHARYYA);
159         cout << "InDoor与OutDoor    :" << histCompare << endl;
160         histCompare = cvCompareHist(histgram_3D_InDoor, histgram_3D_OutDoorSun, CV_COMP_BHATTACHARYYA);
161         cout << "InDoor与OutDoorSun :" << histCompare << endl;
162         histCompare = cvCompareHist(histgram_3D_OutDoor, histgram_3D_OutDoorSun, CV_COMP_BHATTACHARYYA);
163         cout << "OutDoor与OutDoorSun:" << histCompare << endl;
164 
165         cout << endl;
166         cout << endl;
167         cout << endl;
168 
169         cvReleaseHist(&histgram_3D_InDoor);
170         cvReleaseHist(&histgram_3D_OutDoor);
171         cvReleaseHist(&histgram_3D_OutDoorSun);
172     }
173 
174     //system("pause");
175 
176     cvWaitKey();
177     cvReleaseImage(&image_Source_Indoor);
178     cvReleaseImage(&image_Source_Outdoor);
179     cvReleaseImage(&image_Source_OutdoorSun);
180 
181     cvDestroyAllWindows();
182 
183     return 0;
184 }
185 
186 CvHistogram * Create3DHistogram(const int dims, int bins)
187 {
188     int hist_sizes[] = { bins, bins, bins };
189     int hist_type = CV_HIST_ARRAY;
190     float r_range[] = { 0, 255 };
191     float g_range[] = { 0, 255 };
192     float b_range[] = { 0, 255 };
193     float *hist_ranges[] = { r_range, g_range, b_range };
194 
195     return cvCreateHist(dims, hist_sizes, hist_type, hist_ranges, 1);
196 }
197 
198 void CreateSingleImage(IplImage * image_Src, IplImage **image_r, IplImage **image_g, IplImage **image_b)
199 {
200     IplImage * image_temp = cvCreateImage(cvGetSize(image_Src), IPL_DEPTH_8U, 1);
201     //image_r = &image_temp; 
202     //如果用上面这行这种方式,编译通过,但运行崩溃,本函数结束后image_r便被释放,
203     //因为image_temp只是一个指针变量,占用四个字节的局部变量,对它取地址即&image_temp只是这个局部指针变量的地址,函数结束后自然释放掉
204     //但是,将使用下面这行:将image_temp指针变量所保存的地址赋值给“*image_r”,这个地址是从cvCreateImagere中turn出来的,自然不会随函数结束而释放
205     *image_r = image_temp;
206 
207     *image_g = cvCloneImage(image_temp);
208     *image_b = cvCloneImage(image_temp);
209     cvZero(*image_r);
210     cvZero(*image_g);
211     cvZero(*image_b);
212 }
213 
214 //目前只实现绘制三维直方图
215 void DrawHistogram(IplImage ** image_hist, const CvHistogram * histogram,int scaleValue)
216 {
217     //直方图:横坐标表示各个bin,纵坐标表示各个bin归一化后的值
218     int hist_dims = histogram->mat.dims;
219 
220     int bin_size1, bin_size2, bin_size3;
221 
222     if (hist_dims == 3)
223     {
224         bin_size1 = histogram->mat.dim[0].size;
225         bin_size2 = histogram->mat.dim[1].size;
226         bin_size3 = histogram->mat.dim[2].size;
227     }
228     else
229     {
230         return;
231     }
232 
233     int bin_count = bin_size1*bin_size2*bin_size3;
234     float max_temp;
235     cvGetMinMaxHistValue(histogram, NULL, &max_temp);
236     int max_value = (int)(max_temp*scaleValue) + 1;
237     CvSize hist_imageSize = cvSize(bin_count, max_value);
238     *image_hist = cvCreateImage(hist_imageSize, IPL_DEPTH_8U, 1);
239     (*image_hist)->origin = 1;
240     cvZero(*image_hist);
241 
242     int x;
243     int value;
244 
245     for (int r = 0; r < bin_size1; ++r)
246     {
247         for (int g = 0; g < bin_size2; ++g)
248         {
249             for (int b = 0; b < bin_size3; ++b)
250             {
251                 x = r*(bin_size1*bin_size2) + g*bin_size2 + b;
252                 value = (int)(cvQueryHistValue_3D(histogram, r, g, b)*scaleValue);
253         /*        if (value == 0)
254                 {
255                     value = 10;
256                 }*/
257                 cvRectangle(*image_hist, cvPoint(x, 0), cvPoint(x, value), cvScalar(255));
258             }
259         }
260     }
261 }

  

 

结果图片:

 

 

 

要言妙道:

 ①二维直方图bin的多少是各维度bin的乘积,以h和s二维直方图来说,如果h的bin的个数为30,s的bin的个数为32,则,二维直方图的bin的个数为30×32,访问的时候要使用cvQueryHistValue_2D

②由于需要匹配“各种光线”下的直方图,所以,代码中将BGR图像转成了HSV图像 cvCvtColor(image_Source, image_HSV, CV_BGR2HSV); 

③书中Example 7-1统计的是HS直方图,即色调和饱和度,没有统计亮度,针对三种光线下的手的图像,如果统计亮度即V的直方图,三种环境下的匹配结果值肯定不匹配度很高。这点在230页有专门的讲解,为什么只选取HS两维而避开V维,是这个道理。

④为什么说是手的肤色直方图,从图7-6的表述来看,所谓肤色直方图即肤色所在图片的直方图,在英文版更看得出这个意思。 

⑤一般情况下在对比直方图之前,都应该自行进行归一化操作,因为如果不归一化,像直方图相交等概念就没有任何意义(即使运行)

posted on 2015-05-07 12:36  毋忆典藏  阅读(1276)  评论(0编辑  收藏  举报