您的位置:首页 > 运维架构

Opencv2相似图像检索

2016-04-22 13:23 381 查看
目标:选出一个参考图像,找出一组图像中与参考图像最相似的图像。

相似图像检索:基于图像内容的相似度检索,可以利用两幅图像的直方图特征,评估两幅图像的直方图相似度,进而得到两幅图像的相似度。

第一步:直方图特征提取

函数calcHist用来计算图像直方图特征,函数原型如下:

void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )


例:计算一张彩色图像的直方图特征

//初始化数据
int histSize[3];//容器数(0~255),256项
float hranges[2];
const float* ranges[3];
int channels[3];

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;
//计算直方图特征
cv::calcHist(&image,    //图像
1,          // 1张图片
channels,   // 通道
cv::Mat(),  // 掩码
hist,       // 返回值,直方图特征类型为cv::MatND
3,          // 3维
histSize,   // 容器数量
ranges      // 像素的强度值 范围
);


第二步 比较两幅图像相似度

两幅图像的相似度,可以用他们的直方图特征的相似度来代替。

函数compareHist计算两个直方图的相似度,其函数原型如下,

double compareHist(const SparseMat& H1, const SparseMat& H2, int method)


其中method参数,可以指定测量方法,可选值如下:

CV_COMP_CORREL Correlation

CV_COMP_CHISQR Chi-Square

CV_COMP_INTERSECT Intersection

CV_COMP_BHATTACHARYYA Bhattacharyya distance

CV_COMP_HELLINGER Synonym for CV_COMP_BHATTACHARYYA

例:计算两个直方图的相似度。

double similar=cv::compareHist(refHist, inputHist, CV_COMP_INTERSECT);


similar的值越大,相似度越高。

第三步 相似图像检索

通过前两步得到两幅图像的相似度,我们便可以进行相似图像检索,找出与参考图像最相似的图像。其代码如下:

imagecompare.h

#ifndef IMAGECOMPARE_H
#define IMAGECOMPARE_H
#include"colorhistogram.h"

class ImageCompare
{
private:
//参考图像
cv::Mat reference;
//检测图像
cv::Mat input;
//直方图数据
cv::MatND refHist;
cv::MatND inputHist;
ColorHistogram h;
//减色变量
int div;
public:
ImageCompare() :div(32){}
void setColorReduction(int factor)
{
div = factor;
}
int getColorRedutction()const
{
return div;
}
//设置参考图像
void setRerenceImage(const cv::Mat& image)
{
reference = image;
refHist = h.getHistogram(image);
//cv::normalize(refHist, refHist);
}
//比较两幅图像相似度
double compare(const cv::Mat &image)
{
input = image;
inputHist = h.getHistogram(image);
//cv::normalize(inputHist, inputHist);
return cv::compareHist(refHist, inputHist, CV_COMP_INTERSECT);
}
};
#endif


colorhistogram.h

#ifndef COLHISTOGRAM
#define COLHISTOGRAM

#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include<opencv2\highgui\highgui.hpp>

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;
}

// 计算直方图
cv::MatND getHistogram(const cv::Mat &image) {

cv::MatND hist;

// 彩色直方图
hranges[0]= 0.0;
hranges[1]= 255.0;
channels[0]= 0;
channels[1]= 1;
channels[2]= 2;

// 计算直方图
cv::calcHist(&image,
1,          // 1张图片
channels,   // 通道
cv::Mat(),  // 掩码
hist,       // 直方图
3,          // 3维
histSize,   // 容器数量
ranges      // 像素的强度值 范围
);

return hist;
}

};

#endif


源.cpp

#include"imagecompare.h"
#include<iostream>
int main()
{
//类对象
ImageCompare h;
//参考图像
cv::Mat image = cv::imread("D:/images/beach.jpg");
//设置直方图数据
h.setRerenceImage(image);
//定义double数组,保存相似度数据
double similar[4];
//group.jpg
cv::Mat groupImage = cv::imread("D:/images/group.jpg");
similar[0] = h.compare(groupImage);
std::cout << "group:" << similar[0] << std::endl;
//dog.jpg
cv::Mat dogImage = cv::imread("D:/images/dog.jpg");
similar[1] = h.compare(dogImage);
std::cout << "dog:" << similar[1] << std::endl;
//fundy.jpg
cv::Mat fundyImage = cv::imread("D:/images/fundy.jpg");
similar[2] = h.compare(fundyImage);
std::cout << "fundy:" << similar[2] << std::endl;
//waves.jpg
cv::Mat wavesImage = cv::imread("D:/images/waves.jpg");
similar[3] = h.compare(wavesImage);
std::cout << "waves:" << similar[3] << std::endl;

//找出相似度最大的数据
double max = similar[1];
int index = 0;
for (int i = 0; i < 4; i++)
{
if (similar[i]>max)
{
max = similar[i];
index = i + 1;
}
}
//显示最相似的图片
cv::namedWindow("最相似图片", CV_WINDOW_FREERATIO);
switch (index)
{
case 1:
cv::imshow("最相似图片", groupImage);
break;
case 2:
cv::imshow("最相似图片", dogImage);
break;
case 3:
cv::imshow("最相似图片", fundyImage);
break;
case 4:
cv::imshow("最相似图片", wavesImage);
break;
default:
break;
}
//显示原图
cv::namedWindow("原图", CV_WINDOW_FREERATIO);
cv::imshow("原图", image);
cv::waitKey(0);
return 0;
}


实验结果



与参考图像最相似的图像为:waves.jpg(从数据可以看出dog.jpg与waves.jpg,远比起其他两张图片,同参考图像beach.jpg相似)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: