Reputation: 306
I applied SVD to a CV_32FC1 cvMat and modified some values in the 'u' component. Now I am trying to multiply the 'u, 'w' and 'vt' components to get a single matrix A. But OpenCV fails to multiply the matrices with the following error.
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
When I inspected the types of the matrices in the SVD object, they seem to have type = 20, which doesn't match any of the default matrix types.
#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;
}
Upvotes: 0
Views: 3589
Reputation: 71
The error appears in the matrix multiplication operation (gemm()) although the error may have propagated to the next line where you are trying to create the new matrix B with ill-formed matrix A. Note that the SVD algorithm in OpenCV produces outputs of the form below: For a matrix A(m x n), SVD produces the following three matrices:
w – calculated singular values (min(m,n) x 1)
u – calculated left singular vectors (m x m)
vt – transposed matrix of right singular values (n x n)
Here the singular values are stored in a compact column vector of dimensions (min(m,n) x 1) and not as the actual mathematical equivalent which is a diagonal matrix of dimensions (min(m,n), min(m,n)).
Therefore if you want to reconstruct the matrix from the individual SVD components you'll have to first bring the vector 'w' into a diagonal matrix form. You can do this using OpenCV's diag() method:
A = svd[i].u * Mat::diag(svd[i].w) * svd[i].vt;
Upvotes: 2
Reputation: 522
I also encountered this now, thought I should write here, In my case while computing SVD, my size was like 2 * (#imagePixels), Thus one of the U or Vt matrix became huge which cannot be allocated on heap, thus this exception std::bad_alloc came, as in my case Vt size will be imagePixels * imagePixels which is huge.
May this is also happening in your case.
Leaving this here so that next person encountering this should have a look on the Matrix size also.
Upvotes: 0