【练习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明显很大
③
‖==========钟于原创 乐于分享 宁静致远 毋忆典藏==========‖