关于OpenCV的标量容器Scalar的详细介绍,可参见我的另一篇博文,
链接 https://www.hhai.cc/thread-144-1-1.html
这篇博文就是提醒大家对于标量容器Scalar,让它做容器就好,尽量别让它参与运算。
下面这个例子就表明让它参与运算得到了错误的结果。
代码中用到的两幅图像百度网盘下载链接:
https://pan.baidu.com/s/11sObYLhjzSQ1ejTpD3Selw?pwd=1h9c
//出处:昊虹AI笔记网(hhai.cc)
//用心记录计算机视觉和AI技术
//博主微信/QQ 2487872782
//QQ群 271891601
//欢迎技术交流与咨询
//OpenCV版本 OpenCV3.0
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
cv::Scalar cal_ssim(const Mat& i1, const Mat& i2) //注意,两幅图的大小要一致
{
double C1 = 6.5025, C2 = 58.5225;
cv::Scalar C1_scalar;
C1_scalar[0] = C1;
C1_scalar[1] = C1;
C1_scalar[2] = C1;
cv::Scalar C2_scalar;
C2_scalar[0] = C2;
C2_scalar[1] = C2;
C2_scalar[2] = C2;
cv::Mat I1, I2;
// 转换成32浮点数进行平方操作
i1.convertTo(I1, CV_32F);
i2.convertTo(I2, CV_32F);
cv::Scalar E_I1, SD_I1; //E_I1为图像I1的均值,SD_I1为图像I1的标准差
meanStdDev(I1, E_I1, SD_I1);
cv::Scalar E_I2, SD_I2; //E_I2为图像I2的均值,SD_I2为图像I2的标准差
meanStdDev(I2, E_I2, SD_I2);
cv::Scalar ssim_num;
ssim_num = (2 * E_I1*E_I2 + C1_scalar)*(2 * SD_I1*SD_I2 + C2_scalar);
return ssim_num;
}
int main()
{
// 读取源图像及两幅待检测相似度的图像
cv::Mat srcImage1 = cv::imread("F:/material/images/2022/2022-11/PSNR-SSIM/hand1.jpg", 1);
if (srcImage1.empty())
return -1;
cv::Mat srcImage2 = cv::imread("F:/material/images/2022/2022-11/PSNR-SSIM/hand2.jpg", 1);
if (srcImage2.empty())
return -1;
cv::Scalar ssim_num;
ssim_num = cal_ssim(srcImage1, srcImage1);//注意,两幅图的大小要一致
std::cout << "ssim_num is: \n" << ssim_num << std::endl << std::endl;
return 0;
}
运行结果如下:
上面代码中参与运算的数全是正数,没有做过可能产生负数的运算,但是现在结果为负,明显是错误的。
把上面的运算符 * 换成函数multiply(),运算符 + 换成函数add()得到的结果也是不正确的。
虽然Scalar类有与Mat一样的运算成员函数,但还是尽量不要用它来做运算,毕竟它不是用来做运算的类或对象。