标签:
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
#include "Histogram1D.h"
#include <iostream>
#include <vector>
#include "ContentFinder.h"
#include "colorhistogram.h"
int main()
{
//读取參考图像
cv::Mat image= cv::imread("f:\\img\\ball.jpg");
if (!image.data)
return 0;
//定义查找物体
cv::Mat imageROI= image(cv::Rect(85,200,64,64));
cv::rectangle(image, cv::Rect(85,200,64,64),cv::Scalar(0,0,255));
//显示參考图像
cv::namedWindow("第一张图片,标记篮球位置");
cv::imshow("第一张图片,标记篮球位置",image);
//获得色度直方图
ColorHistogram hc;
cv::MatND colorhist= hc.getHueHistogram(imageROI);
//读入目标图像
image= cv::imread("f:\\img\\ball2.jpg");
//显示目标图像
cv::namedWindow("第二张图片");
cv::imshow("第二张图片",image);
//将RGB图像图像转换为HSV图像
cv::Mat hsv;
cv::cvtColor(image, hsv, CV_BGR2HSV);
//分离图像通道
vector<cv::Mat> v;
cv::split(hsv,v);
//消除饱和度较低的像素点
int minSat=65;
cv::threshold(v[1],v[1],minSat,255,cv::THRESH_BINARY);
cv::namedWindow("第二张图片消除饱和度较低的像素点");
cv::imshow("第二张图片消除饱和度较低的像素点",v[1]);
//进行直方图反投影
ContentFinder finder;
finder.setHistogram(colorhist);
finder.setThreshold(0.3f);
int ch[1]={0};
cv::Mat result= finder.find(hsv,0.0f,180.0f,ch,1);
cv::namedWindow("第二张图片进行直方图反投影");
cv::imshow("第二张图片进行直方图反投影",result);
//利用位运算消除低饱和度像素
cv::bitwise_and(result,v[1],result);
cv::namedWindow("第二张图片利用位运算进一步消除低饱和度像素点");
cv::imshow("第二张图片利用位运算进一步消除低饱和度像素点",result);
// 得到反投影直方图概率图像
finder.setThreshold(-1.0f);
result= finder.find(hsv,0.0f,180.0f,ch,1);
cv::bitwise_and(result,v[1],result);
cv::namedWindow("第二张图片处理后的二值图像");
cv::imshow("第二张图片处理后的二值图像",result);
cv::Rect rect(85,200,64,64);
cv::rectangle(image, rect, cv::Scalar(0,0,255));
cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER,10,0.01);
cout << "均值漂移迭代次数 = " << cv::meanShift(result,rect,criteria) << endl;
cv::rectangle(image, rect, cv::Scalar(0,255,0));
//展示结果图
cv::namedWindow("查找结果,红框为第一幅图中篮球位置,绿框为现位置");
cv::imshow("查找结果,红框为第一幅图中篮球位置,绿框为现位置",image);
cv::waitKey();
return 0;
} #if!defined CONTENTFINDER
#define CONTENTFINDER
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
class ContentFinder
{
private:
float hranges[2];
const float* ranges[3];
int channels[3];
float threshold;
Mat histogram;
public:
ContentFinder():threshold(-1.0f)
{
//所有通道的范围相同
ranges[0] = hranges;
ranges[1] = hranges;
ranges[2] = hranges;
}
//设置门限参数[0,1]
void setThreshold(float t)
{
threshold = t;
}
//获取门限参数
float getThreshold()
{
return threshold;
}
//设置参考的直方图
void setHistogram(const Mat& h)
{
histogram = h;
normalize(histogram,histogram,1.0);
}
//简单的利用反向投影直方图寻找
Mat find(const Mat& image)
{
Mat result;
hranges[0] = 0.0;
hranges[1] = 255.0;
channels[0] = 0;
channels[1] = 1;
channels[2] = 2;
calcBackProject(&image,1,channels,histogram,result,ranges,255.0);
if (threshold>0.0)
{
cv::threshold(result, result, 255*threshold, 255, cv::THRESH_BINARY);
}
return result;
}
//复杂的利用反向投影直方图,增加了一些参数
Mat find(const Mat &image,float minValue,float maxValue,int *channels,int dim)
{
Mat result;
hranges[0] = minValue;
hranges[1] = maxValue;
for(int i = 0;i < dim;i++)
{
this->channels[i] = channels[i];
}
calcBackProject(&image,1,channels,histogram,result,ranges,255.0);
if(threshold >0.0)
cv::threshold(result,result, 255*threshold,255,THRESH_BINARY);
return result;
}
};
#endif #if!defined COLORHISTOGRAM
#define COLORHISTOGRAM
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
class ColorHistogram
{
private:
int histSize[3];
float hranges[2];
const float* ranges[3];
int channels[3];
public:
//构造函数
ColorHistogram()
{
histSize[0]= histSize[1]= histSize[2]= 256;
hranges[0] = 0.0;
hranges[1] = 255.0;
ranges[0] = hranges;
ranges[1] = hranges;
ranges[2] = hranges;
channels[0] = 0;
channels[1] = 1;
channels[2] = 2;
}
//计算彩色图像直方图
Mat getHistogram(const Mat& image)
{
Mat hist;
//BGR直方图
hranges[0]= 0.0;
hranges[1]= 255.0;
channels[0]= 0;
channels[1]= 1;
channels[2]= 2;
//计算
calcHist(&image,1,channels,Mat(),hist,3,histSize,ranges);
return hist;
}
//计算颜色的直方图
Mat getHueHistogram(const Mat &image)
{
Mat hist;
Mat hue;
//转换到HSV空间
cvtColor(image,hue,CV_BGR2HSV);
//设置1维直方图使用的参数
hranges[0] = 0.0;
hranges[1] = 180.0;
channels[0] = 0;
//计算直方图
calcHist(&hue,1,channels,Mat(),hist,1,histSize,ranges);
return hist;
}
//减少颜色
Mat colorReduce(const Mat &image,int div = 64)
{
int n = static_cast<int>(log(static_cast<double>(div))/log(2.0));
uchar mask = 0xFF<<n;
Mat_<Vec3b>::const_iterator it = image.begin<Vec3b>();
Mat_<Vec3b>::const_iterator itend = image.end<Vec3b>();
//设置输出图像
Mat result(image.rows,image.cols,image.type());
Mat_<Vec3b>::iterator itr = result.begin<Vec3b>();
for(;it != itend;++it,++itr)
{
(*itr)[0] = ((*it)[0]&mask) + div/2;
(*itr)[1] = ((*it)[1]&mask) + div/2;
(*itr)[2] = ((*it)[2]&mask) + div/2;
}
return result;
}
};
#endif #if !defined HISTOGRAM
#define HISTOGRAM
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
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);
//这个函数虽然有很多参数,但是大多数时候,只会用于灰度图像或者彩色图像
//但是,允许通过指明一个多通道图像使用多幅图像
//第6个参数指明了直方图的维数
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]);
int hpt = static_cast<int>(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 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;
}
Mat equalize(const Mat &image)
{
Mat result;
equalizeHist(image,result);
return result;
}
};
#endifCompareHist(),是比较两个统计直方图的分布,总共有四个方法,被定义如下:
#define
CV_COMP_CORREL 0
#define CV_COMP_CHISQR 1
#define CV_COMP_INTERSECT2
#define CV_COMP_BHATTACHARYYA3
而这些方法分别为相关系数,卡方,交集法以及在做常态分布比对的Bhattacharyya距离,这些方法都是用来做统计直方图的相似度比较的方法,而且,都是根据统计学的概念,这边就简单的拿来用灰阶统计直方图来比较,而这部份的比较方式,是由图形的色彩结构来着手,下面就简单的用三种情况来分析它们距离比较的方式
#include "opencv2/highgui/highgui.hpp"
#include "opencv/cv.hpp"
//画直方图用
int HistogramBins = 256;
float HistogramRange1[2]={0,255};
float *HistogramRange[1]={&HistogramRange1[0]};
/*
* imagefile1:
* imagefile2:
* method: could be CV_COMP_CHISQR, CV_COMP_BHATTACHARYYA, CV_COMP_CORREL, CV_COMP_INTERSECT
*/
int CompareHist(const char* imagefile1, const char* imagefile2)
{
IplImage *image1=cvLoadImage(imagefile1, 0);
IplImage *image2=cvLoadImage(imagefile2, 0);
CvHistogram *Histogram1 = cvCreateHist(1, &HistogramBins, CV_HIST_ARRAY,HistogramRange);
CvHistogram *Histogram2 = cvCreateHist(1, &HistogramBins, CV_HIST_ARRAY,HistogramRange);
cvCalcHist(&image1, Histogram1);
cvCalcHist(&image2, Histogram2);
cvNormalizeHist(Histogram1, 1);
cvNormalizeHist(Histogram2, 1);
// CV_COMP_CHISQR,CV_COMP_BHATTACHARYYA这两种都可以用来做直方图的比较,值越小,说明图形越相似
printf("CV_COMP_CHISQR : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_CHISQR));
printf("CV_COMP_BHATTACHARYYA : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_BHATTACHARYYA));
// CV_COMP_CORREL, CV_COMP_INTERSECT这两种直方图的比较,值越大,说明图形越相似
printf("CV_COMP_CORREL : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_CORREL));
printf("CV_COMP_INTERSECT : %.4f\n", cvCompareHist(Histogram1, Histogram2, CV_COMP_INTERSECT));
cvReleaseImage(&image1);
cvReleaseImage(&image2);
cvReleaseHist(&Histogram1);
cvReleaseHist(&Histogram2);
return 0;
}
int main(int argc, char* argv[])
{
CompareHist(argv[1], argv[2]);
//CompareHist("d:\\camera.jpg", "d:\\camera1.jpg");
system("pause");
return 0;
} 图1
图2
结果
亮度变换
#include "opencv\\cv.h"
#include "opencv\\highgui.h"
/*
src and dst are grayscale, 8-bit images;
Default input value:
[low, high] = [0,1]; X-Direction
[bottom, top] = [0,1]; Y-Direction
gamma ;
if adjust successfully, return 0, otherwise, return non-zero.
*/
int ImageAdjust(IplImage* src, IplImage* dst,
double low, double high, // X方向:low and high are the intensities of src
double bottom, double top, // Y方向:mapped to bottom and top of dst
double gamma )
{
if( low<0 && low>1 && high <0 && high>1&&
bottom<0 && bottom>1 && top<0 && top>1 && low>high)
return -1;
double low2 = low*255;
double high2 = high*255;
double bottom2 = bottom*255;
double top2 = top*255;
double err_in = high2 - low2;
double err_out = top2 - bottom2;
int x,y;
double val;
// intensity transform
for( y = 0; y < src->height; y++)
{
for (x = 0; x < src->width; x++)
{
val = ((uchar*)(src->imageData + src->widthStep*y))[x];
val = pow((val - low2)/err_in, gamma) * err_out + bottom2;
if(val>255) val=255; if(val<0) val=0; // Make sure src is in the range [low,high]
((uchar*)(dst->imageData + dst->widthStep*y))[x] = (uchar) val;
}
}
return 0;
}
int main( int argc, char** argv )
{
IplImage *src = 0, *dst = 0;
src=cvLoadImage("f:\\img\\c2.jpg", 0); // force to gray image
if(src==0)return 0;
cvNamedWindow( "src", 1 );
cvNamedWindow( "result", 1 );
// Image adjust
dst = cvCloneImage(src);
// 输入参数 [0,0.5] 和 [0.5,1], gamma=1
if( ImageAdjust( src, dst, 0, 0.5, 0.5, 1, 1)!=0) return -1;
cvShowImage( "src", src );
cvShowImage( "result", dst );
cvWaitKey(0);
cvDestroyWindow("src");
cvDestroyWindow("result");
cvReleaseImage( &src );
cvReleaseImage( &dst );
return 0;
}
标签:
原文地址:http://blog.csdn.net/q123456789098/article/details/51141457