zoukankan      html  css  js  c++  java
  • 直方图与匹配

    灰度直方图是灰度级的函数,描述的是图像中具有该灰度级的像素的个数:其横坐标是灰度级,纵坐标是该灰度出现的频率(像素的个数)。

    在opencv中可以通过cvCreateHist()来生成直方图

    CvHistogram* cvCreateHist(
        int dims,       
        int* sizes,   
        int type,    
        float** ranges=NULL, 
        int uniform=1  
        )
        dims   
        //直方图包含的维数
        sizes 
        //数组的长度等于dims,数组中每个整数表示分配给对应维数的的bin的个数
        type  
        //表示存储类型,CV_HIST_ARRAy表示用密集多维矩阵结构存储直方图,CV_HIST_SPARSE表示数据已稀疏矩阵方式存储
        ranges=NULL, 
        //浮点数对的构成的数组,每个浮点数对表示对应维数的bin的区间的上下界
        uniform=1  
        //非0表示均匀直方图,为NULL表示未知,即在后面可以设置。CvHistogram* cvCreateHist(
      
    

    使用cvCalcHist()函数来计算直方图

    void cvCalcHist(
    	IplImage** image,
    	CvHistogram* hist,
    	int accmulate=0,
    	const CvArr* mask=NULL
    	)
    	image  //是一个指向数组的IplImage*类型的指针,着允许利用多个图像通道
    	hist   //要计算的直方图
    	accmulate //非0时,表示直方图hist在读入图像之前没有被清零
    	mask //如果为非NULL,则只有与mask非零元素对应的像素点会被包含在计算直方图中。

    1.单通道图像的直方图

    #include "stdafx.h"
    #include <highgui.h>
    #include <math.h>
    #include <cv.h>
    int main()
    {
    	IplImage* sourceImage=0;
    	
    	//以单通道读入图像
    	if(!(sourceImage=cvLoadImage("YAYA.jpg",0)))
    		return -1;
    
    	int hdims=51;      //分配给对应维数的bin的个数
    	float rangesArray[]={0,255};
    	float* ranges[]={rangesArray};
    	float maxValue;
    	
    	CvHistogram* histogram=0;
    	histogram=cvCreateHist(1,&hdims,CV_HIST_ARRAY,ranges,1);
    	
    	IplImage* histImage;      //用来显示直方图
    	histImage=cvCreateImage(cvGetSize(sourceImage),8,3);
    	cvZero(histImage);
    	
    	//计算直方图
    	cvCalcHist(&sourceImage,histogram,0,0);
    	
    	//获取最大值
    	cvGetMinMaxHistValue(histogram,0,&maxValue,0,0);
    	
    	cvConvertScale(histogram->bins,histogram->bins,maxValue?255./maxValue:0,0);
    	
    	float binsWidth;
    	binsWidth=histImage->width/hdims;
    	CvScalar color=CV_RGB(255,255,255);
    	for(int i=0;i<hdims;i++)
    	{
    		double value=(cvGetReal1D(histogram->bins,i)*histImage->height/255);
    		cvRectangle(histImage,cvPoint(i*binsWidth,histImage->height),cvPoint((i+1)*binsWidth,(int)(histImage->height-value)),color,1,8,0);
    	}
    	//显示	
    	cvNamedWindow("sourceImage",0);
    	cvNamedWindow("histImage",0);
    	cvShowImage("sourceImage",sourceImage);
    	cvShowImage("histImage",histImage);
    	//释放资源
    	cvDestroyAllWindows();
    	cvReleaseImage(&sourceImage);
    	cvReleaseImage(&histImage);
    	cvReleaseHist(&histogram);
    
    	cvWaitKey(-1);
    		return 0;
    }

    运行结果:


    多通道图像的直方图

    因为ccCalHist()只接受单通道图像,所以在调用cvCalcHist()之前,首先用cvSplit()将多通道图像分解为单通道图像。

    #include "stdafx.h"
    #include <highgui.h>
    #include <math.h>
    #include <cv.h>
    int main()
    {
        IplImage* sourceImage=0;
        if(!(sourceImage=cvLoadImage("YAYA.jpg",1)))
            return -1;
    
        IplImage* hsvImage=cvCreateImage(cvGetSize(sourceImage),8,3);
        cvCvtColor(sourceImage,hsvImage,CV_BGR2HSV);
        IplImage* h_plane=cvCreateImage(cvGetSize(sourceImage),8,1);
        IplImage* s_plane=cvCreateImage(cvGetSize(sourceImage),8,1);
        IplImage* v_plane=cvCreateImage(cvGetSize(sourceImage),8,1);
        cvSplit(hsvImage,h_plane,s_plane,v_plane,0);
        
        int h_bins=30,s_bins=32;
        CvHistogram* histogram;
        {
            int hist_size[]={h_bins,s_bins};
            float h_ranges[]={0,180};
            float s_ranges[]={0,255};
            float* ranges[]={h_ranges,s_ranges};
            histogram=cvCreateHist(
                2,
                hist_size,
                CV_HIST_ARRAY,
                ranges,
                1
                );
        }
        IplImage* planes[]={h_plane,s_plane};
        cvCalcHist(planes,histogram,0,0);
        cvNormalizeHist(histogram,1.0);
        int scale=10;
        IplImage* histImage=cvCreateImage(
            cvSize(h_bins*scale,s_bins*scale),8,3);
        cvZero(histImage);
    
        float maxValue;
        cvGetMinMaxHistValue(histogram,0,&maxValue,0,0);
        
        for(int h=0;h<h_bins;h++)
            for(int s=0;s<s_bins;s++)
            {
                float binValue=cvQueryHistValue_2D(histogram,h,s);
                int intensity=cvRound(binValue*255./maxValue);
                cvRectangle(
                    histImage,
                    cvPoint(h*scale,s*scale),
                    cvPoint((h+1)*scale-1,(s+1)*scale-1),
                    CV_RGB(intensity,intensity,intensity),
                    CV_FILLED
                    );
            }
    
            cvNamedWindow("hsvImage",1);
            cvNamedWindow("histImage",1);
    
            cvShowImage("hsvImage",hsvImage);
            cvShowImage("histImage",histImage);
            cvWaitKey(-1);
            cvDestroyAllWindows();
            cvReleaseImage(&sourceImage);
            cvReleaseImage(&histImage);
            cvReleaseHist(&histogram);
            return 0;
    }

    运行结果:


    直方图的相似度

    计算直方图相似度的函数如下:

    double cvCompareHist(
    	const CvHistogram* hist1,
    	const CvHistogram* hist2,
    	int method;           //距离标准
    )

    method的取值有:

    CV_COMP_CORREL     完全匹配为1,完全不匹配为-1,数值越大越匹配

    CV_COMP_CHISQR      低分比高分匹配的程度高,完全匹配的值为0,完全不匹配为无限值

    CV_COMP_INTERSECT   高分表示好匹配,低分表示坏匹配

    CV_COMP_BHATTACHARYYA     低分表示好匹配,高分表示换匹配。完全匹配为0,完全不匹配为0.

    #include "stdafx.h"
    #include <highgui.h>
    #include <math.h>
    #include <cv.h>
    using namespace std;
    //对比两个直方图的相似度
    int main()
    {
        IplImage* templateImage=cvLoadImage("YAYA.jpg");
        if(!templateImage)
            return -1;
        IplImage* grayImage=cvCreateImage(cvGetSize(templateImage),8,1);
        cvCvtColor(templateImage,grayImage,CV_BGR2GRAY);
        //首先加载图片,然后将图片变为灰度图
        
        int hist_size=51;
        float range[]={0,255};
        float* ranges[]={range};
    
        CvHistogram* histogram;
        histogram=cvCreateHist(
            1,
            &hist_size,      //size  元素为对应bin的个数
            CV_HIST_ARRAY,
            ranges,
            1
            );
        cvCalcHist(&grayImage,histogram,0,0);
    
        IplImage* compareImage=cvLoadImage("YAYA2.jpg");
        if(!compareImage)
            return -1;
        IplImage* compareGrayImage=cvCreateImage(cvGetSize(compareImage),8,1);
        cvCvtColor(compareImage,compareGrayImage,CV_BGR2GRAY);
        //首先加载图片,然后将图片变为灰度图
        
        CvHistogram* compareHistogram;
        compareHistogram=cvCreateHist(
            1,
            &hist_size,
            CV_HIST_ARRAY,
            ranges,
            1
            );
        cvCalcHist(&compareGrayImage,compareHistogram,0,0);
    
        //对直方图进行归一化操作
        cvNormalizeHist(histogram,1);
        cvNormalizeHist(compareHistogram,1);
        //计算匹配系数
        double degree=cvCompareHist(histogram,compareHistogram,
            CV_COMP_CHISQR);
        cout<<degree<<endl;
        cvWaitKey(10000000);
        cvDestroyAllWindows();
        cvReleaseImage(&templateImage);
        cvReleaseImage(&grayImage);
        cvReleaseImage(&compareImage);
        cvReleaseImage(&compareGrayImage);
        cvReleaseHist(&compareHistogram);
        cvReleaseHist(&histogram);
        return 0;
    }
    

    Reference

    《学习opencv》

  • 相关阅读:
    android布局
    Windows7 32/64位系统搭建Cocos2d-x及Android交叉编译环境
    第12章 文件管理
    第十章 多处理器和实时调度
    C语言实现多级反馈队列调度算法
    C++实现操作系统调度算法(FSFS,SJF,RR,多级反馈队列算法)
    多级反馈队列调度算法
    第九章 单处理器调度
    第六章 并发:死锁与饥饿
    第七章 内存管理
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3162971.html
Copyright © 2011-2022 走看看