这里的注意的是色调H,其在这里的取值范围为0到180,因为Note this is only done for 8-bit formats. So if you want fullprecision, you can always switch to a 32f format prior to the colorspace conversion, which will yield the full 0-360 hue range.简单来说就是这图为uchar范围在0到255,如果取全范围0到360就会超过256,所以这里用0到180来表示。
至于image.type()返回的int,如果为cv_8uc3返回为16,具体见其源文件的定义。
以下为代码:
// opencv_calcbackproject.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <opencv245.h>
using namespace std;
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;
}
};
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;
}
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;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
ColorHistogram hc;
ContentFinder finder;
Mat result1;
Mat image = imread("C:\\Users\\sony\\Desktop\\cloud.jpg");
Mat imageROI = image(Rect(130, 156, 32, 32));
Mat imagehist = hc.getHueHistogram(imageROI);
//归一化直方图 使其在0到1之间
finder.setHistogram(imagehist);
/*finder.setThreshold(0.3f);*/
Mat hsv;
cvtColor(image,hsv,CV_BGR2HSV);
//表示通道
int ch[1] ;
ch[0] = 0;
result1 = finder.find(hsv, 0.0f,180.0f,ch,1);
imshow("使用色度的结果(1)",result1);
waitKey(0);
return 0;
}
效果图如下: