zl程序教程

您现在的位置是:首页 >  后端

当前栏目

OpenCV学习笔记——判断两张图的相似度

Opencv笔记学习 判断 相似 两张
2023-09-11 14:16:46 时间

判断两张图的相似度

方法

  1. 直方图对比法
  2. ORB算法

实验

1.直方图对比法

参考如何使用OpenCV3直方图方法进行人脸相似度对比
因为我的环境是VS2010+OpenCV2.4.8,所以在原版的基础上做了一点小修改。

#include <opencv2/opencv.hpp>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
using namespace cv;
//直方图比对
bool compareFacesByHist(Mat img,Mat orgImg)
{
	Mat tmpImg;
	resize(img, tmpImg, Size(orgImg.cols, orgImg.rows));
	imshow("Img1", img);
	imshow("tmpImg", tmpImg);
	imshow("orgImg", orgImg);
	//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;
}

int main()
{
	Mat orgImg = imread("p34.png");
	Mat img = imread("p45.png");
	compareFacesByHist(img, orgImg);
	waitKey(0);
	return 0;
}

主要实现思路:
1)从本地读取两张图像
2)将需要对比的图像进行HSV格式转换
3)构建图像的直方图模型,并进行直方图归一化
4)比较两张图片的直方图模型,计算图片的直方图相似度
5)判断相似度值,如果大于0.85左右我们可以认为两张图片比较相似的

2. ORB算法

参考OpenCV图像相似度ORB算法(图像特征比对)

#include "stdafx.h"
#include <iostream>
#include<opencv2/opencv.hpp>
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/nonfree/features2d.hpp"
#include<opencv2/legacy/legacy.hpp>

using namespace std;
using namespace cv;

int getORB(char * imagePatha,char * imagePathb){
   double t;
   t=getTickCount();
   Mat img_1 = imread(imagePatha);
   Mat img_2 = imread(imagePathb);
   if (!img_1.data || !img_2.data)   
   {
      cout << "error reading images " << endl;      return -1;
   }
   ORB orb;
   vector<KeyPoint> keyPoints_1, keyPoints_2;
   Mat descriptors_1, descriptors_2;
   orb(img_1, Mat(), keyPoints_1, descriptors_1);
   orb(img_2, Mat(), keyPoints_2, descriptors_2);
   BruteForceMatcher<HammingLUT> matcher;
   vector<DMatch> matches;
   matcher.match(descriptors_1, descriptors_2, matches);
   double max_dist = 0; double min_dist = 100;
   for( int i = 0; i < descriptors_1.rows; i++ )   
   {
      double dist = matches[i].distance;
      if( dist < min_dist ) min_dist = dist;
      if( dist > max_dist ) max_dist = dist;
   }
   printf("-- Max dist : %f \n", max_dist );
   printf("-- Min dist : %f \n", min_dist );
   std::vector< DMatch > good_matches;
   for( int i = 0; i < descriptors_1.rows; i++ )   
   {
     if( matches[i].distance < 0.6*max_dist )
	 {
		good_matches.push_back(matches[i]);
     }
   }
	t=getTickCount()-t;
	t=t*1000/getTickFrequency();
	Mat img_matches;
	drawMatches(img_1, keyPoints_1, img_2, keyPoints_2,good_matches, img_matches,
	Scalar::all(-1), Scalar::all(-1),vector<char>(),
	DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
	imshow( "Match", img_matches);   
	printf( "%f ms\n", t );
	cvWaitKey(0);
	return 0;
}

int main()
{
	getORB("r.png","s.png");
	return 0;
}