参考链接: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 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 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 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 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;
}
以上六种方法,根据图像进行不同的运用,原理自行百度,代码可直接运行。