欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

opencv基于颜色直方图的图像比较

程序员文章站 2024-03-25 18:47:22
...

opencv基于颜色直方图的图像比较

图像预处理
把图像分割,把要检测的图像分割为9个小图像。比如下图为待检索的图像,将其划分为9个小部分,分别对每部分比较最后计算平均值。
opencv基于颜色直方图的图像比较
计算直方图并归一化
将图像划分为9个小部分后将图像转换为HSV空间
HSV空间的图像检索使用H(色调)和S(饱和度)分量计算直方图并比较。opencv中计算直方图调用函数calcHist,将直方图归一化要调用函数normalize。
比较相似度
在得到归一化的直方图后,要度量图像的相似度。常用的相似度度量方式有5种,分别是相关性比较(Correlation)、卡方比较(Chi-Square)、十字交叉比(Intersection)、巴氏距离(Bhattacharyya)和EMD距离。
程序选择了相关性比较和EMD距离来比较图像的相关性。

程序运行环境vs2015+opencv2.4.1

#include <opencv2/core/core.hpp>    
#include "opencv2/opencv.hpp"
#include <opencv2/highgui/highgui.hpp>    
#include <iostream>  
#include <opencv2/imgproc/imgproc.hpp>  
#include <vector>  
#include <string>
#include <stdlib.h>
#include <io.h>
#include < fstream>
#include <algorithm>
//运行环境vs2015+opencv2.4.1
using namespace std;
using namespace cv;

//读入文件夹下指定格式的所有文件,本程序是读取文件夹下所有jpg图片
void getFiles(string path, string file_format, vector<string>& files)
{
	intptr_t   hFile = 0;//intptr_t和uintptr_t是什么类型:typedef long int/ typedef unsigned long int
	struct _finddata_t fileinfo;
	string p, file_formatName;
	if (0 != strcmp(file_format.c_str(), ""))
	{
		file_formatName = "\\*." + file_format;
	}
	else
	{
		file_formatName = "\\*";
	}
	if ((hFile = _findfirst(p.assign(path).append(file_formatName).c_str(), &fileinfo)) != -1)//assign方法可以理解为先将原字符串清空,然后赋予新的值作替换。
	{
		do
		{
			files.push_back(p.assign(path).append("\\").append(fileinfo.name));
		} while (_findnext(hFile, &fileinfo) == 0);
		_findclose(hFile);
	}
}
//用于数组降序排列
bool hightolow(float a, float b)
{
	return a>b;
}
//图像分割
void rectImage(Mat* rectImg, Mat oImg) {
	int m = oImg.cols;//宽
	int n = oImg.rows;//高
	rectImg[1] = oImg(Rect(0, 0, m / 3, n / 3));
	rectImg[2] = oImg(Rect(m / 3, 0, m / 3, n / 3));
	rectImg[3] = oImg(Rect(m / 3 * 2, 0, m / 3, n / 3));
	rectImg[4] = oImg(Rect(0, n / 3, m / 3, n / 3));
	rectImg[5] = oImg(Rect(m / 3, n / 3, m / 3, n / 3));
	rectImg[6] = oImg(Rect(m / 3 * 2, n / 3, m / 3, n / 3));
	rectImg[7] = oImg(Rect(0, n / 3 * 2, m / 3, n / 3));
	rectImg[8] = oImg(Rect(m / 3, n / 3 * 2, m / 3, n / 3));
	rectImg[9] = oImg(Rect(m / 3 * 2, n / 3 * 2, m / 3, n / 3));
}
//图像检索
void compareFacesByHist(string filePath, Mat orgImg)
{
	vector<Mat> src;
	vector<string> files;
	string file_format = "jpg";
	getFiles(filePath, file_format, files);
	int number = files.size();//文件数量
	//计算直方图所需参数
	vector<Mat> signature1(10);
	vector<Mat> signature2(10);
	MatND hist1, hist2;
	int scale = 10, histSize[] = { 8,8 }, ch[] = { 0,1 };
	float h_ranges[] = { 0,180 };
	float s_ranges[] = { 0,255 };
	const float* ranges[] = { h_ranges,s_ranges };
	Mat oimage[10];
	Mat image[10];
	int m = orgImg.cols;//宽
	int n = orgImg.rows;//高
	std::map<string, float> mymap;
	std::map<string, float> mymapEMD;
	//存放检索结果 大小与图像库图片数量相同
	float compare[30];
	float compareEMD[30];
	//读取图像库
	for (int i = 0; i < number; i++)
	{
		Mat img = imread(files[i]);
		src.push_back(img);
	}
	//待检索图像分割并转换为HSV空间
	rectImage(oimage, orgImg);
	for (int i = 1; i < 10; i++) {
		cvtColor(oimage[i], oimage[i], COLOR_RGB2HSV);
		
	}
	//从图像库依次读取图像检索
	for (int i = 0; i < number; i++) {
		double s = 0;
		double similarityValue = 0;
		float emd = 0;
		float semd = 0;
		mymap[files[i]] = 0;
		/*
		imge[1] = src[i](Rect(0, 0, a / 3, b / 3));
		imge[2] = src[i](Rect(a / 3, 0, a / 3, b / 3));
		imge[3] = src[i](Rect(a / 3 * 2, 0, a / 3, b / 3));
		imge[4] = src[i](Rect(0, b / 3, a / 3, b / 3));
		imge[5] = src[i](Rect(a / 3, b / 3, a / 3, b / 3));
		imge[6] = src[i](Rect(a / 3 * 2, b / 3, a / 3, b / 3));
		imge[7] = src[i](Rect(0, b / 3 * 2, a / 3, b / 3));
		imge[8] = src[i](Rect(a / 3, b / 3 * 2, a / 3, b / 3));
		imge[9] = src[i](Rect(a / 3 * 2, b / 3 * 2, a / 3, b / 3));*/
		rectImage(image, src[i]);
		for (int k = 1; k < 10; k++) {
			//计算直方图并归一化
			vector<Vec3f> sigv1, sigv2;
			calcHist(&oimage[k], 1, ch, Mat(), hist1, 2, histSize, ranges, true, false);
			normalize(hist1, hist1, 0, 1, NORM_MINMAX, -1, Mat());
			cvtColor(image[k], image[k], COLOR_RGB2HSV);
			calcHist(&image[k], 1, ch, Mat(), hist2, 2, histSize, ranges, true, false);
			normalize(hist2, hist2, 0, 1, NORM_MINMAX, -1, Mat());
			//直方图比较 改变最后一个参数可改变比较方式,当前参数为相关性比较
			similarityValue = compareHist(hist1, hist2, CV_COMP_CORREL);
			s = s + similarityValue;
			//EMD距离比较
			for (int h = 0; h < histSize[0]; h++)
				for (int s = 0; s < histSize[1]; s++) {
					float hval = hist1.at<float>(h, s);
					float hva2 = hist2.at<float>(h, s);
					if (hval != 0)
						sigv1.push_back(Vec3f(hval, (float)h, (float)s));
					sigv2.push_back(Vec3f(hva2, (float)h, (float)s));
				}

			signature1[k] = Mat(sigv1).clone().reshape(1);
			signature2[k] = Mat(sigv2).clone().reshape(1);
			emd = EMD(signature1[k], signature2[k], CV_DIST_L2);
			semd = semd + emd;
		}
		semd = semd / 9;
		s = s / 9;
		compare[i] = s;
		compareEMD[i] = semd;
		mymap[files[i]] = s;
		mymapEMD[files[i]] = semd;
		//cout << "相似度:" << s << endl;
		//cout << "emd:" << semd << endl;
	}
	sort(compare, compare + 30, hightolow);
	sort(compareEMD, compareEMD + 30);
	//输出检索出的图像 相关性比较
	/*
	for (int l = 0; l < 10; l++) {
		string path;
		for (std::map<string, float>::iterator it = mymap.begin(); it != mymap.end(); it++)
		{
			if (it->second == compare[l])
				path = it->first;
		}
		Mat image = imread(path);
		imshow("相关性" + std::to_string(compare[l]), image);
		waitKey(200);
	}*/
	//输出检索出的图像 EMD距离
	
	for (int l = 0; l < 10; l++) {
	string path;
		for (std::map<string, float>::iterator it = mymapEMD.begin(); it != mymapEMD.end(); it++)
		{
			if (it->second == compareEMD[l])
				path = it->first;
		}
		Mat image = imread(path);
		imshow("EMD" + std::to_string(compareEMD[l]), image);
		waitKey(200);
	}
	waitKey(0);

}

int main()
{
	vector<Mat> src;
	//图片库路径
	string filePath = "D:\\video-img\\testcompare\\images"; 
    //待检索图像
	Mat orgImg = imread("D:\\video-img\\testcompare\\images\\image15.jpg");
	compareFacesByHist(filePath, orgImg);
	waitKey(0);
	return 0;
}