昊虹君 发表于 2022-11-23 14:35

OpenCV的标量容器Scalar尽量别去做运算,用来存储标量数据即可

OpenCV的标量容器Scalar尽量别去做运算,用来存储标量数据即可

关于OpenCV的标量容器Scalar的详细介绍,可参见我的另一篇博文,
链接 https://www.hhai.cc/thread-144-1-1.html

这篇博文就是提醒大家对于标量容器Scalar,让它做容器就好,尽量别让它参与运算。

下面这个例子就表明让它参与运算得到了错误的结果。

//出处:昊虹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 = C1;
        C1_scalar = C1;
        C1_scalar = C1;

        cv::Scalar C2_scalar;
        C2_scalar = C2;
        C2_scalar = C2;
        C2_scalar = 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;
}
代码中用到的两幅图像百度网盘下载链接:
https://pan.baidu.com/s/11sObYLhjzSQ1ejTpD3Selw?pwd=1h9c
运行结果如下:
http://pic1.hhai.cc/pic1/2022/2022-11/005/06.png
上面代码中参与运算的数全是正数,没有做过可能产生负数的运算,但是现在结果为负,明显是错误的。
把上面的运算符 * 换成函数multiply(),运算符 + 换成函数add()得到的结果也是不正确的。
虽然Scalar类有与Mat一样的运算成员函数,但还是尽量不要用它来做运算,毕竟它不是用来做运算的类或对象。
页: [1]
查看完整版本: OpenCV的标量容器Scalar尽量别去做运算,用来存储标量数据即可