我们知道,直方图可以在一定程度上反应图像的一些统计信息。所以,可以考虑用直方图对比的方法,进行基于内容的图像检索。
通常我们搜索图片,都是根据图片的标签搜索的。基于内容的搜索,就是假设我们不知道标签,而是直接输入一幅图像,然后从得出一些跟这幅图像的直方图比较相似的图像。
那么我们不禁要问,如何度量两幅直方图的相似程度呢?
OpenCV的compareHist函数提供了一个参数供你选择。最简单的就是CV_COMP_INTERSECT。这个方法原理其实很简单,就是对于两幅的同一个bin,选择他们的最小值,然后把所有的bin都加起来。举个例子,如果两幅图像没有任何相同的颜色,那么这个比较的计算结果就为0;如果是两幅完全相同的图像,那么计算结果就应该是整幅图像的像素数。其他的度量方法可以参考OpenCV的帮助手册,这里就不一一细说了。
下面看看代码吧。因为需要计算彩色图像的直方图,所以先建立一个计算彩色图像直方图的类:
#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 IMAGECOMPARATOR
#define IMAGECOMPARATOR
#include "colorhistogram.h"
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
class ImageComparator
{
private:
Mat reference;
Mat input;
Mat refH;
Mat inputH;
ColorHistogram hist;
int div;
public:
ImageComparator():div(32){}
void setColorReducation(int factor)
{
div = factor;
}
int getColorReduction()
{
return div;
}
void setRefrenceImage(const Mat &image)
{
reference = hist.colorReduce(image,div);
refH = hist.getHistogram(reference);
}
double compare(const Mat &image)
{
input = hist.colorReduce(image,div);
inputH = hist.getHistogram(input);
return compareHist(refH,inputH,CV_COMP_INTERSECT);
}
};
#endif
注意到在计算直方图前,我对图像的颜色进行了减少,这样做的主要目的是为了减少运算量。
有了这两个类,我们的主程序就变得简单多了:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "imageComparator.h"
#include <iostream>
using namespace std;
int main()
{
Mat image = imread("D:/picture/images/waves.jpg");
if(!image.data)
return -1;
imshow("待检测图像",image);
cout<<"图像像素数为:"<<image.cols*image.rows<<endl;
ImageComparator c;
c.setRefrenceImage(image);
//跟自己比
Mat input = imread("D:/picture/images/waves.jpg");
imshow("自己",input);
cout<<"waves VS waves:"<<c.compare(input)<<endl;
input = imread("D:/picture/images/dog.jpg");
imshow("dog",input);
cout<<"waves VS dog:"<<c.compare(input)<<endl;
input = imread("D:/picture/images/marais.jpg");
imshow("沼泽",input);
cout<<"waves VS marsh:"<<c.compare(input)<<endl;
input= cv::imread("D:/picture/images/bear.jpg");
imshow("熊",input);
cout<<"waves VS bear:"<<c.compare(input)<<endl;
waitKey(0);
return 0;
}
正如前面所说的,如果自己跟自己比较,结果就是整幅图像像素数。
最后,做一点小小的说明,这里演示的直方图比较法其实不是特别靠谱。举一个简单的例子,对于一幅图像,如果把它进行翻转,或者分割以后在重新随机组合起来(尽管结果可能没有什么意义),尽管图像发生了显著地变化,但是他的直方图是不会变的。所以又有人想出了对图像分块,然后再做直方图之类的方法。我也不是这方面的专家,如果大家真的想弄一个靠谱的做法,最好是查查论文,看看牛人们都是怎么搞的。
分享到:
相关推荐
爱分享、爱极客的编程怪兽--DaveBobo 博文 《【OpenCV学习笔记 007】使用直方图统计像素》 博文链接: http://blog.csdn.net/davebobo/article/details/52554968 OpenCV版本:2.4.9
自己编的,基于opencv的,使用颜色直方图进行图像匹配,效果还可以,希望大家喜欢
在visual studio2010上使用opencv编写的MFC程序,可用于彩色图像直方图均衡
使用VC6.0集成开发环境初步实现了基于图片轮廓和图片颜色直方图的图像检索系统;对于给定的例子图像,系统搜索指定目录并根据与例子图像的颜色直方图或轮廓相似性程度数值按升序排列相符合的
基于opencv的图像直方图显示与直方图均衡 下载必看: 1.程序默认处理的是灰度图像,彩色图像将转换成灰度图处理 2.程序基于opencv2.2的c++ API编写,编译前确保你配置的是opencv2.x环境,1.0没试过。
本程序用c++调用OpenCV函数实现了通过直方图均衡化来增强图像对比度,内涵处理前后效果图。
利用OpenCV实现了四种方法的两张图像直方图的对比
实现利用opencv画灰度图像或者彩色图像的直方图。
在VS2010中实现图像的直方图计算,可以运行,效果很好
OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,网络上一些小伙伴写的一些关于Android版OpenCV的博客,大部分都模糊不清,基本就复制粘贴的,有些甚至没有实践就直接贴上去了,这样...
基础学习笔记(注释)之opencv(12):改变图像对比度和亮度.doc
基于OpenCV的图象RGB直方图检索系统 文件结构: DB/ 数据库文件夹(存放图像的直方图特征) mirflickr/ 图片文件夹(存放jpg图片,本例为mirflickr25k数据集) config.py 配置文件(定义图片文件夹路径、数据库...
基于OPENCV和VC的计算图像颜色直方图的小程序。
利用opencv取一幅图像的直方图,并显示出来,可以让你熟悉opencv的工作过程,和直方图原理
基于opencv的图像颜色直方图提取程序
(3)画出图像的直方图:用行表示灰度值所在区间,在列上用“*”表示直方图数据,“*”的个数即为 对应区间内的像素值统计结果,数据为 0 的不显示。 完成情况:对查找得到的代码进行研读理解并小幅度修改。 2. ...
基于vc用opencv完成对图像和视频的边缘检测和直方图均衡化等操作
可以获得灰度图像或者彩色图像的直方图。详细见 :http://blog.csdn.net/fred_yang2013/article/details/10824435