【练习7.4】使用直方图陆地移动距离EMD区分不同光线条件下的图片cvCalcEMD2

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

  

题目要求:

 设计一个直方图,可以判断给定的图像是在哪种光线条件下被捕捉到的。

程序代码:

  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 CreateSignatureFromHistogram(const CvHistogram * histgogram, CvMat ** signature);
 21 
 22 //<--<--<--<--<--<--<--<--<--函数声明//
 23 
 24 int _tmain(int argc, _TCHAR* argv[])
 25 {
 26     const char * soutceFile_InDoor = "D:\Work\Work_Programming\Source\Image\OpenCVExerciseImage\第7章\楼道1.jpg";
 27     const char * soutceFile_OutDoor = "D:\Work\Work_Programming\Source\Image\OpenCVExerciseImage\第7章\楼道2.jpg";
 28     const char * soutceFile_OutDoorSun = "D:\Work\Work_Programming\Source\Image\OpenCVExerciseImage\第7章\室外阳光1.jpg";
 29 
 30     const char * coloc_1 = "楼道1";
 31     const char * coloc_2 = "楼道2";
 32     const char * coloc_3 = "室外阳光1";
 33     
 34     IplImage * load_image_Source_Indoor = cvLoadImage(soutceFile_InDoor, CV_LOAD_IMAGE_UNCHANGED);
 35     assert(load_image_Source_Indoor);
 36     IplImage * load_image_Source_Outdoor = cvLoadImage(soutceFile_OutDoor, CV_LOAD_IMAGE_UNCHANGED);
 37     assert(load_image_Source_Outdoor);
 38     IplImage * load_image_Source_OutdoorSun = cvLoadImage(soutceFile_OutDoorSun, CV_LOAD_IMAGE_UNCHANGED);
 39     assert(load_image_Source_OutdoorSun);
 40 
 41     IplImage * image_Source_Indoor = cvCreateImage(cvGetSize(load_image_Source_Indoor), IPL_DEPTH_8U, 3);
 42     IplImage * image_Source_Outdoor = cvCreateImage(cvGetSize(load_image_Source_Outdoor), IPL_DEPTH_8U, 3);
 43     IplImage * image_Source_OutdoorSun = cvCreateImage(cvGetSize(load_image_Source_OutdoorSun), IPL_DEPTH_8U, 3);
 44     cvCvtColor(load_image_Source_Indoor, image_Source_Indoor, CV_BGR2HSV);
 45     cvCvtColor(load_image_Source_Outdoor, image_Source_Outdoor, CV_BGR2HSV);
 46     cvCvtColor(load_image_Source_OutdoorSun, image_Source_OutdoorSun, CV_BGR2HSV);
 47 
 48     IplImage * image_r;
 49     IplImage * image_g;
 50     IplImage * image_b;
 51 
 52     CvHistogram * histgram_3D_InDoor;
 53     CvHistogram * histgram_3D_OutDoor;
 54     CvHistogram * histgram_3D_OutDoorSun;
 55     CvMat * sig_Indoor, *sig_Outdoor, *sig_OutdoorSun;
 56 
 57     double emd_result;
 58 
 59     const int dims = 1;
 60     int bin_N[] = { 8 }; //本题只计算bin值为8的情况
 61     size_t length_bin_N = sizeof(bin_N) / sizeof(bin_N[0]);
 62 
 63     for (size_t i = 0; i < length_bin_N; ++i)
 64     {
 65         //
 66         CreateSingleImage(image_Source_Indoor, &image_r, &image_g, &image_b);
 67         cvCvtPixToPlane(image_Source_Indoor, image_r, image_g, image_b, NULL);
 68         IplImage *allImagePlane[3] = { image_r, image_g, image_b };
 69 
 70         histgram_3D_InDoor = Create3DHistogram(dims, bin_N[i]);
 71         cvCalcHist(allImagePlane, histgram_3D_InDoor);
 72         //cvNormalizeHist(histgram_3D_InDoor, 1.0);
 73         CreateSignatureFromHistogram(histgram_3D_InDoor, &sig_Indoor);
 74 
 75         cvReleaseImage(&image_r);
 76         cvReleaseImage(&image_g);
 77         cvReleaseImage(&image_b);
 78 
 79         //
 80         CreateSingleImage(image_Source_Outdoor, &image_r, &image_g, &image_b);
 81         cvCvtPixToPlane(image_Source_Outdoor, image_r, image_g, image_b, NULL);
 82         allImagePlane[0] = image_r;
 83         allImagePlane[1] = image_g;
 84         allImagePlane[2] = image_b;
 85 
 86         histgram_3D_OutDoor = Create3DHistogram(dims, bin_N[i]);
 87         cvCalcHist(allImagePlane, histgram_3D_OutDoor);
 88         //cvNormalizeHist(histgram_3D_OutDoor, 1.0);
 89         CreateSignatureFromHistogram(histgram_3D_OutDoor, &sig_Outdoor);
 90 
 91         cvReleaseImage(&image_r);
 92         cvReleaseImage(&image_g);
 93         cvReleaseImage(&image_b);
 94 
 95         //
 96         CreateSingleImage(image_Source_OutdoorSun, &image_r, &image_g, &image_b);
 97         cvCvtPixToPlane(image_Source_OutdoorSun, image_r, image_g, image_b, NULL);
 98         allImagePlane[0] = image_r;
 99         allImagePlane[1] = image_g;
100         allImagePlane[2] = image_b;
101 
102         histgram_3D_OutDoorSun = Create3DHistogram(dims, bin_N[i]);
103         cvCalcHist(allImagePlane, histgram_3D_OutDoorSun);
104         //cvNormalizeHist(histgram_3D_OutDoorSun, 1.0);
105         CreateSignatureFromHistogram(histgram_3D_OutDoorSun, &sig_OutdoorSun);
106 
107         cvReleaseImage(&image_r);
108         cvReleaseImage(&image_g);
109         cvReleaseImage(&image_b);
110 
111         cout << "=============直方图EMD距离:0表示最精确的匹配=============" << endl << endl;
112         cout << "-------------“" << coloc_1 << "”与“" << coloc_2 << "”直方图EMD距离-------------" << endl;
113         emd_result = cvCalcEMD2(sig_Indoor, sig_Outdoor, CV_DIST_L2);
114         cout << emd_result << endl << endl;
115 
116         cout << "-------------“" << coloc_1 << "”与“" << coloc_3 << "”直方图EMD距离-------------" << endl;
117         emd_result = cvCalcEMD2(sig_Indoor, sig_OutdoorSun, CV_DIST_L2);
118         cout << emd_result << endl << endl;
119 
120         cout << "-------------“" << coloc_2 << "”与“" << coloc_3 << "”直方图EMD距离-------------" << endl;
121         emd_result = cvCalcEMD2(sig_Outdoor, sig_OutdoorSun, CV_DIST_L2);
122         cout << emd_result << endl << endl;
123 
124         cvReleaseMat(&sig_Indoor);
125         cvReleaseMat(&sig_Outdoor);
126         cvReleaseMat(&sig_OutdoorSun);
127 
128         cvReleaseHist(&histgram_3D_InDoor);
129         cvReleaseHist(&histgram_3D_OutDoor);
130         cvReleaseHist(&histgram_3D_OutDoorSun);
131     }
132 
133     system("pause");
134 
135     cvWaitKey();
136     cvReleaseImage(&image_Source_Indoor);
137     cvReleaseImage(&image_Source_Outdoor);
138     cvReleaseImage(&image_Source_OutdoorSun);
139 
140     cvDestroyAllWindows();
141 
142     return 0;
143 }
144 
145 CvHistogram * Create3DHistogram(const int dims, int bins)
146 {
147     int hist_sizes[] = { bins };
148     int hist_type = CV_HIST_ARRAY;
149     float v_range[] = { 0, 255 };
150     float *hist_ranges[] = { v_range};
151 
152     return cvCreateHist(dims, hist_sizes, hist_type, hist_ranges, 1);
153 }
154 
155 void CreateSingleImage(IplImage * image_Src, IplImage **image_r, IplImage **image_g, IplImage **image_b)
156 {
157     IplImage * image_temp = cvCreateImage(cvGetSize(image_Src), IPL_DEPTH_8U, 1);
158     //image_r = &image_temp; 
159     //如果用上面这行这种方式,编译通过,但运行崩溃,本函数结束后image_r便被释放,
160     //因为image_temp只是一个指针变量,占用四个字节的局部变量,对它取地址即&image_temp只是这个局部指针变量的地址,函数结束后自然释放掉
161     //但是,将使用下面这行:将image_temp指针变量所保存的地址赋值给“*image_r”,这个地址是从cvCreateImagere中turn出来的,自然不会随函数结束而释放
162     *image_r = image_temp;
163 
164     *image_g = cvCloneImage(image_temp);
165     *image_b = cvCloneImage(image_temp);
166     cvZero(*image_r);
167     cvZero(*image_g);
168     cvZero(*image_b);
169 }
170 
171 void CreateSignatureFromHistogram(const CvHistogram * histgogram, CvMat ** signature)
172 {
173     int hist_dims = histgogram->mat.dims;
174 
175     int bin_size;
176 
177     bin_size = histgogram->mat.dim[0].size;
178 
179     int numrows = bin_size;
180     *signature = cvCreateMat(numrows, 2, CV_32FC1);
181 
182     float bin_value;
183  
184      
185     for (int v = 0; v < bin_size; ++v)
186     {
187         bin_value = cvQueryHistValue_1D(histgogram, v);
188         cvSet2D(*signature, v, 0, cvScalar(bin_value));
189         cvSet2D(*signature, v, 1, cvScalar(v));
190     }
191 }

结果图片:

要言妙道:

 ①目的是判断光线条件,所以,建一个HSV图像的V的直方图,作为“参考直方图”,其它图像的V直方图与参考直方图计算EMD距离,如果在一个范围内,则表示实在该光线条件下

②共三个输入图像,第一个和第二个选择同一光线条件下的,第三个图像选择其它光线条件,可以看出,第一和第二个的EMD距离很小,第一第三或第二第三的EMD明显很大

原文地址:https://www.cnblogs.com/tingshuixuan2012/p/4491242.html