矩阵乘法
最常见的矩阵乘法运算,OpenCV中是通过重载 乘号*
来的实现的:
cv::Mat A = cv::Mat::ones(3, 4, CV_64F);
cv::Mat B = cv::Mat::ones(4, 5, CV_64F);
cv::Mat C = A * B;
要求:
- 内标一样:(m,n) × (n,m) = (m,m)
- 数据类型只能是
CV_32F
(CV_32FC1)、CV_64F
(CV_64FC1)、CV_32FC2
、CV_64FC2
四种之一。
报错如下:OpenCV(4.1.2) Error: Assertion failed ((type == (((5) & ((1 << 3) - 1)) + (((1)-1) << 3)) || type == (((6) & ((1 << 3) -
1)) + (((1)-1) << 3)) || type == (((5) & ((1 << 3) - 1)) + (((2)-1) << 3)) || type == (((6) & ((1 << 3) - 1)) + (((2)-1
) << 3)))) in gemm
即数据类型必须应该是5, 6, 13, 14
查表对应:Mat矩阵的基本数据类型
矩阵内积
矩阵内积是OpenCV定义的广义的向量内积或向量点乘,为了与下文的矩阵点乘区别,这里称为矩阵内积。原理是把整个Mat矩阵 ravel
展开成一个行(列)向量,之后执行向量的点乘运算,要求参与dot运算的两个Mat矩阵的行列数完全一致,结果是一个double
类型的标量。
cv::Mat D = cv::Mat::ones(3, 4, CV_64FC3);
cv::Mat E = cv::Mat::ones(3, 4, CV_64FC3);
double ret = D.dot(E);
要求:
- 两个矩阵同型:行列数必须一致,而不是元素个数一致
- 不要求数据类型
- 多通道时,对各通道的内积求和
矩阵点乘
这里的点乘不同于向量点乘,是指矩阵各元素对应相乘,结果还是矩阵,与MATLAB语法一致。我所遇到的点乘运用就是在CF Tracker上,见博文KCF核心公式与推导
- 使用
cv::multiply(A, B, ret);
cv::Mat M = cv::Mat::ones(3, 4, CV_64FC1);
cv::Mat N = cv::Mat::ones(3, 4, CV_64FC1);
cv::Mat K;
cv::multiply(M, N, K);
- 使用
Mat.mul()
成员函数
cv::Mat M = cv::Mat::ones(3, 4, CV_64FC1);
cv::Mat N = cv::Mat::ones(3, 4, CV_64FC1);
cv::Mat K = M.mul(N)
要求:
- 两个矩阵同型:行列数必须一致,各元素才能对应相乘
- 不要求数据类型,但两者应该类型一致
- 元素乘积可能发生上溢出,保留最大值(封顶)
矩阵相等判断
bool isEqual(cv::Mat& A, cv::Mat& B){
assert(A.channels() == 1 && B.channels() == 1);
cv::Mat comp = A != B;
return cv::countNonZero(comp) == 0;
}