opencv-图像相似度评价指标方法总结

参考链接:https://blog.csdn.net/zjyruobing/article/details/49908979
C++ 实现的MSSIM代码如下:

Scalar getMSSIM(Mat  inputimage1, Mat inputimage2)
{
    //x:inputimage1 y:inputimage2
	Mat i1 = inputimage1;
	Mat i2 = inputimage2;
	const double C1 = 6.5025, C2 = 58.5225;
	int d = CV_32F;
	Mat I1, I2;
	i1.convertTo(I1, d);//将CV_8U转成CV_32F
	i2.convertTo(I2, d);
	Mat I2_2 = I2.mul(I2);//y^2
	Mat I1_2 = I1.mul(I1);//x^2
	Mat I1_I2 = I1.mul(I2);//x*y
	Mat mu1, mu2;
	GaussianBlur(I1, mu1, Size(11, 11), 1.5); //u_x
	GaussianBlur(I2, mu2, Size(11, 11), 1.5); //u_y
	Mat mu1_2 = mu1.mul(mu1); //u_x^2
	Mat mu2_2 = mu2.mul(mu2); //u_y^2
	Mat mu1_mu2 = mu1.mul(mu2); //u_y*u_x
	Mat sigma1_2, sigma2_2, sigma12;
	GaussianBlur(I1_2, sigma1_2, Size(11, 11), 1.5);
	sigma1_2 -= mu1_2;
	GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);
	sigma2_2 -= mu2_2;
	GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);
	sigma12 -= mu1_mu2;
	Mat t1, t2, t3;
	t1 = 2 * mu1_mu2 + C1;
	t2 = 2 * sigma12 + C2;
	t3 = t1.mul(t2);
	t1 = mu1_2 + mu2_2 + C1;
	t2 = sigma1_2 + sigma2_2 + C2;
	t1 = t1.mul(t2);
	Mat ssim_map;
	divide(t3, t1, ssim_map);
	Scalar mssim = mean(ssim_map);
	return mssim;
}

C++实现的峰值信噪比(PSNR)

double getPSNR(const Mat& I1, const Mat& I2)
{
	Mat s1;
	absdiff(I1, I2, s1);       // |I1 - I2|
	s1.convertTo(s1, CV_32F);  // cannot make a square on 8 bits
	s1 = s1.mul(s1);           // |I1 - I2|^2

	Scalar s = sum(s1);         // sum elements per channel

	double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels

	if (sse <= 1e-10) // for small values return zero
		return 0;
	else
	{
		double  mse = sse / (double)(I1.channels() * I1.total());
		double psnr = 10.0*log10((255 * 255) / mse);
		return psnr;
	}
}

C++直方图对比

bool compareByHist(Mat img, Mat orgImg)
{
		Mat tmpImg;
		resize(img, tmpImg, Size(orgImg.cols, orgImg.rows));
		//HSV颜色特征模型(色调H,饱和度S,亮度V)
		cvtColor(tmpImg, tmpImg, COLOR_BGR2HSV);
		cvtColor(orgImg, orgImg, COLOR_BGR2HSV);
		//直方图尺寸设置
		//一个灰度值可以设定一个bins,256个灰度值就可以设定256个bins
		//对应HSV格式,构建二维直方图
		//每个维度的直方图灰度值划分为256块进行统计,也可以使用其他值
		int hBins = 256, sBins = 256;
		int histSize[] = { hBins,sBins };
		//H:0~180, S:0~255,V:0~255
		//H色调取值范围
		float hRanges[] = { 0,180 };
		//S饱和度取值范围
		float sRanges[] = { 0,255 };
		const float* ranges[] = { hRanges,sRanges };
		int channels[] = { 0,1 };//二维直方图
		MatND hist1, hist2;
		calcHist(&tmpImg, 1, channels, Mat(), hist1, 2, histSize, ranges, true, false);
		normalize(hist1, hist1, 0, 1, NORM_MINMAX, -1, Mat());
		calcHist(&orgImg, 1, channels, Mat(), hist2, 2, histSize, ranges, true, false);
		normalize(hist2, hist2, 0, 1, NORM_MINMAX, -1, Mat());
		double similarityValue = compareHist(hist1, hist2, CV_COMP_CORREL);
		cout << "相似度:" << similarityValue << endl;
		if (similarityValue >= 0.85)
		{
			return true;
		}
		return false;
}

获取ORB特征值

double cacORBFeatureAndCompare(string srcPath1, string srcPath2)
{
	Mat srcImage1 = imread(srcPath1);
	Mat srcImage2 = imread(srcPath2);
	resize(srcImage1, srcImage1, Size(srcImage1.cols*5, srcImage1.rows*5));
	resize(srcImage2, srcImage2, Size(srcImage2.cols*5, srcImage2.rows*5));
	CV_Assert(srcImage1.data != NULL && srcImage2.data != NULL);
	// 关键点检测
	std::vector<KeyPoint> keyPoint1, keyPoint2;
	ORB orb;
	orb.detect(srcImage1, keyPoint1);
	orb.detect(srcImage2, keyPoint2);
	// 计算特征向量
	Mat descriptorMat1, descriptorMat2;
	orb.compute(srcImage1, keyPoint1, descriptorMat1);
	orb.compute(srcImage2, keyPoint2, descriptorMat2);
	// 特征匹配
	BFMatcher matcher(NORM_HAMMING);
	std::vector<DMatch> mathces;
	matcher.match(descriptorMat1, descriptorMat2, mathces);
	double max_dis = 0; double min_dis = 500;
	for (int i = 0; i < descriptorMat1.rows; i++)
	{
		double dist = mathces[i].distance;
		if (dist < min_dis) min_dis = dist;
		if (dist > max_dis) max_dis = dist;
	}
	//cout << " " << min_dis/100 << endl;
	// 绘制匹配点集
	/*Mat matchMat;
	drawMatches(srcImage1, keyPoint1,
		srcImage2, keyPoint2, mathces, matchMat);
	cv::imshow("Mathces", matchMat);
	waitKey(0);*/
	return min_dis;
}

SURF特征值

double ImageDis(string temp1, string temp2)
{
	Mat srcImage = imread(temp1);
	Mat srcImage1 = imread(temp2);
	//resize(srcImage, srcImage, Size(srcImage.cols * 5, srcImage.rows * 5));
	//resize(srcImage1, srcImage1, Size(srcImage1.cols * 5, srcImage1.rows * 5));
	int minHessian =500;
	SurfFeatureDetector detector(minHessian);
	//SurfFeatureDetector(SURF);
	std::vector<KeyPoint> keyPoint1, keyPoint2;
	detector.detect(srcImage, keyPoint1);
	detector.detect(srcImage1, keyPoint2);
	SurfDescriptorExtractor extrator;
	Mat descriptors1, descriptors2;
	extrator.compute(srcImage, keyPoint1, descriptors1);
	extrator.compute(srcImage1, keyPoint2, descriptors2);
	FlannBasedMatcher matcher;
	std::vector<DMatch> matches;
	matcher.match(descriptors1, descriptors2, matches);
	double max_dis = 0; double min_dis = 100;
	for (int i = 0; i < descriptors1.rows; i++)
	{
		double dist = matches[i].distance;
		if (dist < min_dis) min_dis = dist;
		if (dist > max_dis) max_dis = dist;
	}
	return min_dis;
}

根据像素基本运算对比(自己写的)

double DisImage(string path1, string path2)
{
	Mat SrcImage = imread(path1);
	Mat SrcImage1 = imread(path2);
	cvtColor(SrcImage, SrcImage, COLOR_BGR2GRAY);
	adaptiveThreshold(SrcImage,SrcImage, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY,11,5);//自动阈值分割,邻域均值
	//threshold(SrcImage, SrcImage, 150, 255, CV_THRESH_BINARY_INV);
	//imshow("SrcImage", SrcImage);
	cvtColor(SrcImage1, SrcImage1, COLOR_BGR2GRAY);
	adaptiveThreshold(SrcImage1, SrcImage1, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY,11,5);//自动阈值分割,邻域均值
	//threshold(SrcImage1, SrcImage1, 150, 255, CV_THRESH_BINARY_INV);
	//imshow("SrcImage1", SrcImage1);
	Mat  xnot;
	bitwise_xor(SrcImage, SrcImage1, xnot);
	medianBlur(xnot, xnot,5);
	//imshow("xnot", xnot);
	//waitKey(0);
	double similar = (1.0 - (double)countNonZero(xnot) / (SrcImage.rows*SrcImage.cols));
	return similar;
}

以上六种方法,根据图像进行不同的运用,原理自行百度,代码可直接运行。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值