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

第七章 学习OpenCV(4)

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

运行结果如下图:

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

基于块的反向投影

读入一个模板和要匹配的图像,然后分别利用6种方法进行匹配,规范化后将匹配结果显示出来,具体代码如下:

#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* src, *temp1, *result[6];  
    //杯子源图像
    if (!(src = cvLoadImage("D:\\Template\\OpenCV\\Template50_Match_Template\\Debug\\cup1.jpg")))
        return -1;
    //用于匹配的杯子模板图像
    if (!(temp1 = cvLoadImage("D:\\Template\\OpenCV\\Template50_Match_Template\\Debug\\cup2.jpg")))
        return -2;
    //结果图像尺寸
    int result_width = src->width - temp1->width + 1;
    int result_height = src->height - temp1->height + 1;;
    CvSize result_size = cvSize(result_width, result_height);
    //创建结果图像
    for (int i = 0; i < 6; ++i)
    {
        printf("i=%d\n", i);
        result[i] = cvCreateImage(result_size, IPL_DEPTH_32F, 1);
    }
    //均衡化图像
    for (int i = 0; i < 6; i++)
    {
        printf("i=%d\n", i);
        cvMatchTemplate(src, temp1, result[i], i);              //模板匹配
        cvNormalize(result[i], result[i], 1, 0, CV_MINMAX);     //元素规范化 平移缩放返回值[0,1]
    }
    cvNamedWindow("Src", 1);
    cvNamedWindow("Template", 1);
    cvNamedWindow("SQDIFF", 1);
    cvNamedWindow("CCORR", 1);
    cvNamedWindow("CCOEFF", 1);
    cvNamedWindow("SQDIFF_NORMED", 1);
    cvNamedWindow("CCORR_NORMED", 1);
    cvNamedWindow("CCOEFF_NORMED", 1);
    cvShowImage("Src", src);
    cvShowImage("Template", temp1);
    cvShowImage("SQDIFF", result[0]);
    cvShowImage("SQDIFF_NORMED", result[1]);
    cvShowImage("CCORR", result[2]);
    cvShowImage("CCORR_NORMED", result[3]);
    cvShowImage("CCOEFF", result[4]);
    cvShowImage("CCOEFF_NORMED", result[5]);
    cvWaitKey(0);
    //system("pause");
    cvReleaseImage(&src);
    cvReleaseImage(&temp1);
    cvReleaseImage(&result[0]);
    cvReleaseImage(&result[1]);
    cvReleaseImage(&result[2]);
    cvReleaseImage(&result[3]);
    cvReleaseImage(&result[4]);
    cvReleaseImage(&result[5]);
    cvDestroyAllWindows();
}

运行结果如下图:

模板匹配

注意:本程序中,打印了两次i的值,分别对应for循环中的“++i”“i++”,打印结果相同,并不代表“++i”“i++”没有区别,而是因为for循环中表达式是作为一个语句来执行,因此此处i均是其最终的值。

在0~1之间生成1000个随机值ri,定义一个bin的大小,并且建立一个直方图1/ri,,具体代码如下:

#include <cv.h>
#include <highgui.h>  
#include <stdlib.h>  
#include <stdio.h> 
#include <math.h>
using namespace std;
int main(int argc, char* argv[])
{
    //产生1000个随机数
    CvRNG rng;
    IplImage *Img = cvCreateImage(cvSize(1000,1),32,1); //数据图像
    cvSetZero(Img);     //清零
    rng = cvRNG(cvGetTickCount());                  //64位长整数的时间数据作为种子
    for (int i = 0; i<1000; i++)
    {
        double value;   //获取的随机值
        cvSetReal1D(Img, i, cvRandReal(&rng));      //返回均匀分布,0~1之间的随机小数
        value = cvGetReal1D(Img, i);                //返回图像中小数值
        //printf("%d\n", cvRandInt(&rng) % 6);      //返回均匀分布32位的随机数,%6将会是0~255的正整数
        printf("%.2lf\n", value);                   //打印
    }
    printf("Tick Frequency= %f\n", cvGetTickFrequency());   //系统时钟频率
    system("pause");                    
    //建立直方图
    CvHistogram *hist;
    int dims = 1;       //维数
    int bins = 1000;    //bins个数        
    int hist_size[] = { bins };     //对应维数包含bins个数的数组
    float range[] = { 0, 1 };       //划分范围[0,1]
    float* ranges[] = { range };    //划分范围数对, ****均匀bin,range只要最大最小边界
    //创建直方图 (维数,对应维数bins个数,密集矩阵方式存储,划分范围数对,均匀直方图)
    hist = cvCreateHist(dims, hist_size, CV_HIST_ARRAY, ranges, 1);
    IplImage *img[] = { Img };      //计算直方图的图像数组
    cvCalcHist(img, hist, 0, 0);    //计算直方图
    for (int j = 0; j < bins; j++)
    {
        float bin_val = cvQueryHistValue_1D(hist,j);    //获取直方图相应bin中的浮点数
        cout << "the bins of " << j << ":" << bin_val << endl;
    }
    system("pause");
    cvWaitKey(0);
    cvReleaseHist(&hist);
    cvReleaseImage(&Img);
}

运行结果如下图:

随机数

直方图bin中值

对于同一幅场景,我们按波长从小到大依次用每一个区间波长的光去拍摄图像,将得到2500~400/n幅图像,这组图像作为整体被称作高光谱图像。当空间三维场景被投影为二维图像时,同一景物在不同视点下的图像会有很大不同,而且场景中的诸多因素,如光照条件、景物几何形状和物理特性、噪声干扰和畸变以及摄像机特性等,都被综合成单一的图像灰度值。0都难以胜任室内抓拍(夜晚室内60w光照条件,布键不错。

 1. 依次尝试用少量的bin(如每维有2个),中等数目的bin(每维有16个)和很多bin(每维256个),然后对各种光线下的图像运行匹配程序(使用所有的直方图匹配方法);
 2. 现在加上每维为8个和32个bin,在各种光线条件下进行匹配;

程序中三幅图像已经过处理,依次比前一幅亮度增加40,具体代码如下:

#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,*Imask, *hsv1, *hsv2,*hsv3;                //源图像 HSV格式图像
    //src1 src2 亮度较前一张增加了10 src2 src3 亮度较前一张增加了40
    if (!(src1 = cvLoadImage("D:\\Template\\OpenCV\\Template52_hue-saturation_Compare\\Debug\\hand1.jpg")))
        return -1;
    if (!(src2 = cvLoadImage("D:\\Template\\OpenCV\\Template52_hue-saturation_Compare\\Debug\\hand3.jpg")))
        return -2;
    if (!(src3 = cvLoadImage("D:\\Template\\OpenCV\\Template52_hue-saturation_Compare\\Debug\\hand5.jpg")))
        return -3;
    //Mask为手掌掩码 过滤掉其他背景 只分析手掌颜色直方图 可略
    if (!(Imask = cvLoadImage("D:\\Template\\OpenCV\\Template52_hue-saturation_Compare\\Debug\\Imask.jpg", 
        CV_LOAD_IMAGE_GRAYSCALE)))
        return -4;
    hsv1 = cvCreateImage(cvGetSize(src1), src1->depth, src1->nChannels);
    hsv2 = cvCreateImage(cvGetSize(src2), src2->depth, src2->nChannels);
    hsv3 = cvCreateImage(cvGetSize(src3), src3->depth, src3->nChannels);
    cvCvtColor(src1, hsv1, CV_BGR2HSV);     //源图像->HSV格式图像
    cvCvtColor(src2, hsv2, CV_BGR2HSV);     //源图像->HSV格式图像
    cvCvtColor(src3, hsv3, 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 *planes1[] = { h_plane_1, s_plane_1 };                     //色相饱和度数组
    IplImage *planes2[] = { h_plane_2, s_plane_2 };                     //色相饱和度数组
    IplImage *planes3[] = { h_plane_3, s_plane_3 };                     //色相饱和度数组
    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);       //图像分割
    //cvSplit(hsv, h_plane, s_plane, v_plane, NULL);
    for (int i = 0; i < 5; i++)
    {
        //建立直方图
        CvHistogram *hist1, *hist2, *hist3;
        int bins=0;
        int h_bins_1 = 2, s_bins_1 = 2;
        int h_bins_2 = 8, s_bins_2 = 8;
        int h_bins_3 = 16, s_bins_3 = 16;
        int h_bins_4 = 32, s_bins_4 = 32;
        int h_bins_5 = 256, s_bins_5 = 256;
        int hist_size_1[] = { h_bins_1, s_bins_1 }; //对应维数包含bins个数的数组
        int hist_size_2[] = { h_bins_2, s_bins_2 }; //对应维数包含bins个数的数组
        int hist_size_3[] = { h_bins_3, s_bins_3 }; //对应维数包含bins个数的数组
        int hist_size_4[] = { h_bins_4, s_bins_4 }; //对应维数包含bins个数的数组
        int hist_size_5[] = { h_bins_5, s_bins_5 }; //对应维数包含bins个数的数组
        float h_ranges[] = { 0, 180 };              //H通道划分范围 饱和度0-180
        float s_ranges[] = { 0, 255 };              //S通道划分范围
        float* ranges[] = { h_ranges, s_ranges };   //划分范围数对, 均匀bin,range只要最大最小边界
        //bins 2*2
        if (i == 0)
        {
            hist1 = cvCreateHist(2, hist_size_1, CV_HIST_ARRAY, ranges, 1);
            hist2 = cvCreateHist(2, hist_size_1, CV_HIST_ARRAY, ranges, 1);
            hist3 = cvCreateHist(2, hist_size_1, CV_HIST_ARRAY, ranges, 1);
            bins = h_bins_1;
        }
        //bins 8*8
        if (i == 1)
        {
            hist1 = cvCreateHist(2, hist_size_2, CV_HIST_ARRAY, ranges, 1);
            hist2 = cvCreateHist(2, hist_size_2, CV_HIST_ARRAY, ranges, 1);
            hist3 = cvCreateHist(2, hist_size_2, CV_HIST_ARRAY, ranges, 1);
            bins = h_bins_2;
        }
        //bins 16*16
        if (i == 2)
        {
            hist1 = cvCreateHist(2, hist_size_3, CV_HIST_ARRAY, ranges, 1);
            hist2 = cvCreateHist(2, hist_size_3, CV_HIST_ARRAY, ranges, 1);
            hist3 = cvCreateHist(2, hist_size_3, CV_HIST_ARRAY, ranges, 1);
            bins = h_bins_3;
        }
        //bins 32*32
        if (i == 3)
        {
            hist1 = cvCreateHist(2, hist_size_4, CV_HIST_ARRAY, ranges, 1);
            hist2 = cvCreateHist(2, hist_size_4, CV_HIST_ARRAY, ranges, 1);
            hist3 = cvCreateHist(2, hist_size_4, CV_HIST_ARRAY, ranges, 1);
            bins = h_bins_4;
        }
        //bins 256*256
        if (i == 4)
        {
            hist1 = cvCreateHist(2, hist_size_5, CV_HIST_ARRAY, ranges, 1);
            hist2 = cvCreateHist(2, hist_size_5, CV_HIST_ARRAY, ranges, 1);
            hist3 = cvCreateHist(2, hist_size_5, CV_HIST_ARRAY, ranges, 1);
            bins = h_bins_5;
        }
        //创建直方图 (维数,对应维数bins个数,密集矩阵方式存储,划分范围数对,均匀直方图)
        cvCalcHist(planes1, hist1, 0, 0);       //计算直方图(图像,直方图结构,不累加,掩码)
        cvCalcHist(planes2, hist2, 0, 0);       //计算直方图(图像,直方图结构,不累加,掩码)
        cvCalcHist(planes3, hist3, 0, 0);       //计算直方图(图像,直方图结构,不累加,掩码)
        //cvCalcHist(planes1, hist1, 0, Imask);     //计算直方图(图像,直方图结构,不累加,掩码)
        //cvCalcHist(planes2, hist2, 0, Imask);     //计算直方图(图像,直方图结构,不累加,掩码)
        //cvCalcHist(planes3, hist3, 0, Imask);     //计算直方图(图像,直方图结构,不累加,掩码)
        cvNormalizeHist(hist1, 1.0);            //直方图归一化
        cvNormalizeHist(hist2, 1.0);            //直方图归一化
        cvNormalizeHist(hist3, 1.0);            //直方图归一化
        //比较直方图
        for (int j = 0; j < 4; j++)
        {
            double value1 = cvCompareHist(hist1, hist2, j);         //相关方式比较
            double value2 = cvCompareHist(hist1, hist3, j);         //相关方式比较
                if (j == 0)
                {
                    printf("Bins:%d*%d ,Hist1 & Hist2 ,CORREL: %lf;\n", bins, bins, value1);
                    printf("Bins:%d*%d ,Hist1 & Hist3 ,CORREL: %lf;\n", bins, bins, value2);
                }
                if (j == 1)
                {
                    printf("Bins:%d*%d ,Hist1 & Hist2 ,CHISQR: %lf;\n", bins, bins, value1);
                    printf("Bins:%d*%d ,Hist1 & Hist3 ,CHISQR: %lf;\n", bins, bins, value2);
                }
                if (j == 2)
                {
                    printf("Bins:%d*%d ,Hist1 & Hist2 ,INTERSECT: %lf;\n", bins, bins, value1);
                    printf("Bins:%d*%d ,Hist1 & Hist3 ,INTERSECT: %lf;\n", bins, bins, value2);
                }
                if (j == 3)
                {
                    printf("Bins:%d*%d ,Hist1 & Hist2 ,BHATTACHARYYA: %lf;\n", bins, bins, value1);
                    printf("Bins:%d*%d ,Hist1 & Hist3 ,BHATTACHARYYA: %lf;\n", bins, bins, value2);
                }   
        }
        cvReleaseHist(&hist1);
        cvReleaseHist(&hist2);
        cvReleaseHist(&hist3);
        cout << endl;
    }
    cvNamedWindow("SRC1", 1);
    cvNamedWindow("SRC2", 1);
    cvNamedWindow("SRC3", 1);
    cvNamedWindow("IMASK", 1);
    cvShowImage("SRC1", src1);
    cvShowImage("SRC2", src2);
    cvShowImage("SRC3", src3);
    cvShowImage("IMASK", Imask);
    cvWaitKey(0);
    system("pause");
    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();
}