基于直方图比较的图像相似度计算

       由于项目需要,这两天看了一些图像相似度计算方面的资料,图像相似度计算就是对两幅图片之间内容的相似程度进行打分,根据分数的高低来判断图像内容的相似程度。在查找资料过程中,首先看到的图像相似度计算方法就是直方图比较。该算法计算过程很容易理解,首先对于两幅图像分别计算其直方图,然后根据某种衡量标准进行比较,比较结果即为两幅图像的相似度。贴心的OpenCV已提供了直方图比较的函数,即compareHist(),该函数提供了四种对比标准来计算相似度,具体计算公式及函数用法可查阅OpenCV参考手册。下面是我实现的直方图比较程序。经过实验发现,由于直方图自身的局限性:仅反映图像像素各灰度值的数量,不能反映图像纹理结构,很明显该方法存在很多误判,比如纹理结构相同,但明暗不同的图像,应该相似度很高,但实际结果是相似度很低,而纹理结构不同,但明暗相近的图像,相似度却很高。
#include "stdafx.h"
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>

using namespace cv;

// 计算图像直方图
void CompImageHist(Mat &src, MatND &b_hist, MatND &g_hist, MatND &r_hist)
{
	// 分割成3个单通道图像(bgr)
	vector<Mat> rgb_planes;
	split(src, rgb_planes);

	// 设定bin数目及取值范围
	int histSize = 255;
	float range[] = { 0, 255 };
	const float* histRange = { range };

	// 计算直方图
	bool uniform = true;
	bool accumulate = false;
	calcHist(&rgb_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate);
	calcHist(&rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate);
	calcHist(&rgb_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate);

	// 直方图归一化>>范围为[0, 1]
	normalize(r_hist, r_hist, 0, 1, NORM_MINMAX, -1/*, Mat()*/);
	normalize(g_hist, g_hist, 0, 1, NORM_MINMAX, -1/*, Mat()*/);
	normalize(b_hist, b_hist, 0, 1, NORM_MINMAX, -1/*, Mat()*/);
}

int main(int argc, _TCHAR* argv[])
{
	Mat img0 = imread("image\\lena0.jpg");
	imshow("img0", img0);
	Mat img1 = imread("image\\lena1.jpg");
	imshow("img1", img1);

	MatND hist0[3], hist1[3];
	// 计算图像直方图
	CompImageHist(img0, hist0[0], hist0[1], hist0[2]);
	CompImageHist(img1, hist1[0], hist1[1], hist1[2]);

	double sum[4] = { 0.0 };
	double results[4] = { 0.0 };
	char channelName[][8] = { { "蓝色" }, { "绿色" }, { "红色" } };

	// 比较直方图
	printf("各通道比较结果... \n\n");
	for (int i = 0; i < 3; i++)
	{
		// 相关: CV_COMP_CORREL,卡方: CV_COMP_CHISQR,相交: CV_COMP_INTERSECT,巴氏: CV_COMP_BHATTACHARYYA
		results[0] = compareHist(hist0[i], hist1[i], CV_COMP_CORREL);
		results[1] = compareHist(hist0[i], hist1[i], CV_COMP_CHISQR);
		results[2] = compareHist(hist0[i], hist1[i], CV_COMP_INTERSECT);
		results[3] = compareHist(hist0[i], hist1[i], CV_COMP_BHATTACHARYYA);
		sum[0] += results[0];
		sum[1] += results[1];
		sum[2] += results[2];
		sum[3] += results[3];
		printf("%s-->相关: %f, 卡方: %f, 相交: %f, 巴氏: %f \n", channelName[i], results[0], results[1], results[2], results[3]);
	}
	printf("\n均值-->相关: %f, 卡方: %f, 相交: %f, 巴氏: %f \n", sum[0]/3, sum[1]/3, sum[2]/3, sum[3]/3);

	waitKey();
	return 0;
}
运行结果:


程序基于vs2005 + opencv210实现,下载工程后,如果与自己使用的opencv版本不一致,则需要对工程进行简单配置才能正确运行。

  • 1
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值