在 OpenCV 中将矩阵的 SVD 分量相乘
Multiplying SVD components of a matrix in OpenCV
我将SVD应用于CV_32FC1 cvMat,并修改了"u"组件中的一些值。现在我正在尝试将"u"、"w"和"vt"分量相乘以获得单个矩阵 A。但是OpenCV无法将矩阵相乘,并出现以下错误。
OpenCV Error: Assertion failed (type == B.type() && (type == CV_32FC1 || type == CV_64FC1 || type == CV_32FC2 || type == CV_64FC2)) in gemm, file /build/buildd/opencv-2.1.0/src/cxcore/cxmatmul.cpp, line 687
terminate called after throwing an instance of 'cv::Exception'
what(): /build/buildd/opencv-2.1.0/src/cxcore/cxmatmul.cpp:687: error: (-215) type == B.type() && (type == CV_32FC1 || type == CV_64FC1 || type == CV_32FC2 || type == CV_64FC2) in function gemm
当我检查 SVD 对象中的矩阵类型时,它们的 type = 20,这与任何默认矩阵类型都不匹配。
#include <iostream>
#include <stdio.h>
#include "cv.h"
#include "highgui.h"
#include "constants.h"
const unsigned int MAX = 10000;
using namespace cv;
using namespace std;
int NO_FRAMES;
Mat resize_image(Mat &src, Mat img)
{
Mat dst;
resize(src, dst, Size(img.rows, img.cols));
return dst;
}
bool check_exit()
{
return (waitKey(27) > 0)?true:false;
}
int main(int argc, char ** argv)
{
Mat rgb[MAX];
Mat ycbcr[MAX];
Mat wm_rgb[MAX];
SVD svd[MAX];
namedWindow("watermark",1);
namedWindow("RGB", 2);
namedWindow("YCBCR",3);
namedWindow("u",4);
namedWindow("w",5);
namedWindow("vt",6);
if (argc < 3)
{
cout<<"Video file required! (Supported formats: avi, mp4, mpeg)n";
return 1;
}
VideoCapture capture(argv[1]);
Mat watermark = imread(argv[2]);
if(!capture.isOpened())
{
cout<<"Unable to open the video file!n";
return 1;
}
int i=0;
capture >> rgb[i];
while(!rgb[i].empty())
{
imshow("RGB", rgb[i]);
cvtColor(rgb[i], ycbcr[i], CV_RGB2YCrCb);
imshow("YCBCR", ycbcr[i]);
i++;
capture >> rgb[i];
if(check_exit())
exit(0);
}
NO_FRAMES = i;
watermark = resize_image(watermark, ycbcr[0]);
VideoWriter writer("output.avi", CV_FOURCC('d', 'i', 'v', 'x'), 24.0, cvSize(ycbcr[0].cols, ycbcr[0].rows), true);
for(int i = 0; i < NO_FRAMES - 1; i++)
{
Mat dst(ycbcr[i].rows, ycbcr[i].cols, CV_32FC1);
ycbcr[i].convertTo(dst, CV_32S);
SVD temp(dst, 5);
imshow("u", temp.u);
imshow("w", temp.w);
imshow("vt", temp.vt);
svd[i] = temp;
if(check_exit())
exit(0);
}
int j = 0, k = 0;
for (i = 0; i < NO_FRAMES; i++)
{
for (int p = 0; p < svd[i].u.rows; p++)
{
for(int q = 0; q < svd[i].u.cols; q++)
{
if (p == q)
{
if (j >= watermark.rows)
{
goto x;
}
if (k >= watermark.cols)
{
k = 0;
j++;
}
svd[i].u.at<float>(p, q) = watermark.at<float>(j,k);
k++;
}
}
}
}
x: for (i = 0; i < NO_FRAMES; i++)
{
Mat A(rgb[0].rows, rgb[0].cols, CV_32FC1);
//Here
A = svd[i].u * svd[i].w * svd[i].vt;
Mat B(A.rows, A.cols, CV_32FC1);
cvtColor(A, B, CV_YCrCb2RGB);
writer << B;
}
capture.release();
return 0;
}
该错误出现在矩阵乘法运算 (gemm()) 中,尽管该错误可能已传播到您尝试使用格式错误的矩阵 A 创建新矩阵 B 的下一行。请注意,OpenCV 中的 SVD 算法生成以下形式的输出:对于矩阵 A(m x n),SVD 生成以下三个矩阵:
w – 计算的奇异值 (最小值 (m,n) x 1)
u – 计算的左奇异向量 (m x m)
vt – 右奇异值的转置矩阵 (n x n)
在这里,奇异值存储在维度(min(m,n) x 1)的紧凑列向量中,而不是作为实际的数学等价物,它是维度(min(m,n),min(m,n))的对角矩阵。
因此,如果要从各个SVD分量重建矩阵,则必须首先将向量"w"转换为对角矩阵形式。您可以使用 OpenCV 的 diag() 方法执行此操作:
A = svd[i].u * Mat::diag(svd[i].w) * svd[i].vt;
我现在也遇到了这个问题,认为我应该在这里写, 在计算 SVD 时,我的大小就像 2 * (#imagePixels),因此,其中一个 U 或 Vt 矩阵变得巨大,无法在堆上分配,因此这个异常 std::bad_alloc 来了,因为在我的情况下,Vt 大小将是 imagePixel * imagePixel 这是巨大的。
愿这种情况也发生在您的案例中。
把它留在这里,以便下一个遇到这种情况的人也应该看看矩阵的大小。
相关文章:
- 具有 2 个分量的数组的特征映射到 3 的向量
- CUDA - 将 float3 数组的 (x,y,z) 分量的最小值/最大值分开?
- 求无向图中连通分量的个数
- 当文本以分量计开头时,将文本C++到 std::vector 中
- 如何将 Eigen Jacobi SVD 与 Eigen Affine Matrix一起使用
- Jacobi SVD的Eigen图书馆
- EIGEN 3.3 SVD.SOLVE返回错误的值
- 顶点分量的 AVX2 重心插值
- 提取 C++ 中分量之间的子字符串
- 与 MATLAB 相比,使用 cuSolver 时,SVD 非常慢
- 如何使用智能分量和子类应用Typecheck
- Call Julia SVD from C++
- 使用SVD分解的图像重建
- 从文件中读取到分量计
- 快速精确的稀疏svd库
- C++ 替换<< >>分量之间的一组字符串
- 使用OpenCV的c++中图像的绿色分量的直方图
- 为什么用Eigen和OpenCV计算的SVD左奇异向量具有不同的符号
- 打印图中矢量的弱分量
- 在 OpenCV 中将矩阵的 SVD 分量相乘