# OpenCV Mat之间的substact/add/abs/absdiff
# cv::substract
计算矩阵与矩阵之间每个元素的差值。
函数原型:
void subtract(InputArray src1,
InputArray src2,
OutputArray dst,
InputArray mask = noArray(),
int dtype = -1);
src1
可以是Mat/Scalar
src2
可以是Mat/Scalar
dst
可以是Mat/Scalar
mask
掩码矩阵,类型需要为8UC1
或8SC1
,mask==0
的位置取src1
对应的值,不做减法dtype
控制输出矩阵的数据类型
实例:
#include <iostream>
#include <opencv2/core.hpp>
using namespace std;
void printMat(cv::Mat &m1);
int main()
{
cv::Mat m1 = (cv::Mat_<float>(3,3) << -1.2f,2.1f,3.0f,
2.3f,4.5f,5.6f,
7.1f,2.5f,8.9f);
cv::Mat m2 = (cv::Mat_<float>(3,3) << -1.2f,2.1f,3.0f,
2.5f,4.8f,5.6f,
7.1f,2.5f,8.9f);
cv::Mat mc1 = cv::Mat::zeros(cv::Size(2, 2), CV_8SC3);
cv::Mat mc2 = cv::Mat::zeros(cv::Size(2, 2), CV_8SC3);
cv::Mat mask = cv::Mat::ones(cv::Size(2, 2), CV_8SC1);
mask.at<uchar>(0, 0) = 0;
mc2.setTo(cv::Scalar(2,2,2));
cout << "mc1 = " << mc1 << " mc2 = " << mc2;
cv::Scalar mcv = cv::Scalar(2, 3, 1);
cv::Mat m;
cv::subtract(m1, m2, m);
printMat(m);
cv::Scalar v(1.2);
cv::subtract(m1, v, m);
printMat(m);
cv::subtract(mc1, mc2, m, mask);
std::cout << "Mat: \n" << m << std::endl;
cv::subtract(mc1, mcv, m);
std::cout << "Mat: \n" << m << std::endl;
cv::subtract(mc1, v, m, cv::noArray(), CV_32FC3);
std::cout << "Mat: \n" << m << std::endl;
return 0;
}
void printMat(cv::Mat &m1)
{
cout << "Mat: \n";
for (size_t i = 0; i < m1.rows; ++i)
{
for (size_t c = 0; c < m1.cols; ++c)
cout << m1.at<float>(i, c) << " ";
cout << endl;
}
}
上面的例子中分别有:
- 单通道
Mat
减去Mat
- 单通道
Mat
减去Scalar
- 多通道
Mat
减去‵Mat` - 多通道
Mat
减去多通道‵Scalar` - 多通道
Mat
减去单通道‵Scalar,只作用在
Mat`对应的单个通道上
上面例子的输出结果:
mc1 = [ 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0]
mc2 = [ 2, 2, 2, 2, 2, 2;
2, 2, 2, 2, 2, 2]
Mat:
[0 0 0;
-0.2 -0.3 0;
0 0 0]
Mat:
[-2.4 0.9 1.8;
1.1 3.3 4.4;
5.9 1.3 7.7]
Mat:
[ 0, 0, 0, -2, -2, -2;
-2, -2, -2, -2, -2, -2]
Mat:
[ -2, -3, -1, -2, -3, -1;
-2, -3, -1, -2, -3, -1]
Mat:
[-1.2, 0, 0, -1.2, 0, 0;
-1.2, 0, 0, -1.2, 0, 0]
如果cv::subtract(mc1, v, m, cv::noArray(), CV_32FC3);
这里没有指定类型,输出的将是8SC1
类型,结果为:
Mat:
[-1, 0, 0, -1, 0, 0;
-1, 0, 0, -1, 0, 0]
# cv::add
cv::add
是两个输入数据元素间相加,和substract
基本相同。
函数原型:
void add(InputArray src1,
InputArray src2,
OutputArray dst,
InputArray mask = noArray(),
int dtype = -1);
参数参考cv::substract
实例:
cv::Mat m;
cv::subtract(m1, m2, m);
printMat(m);
cv::Scalar v(1.2);
cv::subtract(m1, v, m);
printMat(m);
cv::subtract(mc1, mc2, m, mask);
std::cout << "Mat: \n" << m << std::endl;
cv::subtract(mc1, mcv, m);
std::cout << "Mat: \n" << m << std::endl;
cv::subtract(mc1, v, m, cv::noArray(), CV_32FC3);
std::cout << "Mat: \n" << m << std::endl;
结果,
Mat:
-2.4 4.2 6
4.8 9.3 11.2
14.2 5 17.8
Mat:
0 3.3 4.2
3.5 5.7 6.8
8.3 3.7 10.1
Mat:
[ 0, 0, 0, 2, 2, 2;
2, 2, 2, 2, 2, 2]
Mat:
[ 2, 3, 1, 2, 3, 1;
2, 3, 1, 2, 3, 1]
Mat:
[1.2, 0, 0, 1.2, 0, 0;
1.2, 0, 0, 1.2, 0, 0]
可以看到和cv::substract
的操作相同,除了减法变成了加法运算。
# cv::abs
对输入矩阵的每个元素取绝对值。
实例:
m = cv::abs(m);
printMat(m);
结果为:
Mat:
1.2 2.1 3
2.3 4.5 5.6
7.1 2.5 8.9
# cv::absdiff
cv::absdiff
对输入的两个矩阵先做差再取绝对值。
函数原型:
void absdiff(InputArray src1, InputArray src2, OutputArray dst);
实例:
cv::absdiff(m1, m2, m);
printMat(m);
cv::absdiff(mcv, mcv, m);
cout << m << std::endl;
输出:
Mat:
0 0 0
0.2 0.3 0
0 0 0
[0,0,0,0]
Scalar
能中有四个元素Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);
,因此尽管输入是(2,3,1)
打印出来的结果仍然是[0,0,0,0]
。
1.https://docs.opencv.org/4.8.0/dd/d4d/tutorial_js_image_arithmetics.html (opens new window)