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

Posted 昊虹AI笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV的标量容器Scalar尽量别去做运算,用来存储标量数据即可相关的知识,希望对你有一定的参考价值。

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

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

下面这个例子就表明让它参与运算得到了错误的结果。
代码中用到的两幅图像百度网盘下载链接:
https://pan.baidu.com/s/11sObYLhjzSQ1ejTpD3Selw?pwd=1h9c

//出处:昊虹AI笔记网(hhai.cc)
//用心记录计算机视觉和AI技术

//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一样的运算成员函数,但还是尽量不要用它来做运算,毕竟它不是用来做运算的类或对象。

以上是关于OpenCV的标量容器Scalar尽量别去做运算,用来存储标量数据即可的主要内容,如果未能解决你的问题,请参考以下文章

标量(0,255,0)在opencv中没有给出绿色线

张量(Tensor)标量(scalar)向量(vector)矩阵(matrix)

OpenCV:Scalar数据类型理解

OpenCV:Scalar数据类型理解

OpenCV点滴3

Opencv视觉处理(C++)语法学习图像的算术与逻辑运算