您现在的位置:首页 > 教案格式 > 正文

第七章 学习OpenCV(5)

2019-07-04 21:05 网络整理 教案网

envi直方图匹配_匹配滤波原理_直方图匹配原理

运行结果如下图:

不同光照手部图像

直方图匹配结果

与上例一样,收集手的肤色直方图。以其中的一个室内直方图样本作为模型直方图匹配原理,并计算其与另一个室内直方图、一个室外阴影直方图、一个室外光照直方图的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();
}