将SVD应用于OpenCV中的YCbCr图像

时间:2012-04-08 08:15:55

标签: c++ opencv svd

我正在尝试将图像水印成视频序列。该过程需要将帧分解为SVD,我试图使用下面的部分代码实现。第47行的SVD构造函数因分段错误而失败。 gdb报告以下错误:

“程序接收信号SIGSEGV,分段故障。 来自/usr/lib/liblapack.so.3gf的dlange_()中的0xb5d31ada“

#include <iostream>
#include <stdio.h>
#include "cv.h"
#include "highgui.h"
const unsigned int MAX = 10000;

using namespace cv;
using namespace std;

int NO_FRAMES;

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];
namedWindow("watermark",1);
namedWindow("RGB", 1);
namedWindow("YCBCR",1);
VideoCapture capture(argv[1]);
Mat watermark = imread(argv[2]);
int i=0;
        capture >> rgb[i];
imshow("watermark", watermark);
while(!rgb[i].empty())
{
imshow("RGB", rgb[i]);
cvtColor(rgb[i], ycbcr[i], CV_RGB2YCrCb);
imshow("YCBCR", ycbcr[i]);
i++;
capture >> rgb[i];

cout<<"frame "<<i<<endl;
if(check_exit())
exit(0);
}
//This line creates Segmentation fault
SVD temp(rgb[0]);
capture.release();
return 0;
}

1 个答案:

答案 0 :(得分:0)

更熟悉C接口,我只会描述一些在C ++代码中看起来不合适的东西:

SVD()函数要求输入图像是浮点图像,因此您可能需要将标度从标准8位转换为32位。这里有一些非常基本(而且效率不高)的代码用于说明目的:

int N = img->width;
IplImage* W = cvCreateImage( cvSize(N, 1), IPL_DEPTH_32F , 1 );
IplImage* A = cvCreateImage( cvGetSize(img), IPL_DEPTH_32F , 1 );
cvConvertScale(img, A);

IplImage* W_mod = cvCreateImage( cvSize(N-l, 1), IPL_DEPTH_32F , 1 );
cvSVD(A, W, NULL, NULL, CV_SVD_MODIFY_A);

SVD值存储在名为 W 的Nx1矩阵(在本例中为IplImage)中。输入图像 img A 中转换为32位。我们使用CV_SVD_MODIFY_A标志使其更快并修改 A 中的值。其他选项留空(NULL),但您可以根据需要提供参数。请查看OpenCV文档。

希望您能够从这个工作代码中找出C ++代码中的错误。