2012-03-30 74 views
6

我试图使用OpenCV的人检测功能:CGBitmapContextCreate为CV_8UC3(OpenCV中使用)

cv::HOGDescriptor hog; 
hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector()); 
std::vector<cv::Rect> found; 
hog.detectMultiScale(noMask, found, 0.2, cv::Size(8,8), cv::Size(16,16), 1.05, 2); 

,但我得到了以下断言:

OpenCV Error: Assertion failed (img.type() == CV_8U || img.type() == CV_8UC3) in computeGradient, file /Users/robin/Projects/OpenCVForiPhone/opencv/opencv/modules/objdetect/src/hog.cpp, line 174

它是有道理的,因为我正在传递一张CV_8UC4图片。

所以我猜想我应该创建一个具有这个特征的cvmat。现在我有这2种方法。这让我获得灰色或彩色cvmats(CV_8UC1/CV_8UC4)

对于颜色:

-(cv::Mat)CVMat 
{ 

    CGColorSpaceRef colorSpace = CGImageGetColorSpace(self.CGImage); 
    CGFloat cols = self.size.width; 
    CGFloat rows = self.size.height; 

    cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels 

    CGContextRef contextRef = CGBitmapContextCreate(cvMat.data,     // Pointer to backing data 
                cols,      // Width of bitmap 
                rows,      // Height of bitmap 
                8,       // Bits per component 
                cvMat.step[0],    // Bytes per row 
                colorSpace,     // Colorspace 
                kCGImageAlphaNoneSkipLast | 
                kCGBitmapByteOrderDefault); // Bitmap info flags 

    CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), self.CGImage); 
    CGContextRelease(contextRef); 

    return cvMat; 
} 

灰度:

-(cv::Mat)CVGrayscaleMat 
{ 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); 
    CGFloat cols = self.size.width; 
    CGFloat rows = self.size.height; 

    cv::Mat cvMat = cv::Mat(rows, cols, CV_8UC1); // 8 bits per component, 1 channel 

    CGContextRef contextRef = CGBitmapContextCreate(cvMat.data,     // Pointer to backing data 
                cols,      // Width of bitmap 
                rows,      // Height of bitmap 
                8,       // Bits per component 
                cvMat.step[0],    // Bytes per row 
                colorSpace,     // Colorspace 
                kCGImageAlphaNone | 
                kCGBitmapByteOrderDefault); // Bitmap info flags 

    CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), self.CGImage); 
    CGContextRelease(contextRef); 
    CGColorSpaceRelease(colorSpace); 

    return cvMat; 
} 

这是我的猜测,使它3频道:

-(cv::Mat)CVMat3Channels 
{ 

    //CGColorSpaceRef colorSpace = CGImageGetColorSpace(self.CGImage); 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGFloat cols = self.size.width; 
    CGFloat rows = self.size.height; 

    cv::Mat cvMat(rows, cols, CV_8UC3); // 8 bits per component, 3 channels 

    CGContextRef contextRef = CGBitmapContextCreate(cvMat.data,    // Pointer to backing data 
                cols,      // Width of bitmap 
                rows,      // Height of bitmap 
                8,       // Bits per component 
                cvMat.step[0],    // Bytes per row 
                colorSpace,     // Colorspace 
                kCGImageAlphaNoneSkipLast | 
                kCGBitmapByteOrderDefault); // Bitmap info flags 

    CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), self.CGImage); 
    CGContextRelease(contextRef); 
    CGColorSpaceRelease(colorSpace); 

    return cvMat; 
} 

,但我得到了以下错误:

<Error>: CGBitmapContextCreate: invalid data bytes/row: should be 
     at least 9792 for 8 integer bits/component, 3 components, 
     kCGImageAlphaNoneSkipLast. 
<Error>: CGContextDrawImage: invalid context 0x0 

所以我的问题是,什么是创造一个8UC3兼容CGBitmapContext的正确方法是什么? (我认为8UC3意味着每个像素RGB通道8位)

谢谢。

PD:图像转换代码来自Robin Summerhill。

回答

0

您正在通过使用CV_8UC3正确创建3通道图像。由于CGBitmapContextCreate预计为9792字节/行,这意味着应该有3264列(3通道像素)。如果我运行下面的代码,如由CGBitmapContextCreate需要

int cols = 3264; 
int rows = 1960; // assuming a ~1.66 aspect ratio here... 
Mat temp(rows, cols, CV_8UC3); 
cout << temp.step[0] << endl; 

它输出9792。你能告诉cvMat.step[0]在代码中返回什么吗?它看起来是正确的,但也许其他事情正在发生。

此外,如果您从OpenCV函数(如imread等)获取图像数据,则说明OpenCV本地存储BGR格式的数据。因此,如果颜色看起来很奇怪,请注意这一点。

+0

你好,这是结果: – Pochi 2012-04-01 18:17:52

+0

cols:2448.000000, rows:3264.000000, 7344,但我不明白,这个功能适用于我的其他格式。这张图片来自iphone。 – Pochi 2012-04-01 18:19:15

+0

这里发生了一些可疑的事情...... 7344的步骤正好是2448.0 * 3.因此,看起来你的列和行在某处被交换。虽然,它看起来不像你的代码。是否像屏幕倾斜发生导致尺寸转置? – mevatron 2012-04-02 13:21:57

3

一种不同的方法可能会创建一个CV_8UC4矩阵,然后分裂渠道,获得BGR矩阵,和阿尔法矩阵(在这种情况下丢弃):我用你的组合方式

cv::Mat CVMat(CGImageRef cgimage) 
{ 

    CGColorSpaceRef colorSpace = CGImageGetColorSpace(cgimage); 
    CGFloat cols = CGImageGetWidth(cgimage); 
    CGFloat rows = CGImageGetHeight(cgimage); 

    cv::Mat rgba(rows, cols, CV_8UC4, Scalar(1,2,3,4)); // 8 bits per component, 4 channels 

    CGContextRef contextRef = CGBitmapContextCreate(rgba.data,     // Pointer to backing data 
                cols,      // Width of bitmap 
                rows,      // Height of bitmap 
                8,       // Bits per component 
                rgba.step[0],    // Bytes per row 
                colorSpace,     // Colorspace 
                kCGImageAlphaNoneSkipLast | 
                kCGBitmapByteOrderDefault); // Bitmap info flags 

    CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), cgimage); 
    CGContextRelease(contextRef); 

    Mat bgr(rgba.rows, rgba.cols, CV_8UC3); 
    Mat alpha(rgba.rows, rgba.cols, CV_8UC1); 

    Mat out[] = { bgr, alpha }; 
    // rgba[0] -> bgr[2], rgba[1] -> bgr[1], 
    // rgba[2] -> bgr[0], rgba[3] -> alpha[0] 
    int from_to[] = { 0,2, 1,1, 2,0, 3,3 }; 
    mixChannels(&rgba, 1, out, 2, from_to, 4); 

    return bgr; 
} 
6

,但它的不工作:结果是RGB彩色图像,但失去了许多颜色。

所以我有一个非常简单的方法来转换,这是成功的

此代码是在XCode中:

lastImage = [firstImage CVMat]; 
cv::cvtColor(lastImage , lastImage , CV_RGBA2RGB); 

它将lastImage转换为RGB颜色,与CV_8UC3风格。

对不起,因为这是我第一次评论,我不知道如何格式化。