【练习7.3】从直方图创建signature、计算两个直方图的EMD距离

 

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

 

 

 

  

 

题目要求:

 收集三种光照条件下的手的直方图,计算它们之间的EMD距离

 

程序代码:

 

  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 void CreateSignatureFromHistogram(const CvHistogram * histgogram, CvMat ** signature);
 22 
 23 //<--<--<--<--<--<--<--<--<--函数声明//
 24 
 25 int _tmain(int argc, _TCHAR* argv[])
 26 {
 27     const char * soutceFile_InDoor = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample3.jpg";
 28     const char * soutceFile_OutDoor = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample2.jpg";
 29     const char * soutceFile_OutDoorSun = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第7章\\hand_sample1.jpg";
 30 
 31     IplImage * image_Source_Indoor = cvLoadImage(soutceFile_InDoor, CV_LOAD_IMAGE_UNCHANGED);
 32     assert(image_Source_Indoor);
 33     IplImage * image_Source_Outdoor = cvLoadImage(soutceFile_OutDoor, CV_LOAD_IMAGE_UNCHANGED);
 34     assert(image_Source_Outdoor);
 35     IplImage * image_Source_OutdoorSun = cvLoadImage(soutceFile_OutDoorSun, CV_LOAD_IMAGE_UNCHANGED);
 36     assert(image_Source_OutdoorSun);
 37 
 38     IplImage * image_r;
 39     IplImage * image_g;
 40     IplImage * image_b;
 41 
 42     CvHistogram * histgram_3D_InDoor;
 43     CvHistogram * histgram_3D_OutDoor;
 44     CvHistogram * histgram_3D_OutDoorSun;
 45     CvMat * sig_Indoor, *sig_Outdoor, *sig_OutdoorSun;
 46 
 47     double emd_result;
 48 
 49     const int dims = 3;
 50     int bin_N[] = { 8 }; //本题只计算bin值为8的情况
 51     size_t length_bin_N = sizeof(bin_N) / sizeof(bin_N[0]);
 52 
 53     for (size_t i = 0; i < length_bin_N; ++i)
 54     {
 55         //室内直方图
 56         CreateSingleImage(image_Source_Indoor, &image_r, &image_g, &image_b);
 57         cvCvtPixToPlane(image_Source_Indoor, image_r, image_g, image_b, NULL);
 58         IplImage *allImagePlane[3] = { image_r, image_g, image_b };
 59 
 60         histgram_3D_InDoor = Create3DHistogram(dims, bin_N[i]);
 61         cvCalcHist(allImagePlane, histgram_3D_InDoor);
 62         //cvNormalizeHist(histgram_3D_InDoor, 1.0);
 63         CreateSignatureFromHistogram(histgram_3D_InDoor, &sig_Indoor);
 64 
 65         cvReleaseImage(&image_r);
 66         cvReleaseImage(&image_g);
 67         cvReleaseImage(&image_b);
 68 
 69         //室外直方图
 70         CreateSingleImage(image_Source_Outdoor, &image_r, &image_g, &image_b);
 71         cvCvtPixToPlane(image_Source_Outdoor, image_r, image_g, image_b, NULL);
 72         allImagePlane[0] = image_r;
 73         allImagePlane[1] = image_g;
 74         allImagePlane[2] = image_b;
 75 
 76         histgram_3D_OutDoor = Create3DHistogram(dims, bin_N[i]);
 77         cvCalcHist(allImagePlane, histgram_3D_OutDoor);
 78         //cvNormalizeHist(histgram_3D_OutDoor, 1.0);
 79         CreateSignatureFromHistogram(histgram_3D_OutDoor, &sig_Outdoor);
 80 
 81         cvReleaseImage(&image_r);
 82         cvReleaseImage(&image_g);
 83         cvReleaseImage(&image_b);
 84 
 85         //室外阳光直方图
 86         CreateSingleImage(image_Source_OutdoorSun, &image_r, &image_g, &image_b);
 87         cvCvtPixToPlane(image_Source_OutdoorSun, image_r, image_g, image_b, NULL);
 88         allImagePlane[0] = image_r;
 89         allImagePlane[1] = image_g;
 90         allImagePlane[2] = image_b;
 91 
 92         histgram_3D_OutDoorSun = Create3DHistogram(dims, bin_N[i]);
 93         cvCalcHist(allImagePlane, histgram_3D_OutDoorSun);
 94         //cvNormalizeHist(histgram_3D_OutDoorSun, 1.0);
 95         CreateSignatureFromHistogram(histgram_3D_OutDoorSun, &sig_OutdoorSun);
 96 
 97         cvReleaseImage(&image_r);
 98         cvReleaseImage(&image_g);
 99         cvReleaseImage(&image_b);
100             
101         cout << "=============直方图EMD距离:0表示最精确的匹配=============" << endl << endl;
102         cout << "-------------Indoor和Outdoor直方图EMD距离-------------" << endl;
103         emd_result = cvCalcEMD2(sig_Indoor, sig_Outdoor, CV_DIST_L2);
104         cout << emd_result << endl;
105 
106         cout << "-------------Indoor和OutdoorSun直方图EMD距离-------------" << endl;
107         emd_result = cvCalcEMD2(sig_Indoor, sig_OutdoorSun, CV_DIST_L2);
108         cout << emd_result << endl;
109 
110         cout << "-------------Outdoor和OutdoorSun直方图EMD距离-------------" << endl;
111         emd_result = cvCalcEMD2(sig_OutdoorSun, sig_Outdoor, CV_DIST_L2);
112         cout << emd_result << endl;
113         emd_result = cvCalcEMD2(sig_Outdoor, sig_OutdoorSun, CV_DIST_L2);
114         cout << emd_result<<"  可见cvCalcEMD2参数signature顺序无关,不影响结果" << endl;
115 
116         cvReleaseMat(&sig_Indoor);
117         cvReleaseMat(&sig_Outdoor);
118         cvReleaseMat(&sig_OutdoorSun);
119 
120         cvReleaseHist(&histgram_3D_InDoor);
121         cvReleaseHist(&histgram_3D_OutDoor);
122         cvReleaseHist(&histgram_3D_OutDoorSun);
123     }
124 
125     system("pause");
126 
127     cvWaitKey();
128     cvReleaseImage(&image_Source_Indoor);
129     cvReleaseImage(&image_Source_Outdoor);
130     cvReleaseImage(&image_Source_OutdoorSun);
131 
132     cvDestroyAllWindows();
133 
134     return 0;
135 }
136 
137 CvHistogram * Create3DHistogram(const int dims, int bins)
138 {
139     int hist_sizes[] = { bins, bins, bins };
140     int hist_type = CV_HIST_ARRAY;
141     float r_range[] = { 0, 255 };
142     float g_range[] = { 0, 255 };
143     float b_range[] = { 0, 255 };
144     float *hist_ranges[] = { r_range, g_range, b_range };
145 
146     return cvCreateHist(dims, hist_sizes, hist_type, hist_ranges, 1);
147 }
148 
149 void CreateSingleImage(IplImage * image_Src, IplImage **image_r, IplImage **image_g, IplImage **image_b)
150 {
151     IplImage * image_temp = cvCreateImage(cvGetSize(image_Src), IPL_DEPTH_8U, 1);
152     //image_r = &image_temp; 
153     //如果用上面这行这种方式,编译通过,但运行崩溃,本函数结束后image_r便被释放,
154     //因为image_temp只是一个指针变量,占用四个字节的局部变量,对它取地址即&image_temp只是这个局部指针变量的地址,函数结束后自然释放掉
155     //但是,将使用下面这行:将image_temp指针变量所保存的地址赋值给“*image_r”,这个地址是从cvCreateImagere中turn出来的,自然不会随函数结束而释放
156     *image_r = image_temp;
157 
158     *image_g = cvCloneImage(image_temp);
159     *image_b = cvCloneImage(image_temp);
160     cvZero(*image_r);
161     cvZero(*image_g);
162     cvZero(*image_b);
163 }
164 
165 //目前只实现绘制三维直方图
166 void DrawHistogram(IplImage ** image_hist, const CvHistogram * histogram,int scaleValue)
167 {
168     //直方图:横坐标表示各个bin,纵坐标表示各个bin归一化后的值
169     int hist_dims = histogram->mat.dims;
170 
171     int bin_size1, bin_size2, bin_size3;
172 
173     if (hist_dims == 3)
174     {
175         bin_size1 = histogram->mat.dim[0].size;
176         bin_size2 = histogram->mat.dim[1].size;
177         bin_size3 = histogram->mat.dim[2].size;
178     }
179     else
180     {
181         return;
182     }
183 
184     int bin_count = bin_size1*bin_size2*bin_size3;
185     float max_temp;
186     cvGetMinMaxHistValue(histogram, NULL, &max_temp);
187     int max_value = (int)(max_temp*scaleValue) + 1;
188     CvSize hist_imageSize = cvSize(bin_count, max_value);
189     *image_hist = cvCreateImage(hist_imageSize, IPL_DEPTH_8U, 1);
190     (*image_hist)->origin = 1;
191     cvZero(*image_hist);
192 
193     int x;
194     int value;
195 
196     for (int r = 0; r < bin_size1; ++r)
197     {
198         for (int g = 0; g < bin_size2; ++g)
199         {
200             for (int b = 0; b < bin_size3; ++b)
201             {
202                 x = r*(bin_size1*bin_size2) + g*bin_size2 + b;
203                 value = (int)(cvQueryHistValue_3D(histogram, r, g, b)*scaleValue);
204         /*        if (value == 0)
205                 {
206                     value = 10;
207                 }*/
208                 cvRectangle(*image_hist, cvPoint(x, 0), cvPoint(x, value), cvScalar(255));
209             }
210         }
211     }
212 }
213 
214 void CreateSignatureFromHistogram(const CvHistogram * histgogram,CvMat ** signature)
215 {
216     int hist_dims = histgogram->mat.dims;
217 
218     int bin_size1, bin_size2, bin_size3;
219 
220     //只实现从三维直方图的创建
221     if (hist_dims == 3)
222     {
223         bin_size1 = histgogram->mat.dim[0].size;
224         bin_size2 = histgogram->mat.dim[1].size;
225         bin_size3 = histgogram->mat.dim[2].size;
226     }
227     else
228     {
229         return;
230     }
231 
232     int numrows = bin_size1*bin_size2*bin_size3;
233     *signature = cvCreateMat(numrows, 4, CV_32FC1);
234 
235     float bin_value;
236     int idx;
237     for (int r = 0; r < bin_size1; ++r)
238     {
239         for (int g = 0; g < bin_size2; ++g)
240         {
241             for (int b = 0; b < bin_size3; ++b)
242             {
243                 idx = r*(bin_size1*bin_size2) + g*bin_size2 + b;
244                 bin_value = cvQueryHistValue_3D(histgogram, r, g, b);
245                 cvSet2D(*signature, idx, 0, cvScalar(bin_value));
246                 cvSet2D(*signature, idx, 1, cvScalar(r));
247                 cvSet2D(*signature, idx, 2, cvScalar(g));
248                 cvSet2D(*signature, idx, 3, cvScalar(b));
249             }
250         }
251     }
252 }

 

 

结果图片:

 

要言妙道:

 ①EMD用来度量两个分布之间的相似性

 

posted on 2015-05-09 14:43  毋忆典藏  阅读(748)  评论(0编辑  收藏  举报