2012-04-10 4 views
0

CV_32FC1 cvMat에 SVD를 적용하고 'u'구성 요소의 일부 값을 수정했습니다. 이제는 단일 행렬 A를 얻기 위해 'u, w'및 'vt'구성 요소를 곱하려고합니다. 그러나 OpenCV는 행렬에 다음 오류를 곱하지 못합니다. OpenCV에서 행렬의 SVD 구성 요소 곱하기

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 객체의 행렬의 유형을 검사

, 그들은 기본 매트릭스 형식의 일치하지 않는 유형 = 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; 
} 
+0

구성 요소를 수정하지 않으면 작동합니까? – DRVic

+0

@DRVic 아니요 둘 중 하나도 작동하지 않습니다. – blacktooth

+0

글쎄, 그건 단서가됩니다. 요소를 수정하는 것이 아닙니다. 나는 당신이 SVD를 얻으려는 루틴에 대해 많이 알지 못한다. 그러나 나는 루프 안에서'SVD temp (dst, 5); '를 호출하는 것을 방해하고 svd [i에 결과를 할당한다. ], 그 후에 temp는 범위를 벗어날 수 있습니다. svd [i]의 복사본이 완전한 복사본을 작성합니까? – DRVic

답변

0

가 나는 또한 SVD를 계산하는 동안 거대한되었다 따라서, 내 경우에는, 여기에 U 또는 버몬트 매트릭스 중 하나를 을 내 크기가 2 * (#imagePixels) 같았다 작성해야 생각, 지금이 발생하는 수 없습니다 힙에 할당되므로이 예외 std :: bad_alloc이 생겼다. 필자의 경우 Vt 크기는 imagePixels * imagePixels가 될 것이다.

이 경우에도 마찬가지 일 수 있습니다.

다음에이 문제가 발생하는 사람도 매트릭스 크기를 확인해야합니다.

1

부적합한 행렬 A가있는 새 행렬 B를 만들려고하는 다음 줄로 오류가 전파되었지만 행렬 곱셈 연산 (gemm())에 오류가 나타납니다. SVD 알고리즘 OpenCV의 아래 형태의 출력을 생성하는 입력 : 행렬 A (MXN) 들면 를 SVD는 다음 세 행렬 생성 : - 계산 된 특이 값 (분 (m, n)의 X 1)

U w

을 - 계산 된 왼쪽 특이 벡터 (mxm)

vt - 전치 행렬 아닌 차원의 대각 행렬이며, 실제 수학적 동등 우측 특이 값의 (NXN)

여기

특이 값 측정 컴팩트 열 벡터에 저장된다 (X 1 분 (m, N)) (min (m, n), min (m, n)).

따라서 개별 SVD 구성 요소에서 행렬을 재구성하려면 먼저 벡터 'w'를 대각선 행렬 형식으로 가져와야합니다. OpenCV의 diag() 메소드를 사용하여이 작업을 수행 할 수 있습니다.

A = svd[i].u * Mat::diag(svd[i].w) * svd[i].vt;