9光照对直方图EMD匹配产生的影响

9光照对直方图EMD匹配产生的影响

与上例一样,收集手的肤色直方图。以其中的一个室内直方图样本作为模型,并计算其与另一个室内直方图、一个室外阴影直方图、一个室外光照直方图的EMD距离,利用这些测量值设置一个距离阈值,再次比较EMD距离,程序中三幅图像已经过处理,依次比前一幅亮度增加25,具体代码如下:


#include <cv.h>
#include <highgui.h>  
#include <stdlib.h>  
#include <stdio.h> 
#include <math.h>

using namespace std;

int main(int argc, char* argv[])
{
    IplImage* src1, *src2, *src3, *src4, *Imask, *hsv1, *hsv2, *hsv3, *hsv4;        //源图像 HSV格式图像
    //src1 src2 src3 每张亮度较前一张增加了10 src3 src4增加40
    //模板
    if (!(src1 = cvLoadImage("D:\\Template\\OpenCV\\Template53_hue-saturation_Compare_EMD\\Debug\\handdd.jpg")))
        return -1;
    //室内
    if (!(src2 = cvLoadImage("D:\\Template\\OpenCV\\Template53_hue-saturation_Compare_EMD\\Debug\\handd.jpg")))
        return -2;
    //室外阴影
    if (!(src3 = cvLoadImage("D:\\Template\\OpenCV\\Template53_hue-saturation_Compare_EMD\\Debug\\handdd_out.jpg")))
        return -3;
    //室外光照
    if (!(src4 = cvLoadImage("D:\\Template\\OpenCV\\Template53_hue-saturation_Compare_EMD\\Debug\\handdd_out_sun.jpg")))
        return -4;
    //Mask为手掌掩码 过滤掉其他背景 只分析手掌颜色直方图 可略
    if (!(Imask = cvLoadImage("D:\\Template\\OpenCV\\Template53_hue-saturation_Compare_EMD\\Debug\\Imask1.jpg", 
        CV_LOAD_IMAGE_GRAYSCALE)))
        return -5;

    hsv1 = cvCreateImage(cvGetSize(src1), src1->depth, src1->nChannels);
    hsv2 = cvCreateImage(cvGetSize(src2), src2->depth, src2->nChannels);
    hsv3 = cvCreateImage(cvGetSize(src3), src3->depth, src3->nChannels);
    hsv4 = cvCreateImage(cvGetSize(src4), src4->depth, src4->nChannels);

    cvCvtColor(src1, hsv1, CV_BGR2HSV);     //源图像->HSV格式图像
    cvCvtColor(src2, hsv2, CV_BGR2HSV);     //源图像->HSV格式图像
    cvCvtColor(src3, hsv3, CV_BGR2HSV);     //源图像->HSV格式图像
    cvCvtColor(src4, hsv4, CV_BGR2HSV);     //源图像->HSV格式图像

    //色调(hue) 饱和度(saturation) 明度(value)
    IplImage *h_plane_1 = cvCreateImage(cvSize(hsv1->width, hsv1->height), IPL_DEPTH_8U, 1);
    IplImage *s_plane_1 = cvCreateImage(cvSize(hsv1->width, hsv1->height), IPL_DEPTH_8U, 1);
    IplImage *v_plane_1 = cvCreateImage(cvSize(hsv1->width, hsv1->height), IPL_DEPTH_8U, 1);

    IplImage *h_plane_2 = cvCreateImage(cvSize(hsv2->width, hsv2->height), IPL_DEPTH_8U, 1);
    IplImage *s_plane_2 = cvCreateImage(cvSize(hsv2->width, hsv2->height), IPL_DEPTH_8U, 1);
    IplImage *v_plane_2 = cvCreateImage(cvSize(hsv2->width, hsv2->height), IPL_DEPTH_8U, 1);

    IplImage *h_plane_3 = cvCreateImage(cvSize(hsv3->width, hsv3->height), IPL_DEPTH_8U, 1);
    IplImage *s_plane_3 = cvCreateImage(cvSize(hsv3->width, hsv3->height), IPL_DEPTH_8U, 1);
    IplImage *v_plane_3 = cvCreateImage(cvSize(hsv3->width, hsv3->height), IPL_DEPTH_8U, 1);

    IplImage *h_plane_4 = cvCreateImage(cvSize(hsv4->width, hsv4->height), IPL_DEPTH_8U, 1);
    IplImage *s_plane_4 = cvCreateImage(cvSize(hsv4->width, hsv4->height), IPL_DEPTH_8U, 1);
    IplImage *v_plane_4 = cvCreateImage(cvSize(hsv4->width, hsv4->height), IPL_DEPTH_8U, 1);

    IplImage *planes1[] = { h_plane_1, s_plane_1 };                     //色相饱和度数组
    IplImage *planes2[] = { h_plane_2, s_plane_2 };                     //色相饱和度数组
    IplImage *planes3[] = { h_plane_3, s_plane_3 };                     //色相饱和度数组
    IplImage *planes4[] = { h_plane_4, s_plane_4 };                     //色相饱和度数组

    cvCvtPixToPlane(hsv1, h_plane_1, s_plane_1, v_plane_1, NULL);       //图像分割
    cvCvtPixToPlane(hsv2, h_plane_2, s_plane_2, v_plane_2, NULL);       //图像分割
    cvCvtPixToPlane(hsv3, h_plane_3, s_plane_3, v_plane_3, NULL);       //图像分割
    cvCvtPixToPlane(hsv4, h_plane_4, s_plane_4, v_plane_4, NULL);       //图像分割
    //cvSplit(hsv, h_plane, s_plane, v_plane, NULL);

    //建立直方图
    CvHistogram *hist1, *hist2, *hist3, *hist4;

    int h_bins = 30, s_bins = 32;

    int hist_size[] = { h_bins, s_bins };   //对应维数包含bins个数的数组

    float h_ranges[] = { 0, 180 };              //H通道划分范围 饱和度0-180
    float s_ranges[] = { 0, 255 };              //S通道划分范围
    float* ranges[] = { h_ranges, s_ranges };   //划分范围数对, ****均匀bin,range只要最大最小边界
    //创建直方图 (维数,对应维数bins个数,密集矩阵方式存储,划分范围数对,均匀直方图)
    hist1 = cvCreateHist(2, hist_size, CV_HIST_ARRAY, ranges, 1);
    hist2 = cvCreateHist(2, hist_size, CV_HIST_ARRAY, ranges, 1);
    hist3 = cvCreateHist(2, hist_size, CV_HIST_ARRAY, ranges, 1);
    hist4 = cvCreateHist(2, hist_size, CV_HIST_ARRAY, ranges, 1);

    //创建直方图 (维数,对应维数bins个数,密集矩阵方式存储,划分范围数对,均匀直方图)
    cvCalcHist(planes1, hist1, 0, Imask);   //计算直方图(图像,直方图结构,不累加,mask仅采集手掌)
    cvCalcHist(planes2, hist2, 0, 0);       //计算直方图(图像,直方图结构,不累加,掩码)
    cvCalcHist(planes3, hist3, 0, 0);       //计算直方图(图像,直方图结构,不累加,掩码)
    cvCalcHist(planes4, hist4, 0, 0);       //计算直方图(图像,直方图结构,不累加,掩码)

    //cvNormalizeHist(hist1, 1.0);          //直方图归一化
    //cvNormalizeHist(hist2, 1.0);          // 归一化不可在此调用,后面要调用阈值化
    //cvNormalizeHist(hist3, 1.0);          
    //cvNormalizeHist(hist4, 1.0);          

    CvMat *sig1, *sig2, *sig3, *sig4;
    int numrows = h_bins*s_bins;

    sig1 = cvCreateMat(numrows, 3, CV_32FC1);   //numrows行 3列 矩阵
    sig2 = cvCreateMat(numrows, 3, CV_32FC1);
    sig3 = cvCreateMat(numrows, 3, CV_32FC1);   //numrows行 3列 矩阵
    sig4 = cvCreateMat(numrows, 3, CV_32FC1);

    for (int i = 0; i < 2; i++)
    {
        for (int h = 0; h < h_bins; h++)
        {
            for (int s = 0; s < s_bins; s++)
            {
                double bin_val = cvQueryHistValue_2D(hist1, h, s);
                //h:行数 s_bins:总列数(行长度)s:列数  h*s_bins+s 当前bin对应的sig行数   
                cvSet2D(sig1, h*s_bins + s, 0, cvScalar(bin_val));
                cvSet2D(sig1, h*s_bins + s, 1, cvScalar(h));
                cvSet2D(sig1, h*s_bins + s, 2, cvScalar(s));

                bin_val = cvQueryHistValue_2D(hist2, h, s);
                cvSet2D(sig2, h*s_bins + s, 0, cvScalar(bin_val));
                cvSet2D(sig2, h*s_bins + s, 1, cvScalar(h));
                cvSet2D(sig2, h*s_bins + s, 2, cvScalar(s));

                bin_val = cvQueryHistValue_2D(hist3, h, s);
                cvSet2D(sig3, h*s_bins + s, 0, cvScalar(bin_val));
                cvSet2D(sig3, h*s_bins + s, 1, cvScalar(h));
                cvSet2D(sig3, h*s_bins + s, 2, cvScalar(s));

                bin_val = cvQueryHistValue_2D(hist4, h, s);
                cvSet2D(sig4, h*s_bins + s, 0, cvScalar(bin_val));
                cvSet2D(sig4, h*s_bins + s, 1, cvScalar(h));
                cvSet2D(sig4, h*s_bins + s, 2, cvScalar(s));
            }
        }
        float emd1 = cvCalcEMD2(sig1, sig2, CV_DIST_L2);
        float emd2 = cvCalcEMD2(sig1, sig3, CV_DIST_L2);
        float emd3 = cvCalcEMD2(sig1, sig4, CV_DIST_L2);
        std::printf("Room EMD: %f; \n", emd1);
        std::printf("Outside EMD: %f; \n", emd2);
        std::printf("Outside_sun EMD: %f; \n", emd3);

        cvThreshHist(hist2, 87);        //距离阈值描述不明确,threshhold:87 EMD最小
        cvThreshHist(hist3, 87);
        cvThreshHist(hist4, 87);
        if (i==0)
            cout << endl << endl << "After Threshhold" << endl << endl;
    }

    cvNamedWindow("Model", 1);
    cvNamedWindow("Room", 1);
    cvNamedWindow("Outside", 1);
    cvNamedWindow("Outside_sun", 1);
    cvNamedWindow("IMASK", 1);

    cvShowImage("Model", src1);
    cvShowImage("Room", src2);
    cvShowImage("Outside", src3);
    cvShowImage("Outside_sun", src4);
    cvShowImage("IMASK", Imask);

    cvWaitKey(0);

    cvReleaseMat(&sig1);
    cvReleaseMat(&sig2);
    cvReleaseMat(&sig3);
    cvReleaseMat(&sig4);

    cvReleaseHist(&hist1);
    cvReleaseHist(&hist2);
    cvReleaseHist(&hist3);
    cvReleaseHist(&hist4);

    cvReleaseImage(&src1);
    cvReleaseImage(&src2);
    cvReleaseImage(&src3);
    cvReleaseImage(&Imask);
    cvReleaseImage(&hsv1);
    cvReleaseImage(&hsv2);
    cvReleaseImage(&hsv3);
    cvReleaseImage(&h_plane_1);
    cvReleaseImage(&s_plane_1);
    cvReleaseImage(&v_plane_1);
    cvReleaseImage(&h_plane_2);
    cvReleaseImage(&s_plane_2);
    cvReleaseImage(&v_plane_2);
    cvReleaseImage(&h_plane_3);
    cvReleaseImage(&s_plane_3);
    cvReleaseImage(&v_plane_3);

    cvDestroyAllWindows();
}

结果如下:
这里写图片描述
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值