Opencv2 computer vision application programming cookbook<三>

来源:互联网 发布:js删除video节点 编辑:程序博客网 时间:2024/06/06 03:09
第四章介绍关于图像直方图方面的知识,首先介绍了直方图的计算,cv::calcHist,并写出了自定义的直方图计算方法,然后介绍了LUT的应用,然后介绍了直方图拉伸与均衡cv::equalizeHist(image,result),累积直方图,接着介绍反向投影直方图检测特殊图像内容,接着讲利用均值漂移算法(mean shift algorithm)来发现目标,最后是利用直方图比较进行图像相似检索.
(以后的头文件就不贴上来了,需要的可以贴以前文章的.)
先给出LUT,strech,equalizeHist应用程序:
#include "stdafx.h"
#include<iostream>  
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc/imgproc.hpp>
#include<cv.h>
using namespace std;
using namespace cv;


class Histogram1D  
{  
private:  
      
    //直方图的点数  
    int histSize[1];  
    //直方图的范围  
    float hranges[2];  
    //指向该范围的指针  
    const float* ranges[1];  
    //通道  
    int channels[1];  
      
  
public:  
    //构造函数  
    Histogram1D()  
    {  
         histSize[0] = 256;  
         hranges[0] = 0.0;  
         hranges[1] = 255.0;  
         ranges[0] = hranges;  
         channels[0] = 0;   
    }  

Mat getHistogram(const Mat &image)  
{  
Mat hist;  
//计算直方图函数  
//参数为:源图像(序列)地址,输入图像的个数,通道数,掩码,输出结果,直方图维数,每一维的大小,每一维的取值范围  
calcHist(&image,1,channels,Mat(),hist,1,histSize,ranges);  
  
return hist;  
}  


Mat getHistogramImage(const Mat &image)  
{  
//首先计算直方图  
Mat hist = getHistogram(image);  
  
//获取最大值和最小值  
double maxVal = 0;  
double minVal = 0;  
//minMaxLoc用来获得最大值和最小值,后面两个参数为最小值和最大值的位置,0代表不需要获取  
minMaxLoc(hist,&minVal,&maxVal,0,0);  
//展示直方图的画板:底色为白色  
Mat histImg(histSize[0],histSize[0],CV_8U,Scalar(255));  
  
//将最高点设为bin总数的90%  
int hpt = static_cast<int>(0.9*histSize[0]);  
//为每一个bin画一条线  
for(int h = 0; h < histSize[0];h++)  
{  
float binVal = hist.at<float>(h);  
int intensity = static_cast<int>(binVal*hpt/maxVal);  
//int intensity = static_cast<int>(binVal);  
line(histImg,Point(h,histSize[0]),Point(h,histSize[0]-intensity),Scalar::all(0));  
          
}  
return histImg;  
}  


Mat equalize( Mat& image)
{
Mat equimage;
equalizeHist(image,equimage);
return equimage;
}



Mat applyLookUp(const Mat& image,const Mat& lookup)
{
Mat result;
LUT(image,lookup,result);
return result;
}




Mat strech(const Mat &image,int minValue = 0)  
{  
//首先计算直方图  
Mat hist = getHistogram(image);  
//左边入口  
int imin = 0;  
for(;imin< histSize[0];imin++)  
{  
cout<<hist.at<float>(imin)<<endl;  
if(hist.at<float>(imin) > minValue)  
break;  
  
}  
//右边入口  
int imax = histSize[0]-1;  
for(;imax >= 0; imax--)  
{  
if(hist.at<float>(imax) > minValue)  
break;  
}  
  
//创建查找表  
int dim(256);  
Mat lookup(1,&dim,CV_8U);  
      
for(int i = 0; i < 256; i++)  
{  
if(i < imin)  
{  
lookup.at<uchar>(i) = 0;  
}  
else if(i > imax)  
{  
lookup.at<uchar>(i) = 255;  
}  
else  
{  
lookup.at<uchar>(i) = static_cast<uchar>(255.0*(i-imin)/(imax-imin)+0.5);  
}  
}  
Mat result;  
result = applyLookUp(image,lookup);  
return result;    
}  


};


int main()  
{  
    ///以灰度方式读取图像  
    Mat image = imread("lena.bmp");  
    imshow("lena",image);  
    if (!image.data)  
        return -1; 


Mat result; 
float hranges[2];
    const float* ranges[3];
    int channels[3];


hranges[0]= 0.0;// range [0,255]
hranges[1]= 255.0;


ranges[0]= hranges; // all channels have the same range 
ranges[1]= hranges; 
ranges[2]= hranges; 



channels[0]= 0;// the three channels 
channels[1]= 1; 
channels[2]= 2; 


Mat imageROI;
imageROI=image(Rect(361,171,100,100));
imshow("lenaROI",imageROI);
    Histogram1D h;  
MatND hist=h.getHistogram(imageROI);


//imshow("hist",hist);
//归一化直方图
Mat nhist;
cv::normalize(hist,nhist,1.0);//,0.0,NORM_MINMAX);
    imshow("nhist",nhist);


//
calcBackProject(&image,1,channels,nhist,result,ranges,255);
imshow("reslut",result);
//二值化
//float thresh=-1.0f; 
//threshold(result,result,thresh,255,THRESH_BINARY);


//应用OPENCV的直方图均衡化
Mat src;
cvtColor(image,src,CV_BGR2GRAY);
Mat equalizeImage;
//直方图均衡化要求图像为单通道灰度图像
equalizeHist(src,equalizeImage);
imshow("equalizeImage",equalizeImage);


//单通道的反向投影
int channelst[1];
channelst[0]=0;
const float* rangest[1];
rangest[0]=hranges;
Mat resultOneChannel;
calcBackProject(&src,1,channelst,nhist,resultOneChannel,rangest,255);
imshow("reslutt",resultOneChannel);
waitKey();
return 0;
}  


反向投影用于检测图像中特殊的图像内容.先定义需要检测的ROI,然后直方图归一化,反向投影,再阈值,就能判断图像中是否有目标物体.反向投影直方图就是用ROI归一化直方图中对应的概率值取代输入图像中的每一个像素值.
int _tmain(int argc, _TCHAR* argv[])
{
//以灰度方式读取图像  
    Mat image = imread("lena.bmp");  
    imshow("lena",image);  
    if (!image.data)  
        return -1; 


Mat result; 
float hranges[2];
    const float* ranges[3];
    int channels[3];


hranges[0]= 0.0;// range [0,255]
hranges[1]= 255.0;


ranges[0]= hranges; // all channels have the same range 
ranges[1]= hranges; 
ranges[2]= hranges; 



channels[0]= 0;// the three channels 
channels[1]= 1; 
channels[2]= 2; 


Mat imageROI;
imageROI=image(Rect(361,171,100,100));
imshow("lenaROI",imageROI);
    Histogram1D h;  
MatND hist=h.getHistogram(imageROI);


//imshow("hist",hist);
//归一化直方图
Mat nhist;
cv::normalize(hist,nhist,1.0);//,0.0,NORM_MINMAX);
    imshow("nhist",nhist);


//
calcBackProject(&image,1,channels,nhist,result,ranges,255);
imshow("reslut",result);
//二值化
//float thresh=-1.0f; 
//threshold(result,result,thresh,255,THRESH_BINARY);


//应用OPENCV的直方图均衡化
Mat src;
cvtColor(image,src,CV_BGR2GRAY);
Mat equalizeImage;
//直方图均衡化要求图像为单通道灰度图像
equalizeHist(src,equalizeImage);
imshow("equalizeImage",equalizeImage);


//单通道的反向投影
int channelst[1];
channelst[0]=0;
const float* rangest[1];
rangest[0]=hranges;
Mat resultOneChannel;
calcBackProject(&src,1,channelst,nhist,resultOneChannel,rangest,255);
imshow("reslutt",resultOneChannel);
waitKey();
return 0;
}

为了提高检测结果,可用彩色信息或者HSV彩色空间进行反向投影.

利用直方图完成基于图像内容的检索

呵呵,最后两个程序没有实现

0 0
原创粉丝点击