• 【练习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用来度量两个分布之间的相似性

  • 相关阅读:
    【HDU 4305】Lightning(生成树计数)
    【HDU 1150】Machine Schedule(二分图匹配)
    【HDU 2063】过山车(二分图匹配)
    透过Nim游戏浅谈博弈
    [SCOI2010]字符串
    [SCOI2010]传送带[三分]
    [SCOI2010]序列操作[分块or线段树]
    HDU 5306 Gorgeous Sequence[线段树区间最值操作]
    1455: 罗马游戏[左偏树or可并堆]
    Codevs 5914 [SXOI2016]最大值
  • 原文地址:https://www.cnblogs.com/tingshuixuan2012/p/4489910.html
Copyright © 2020-2023  润新知