2012-03-30 11 views
6

Estoy tratando de utilizar la función de detección de personas en OpenCV:CGBitmapContextCreate para CV_8UC3 (para usar en 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); 

Pero consigo la siguiente afirmación:

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

y tiene sentido porque Estoy pasando una imagen CV_8UC4.

Así que supuse que debería crear un cvmat con estas características. En este momento tengo estos 2 métodos. que permiten que consiga cvmats grises o en color (CV_8UC1/CV_8UC4)

Para Color:

-(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; 
} 

Para Escala de grises:

-(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; 
} 

y este es mi conjetura para hacer it 3 canales:

-(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; 
} 

pero me da el siguiente error:

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

Así que mi pregunta es, ¿cuál es la forma correcta de crear un CGBitmapContext compatibles 8UC3? (supongo que 8UC3 significa 8 bits por píxel con canales RGB)

Gracias.

PD: El código de transformación de la imagen es de Robin Summerhill.

Respuesta

0

Está creando correctamente una imagen de 3 canales utilizando CV_8UC3. Dado que CGBitmapContextCreate espera 9792 bytes/fila, eso significa que debe haber 3264 columnas (de 3 canales de píxeles). Si funciono el siguiente código,

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

emite 9792 como se requiere por CGBitmapContextCreate. ¿Puedes decir qué cvMat.step[0] está regresando en tu código? Parece correcto, pero tal vez está sucediendo algo más.

Además, tenga en cuenta que OpenCV almacena datos de forma nativa en formato BGR si obtiene datos de imágenes de funciones de OpenCV como imread, etc. Por lo tanto, si el color se ve raro, preste atención.

+0

Hola este es el resultado: – Pochi

+0

cols: 2448.000000, filas: 3264.000000, 7344, pero yo no entiendo, esta función se puede utilizar para mis otros formatos. Esta imagen es del iphone. – Pochi

+0

Algo sospechoso está pasando aquí ... El paso de 7344 es exactamente 2448.0 * 3. Por lo tanto, parece que sus columnas y filas se intercambian en algún lugar. Aunque no se parece a su código. ¿Se está produciendo algo así como la inclinación de la pantalla que hace que las dimensiones se transpongan? – mevatron

3

Un enfoque diferente podría ser la creación de una matriz CV_8UC4 y luego dividir los canales, la obtención de una matriz BGR, y una matriz de alfa (desechado en este caso):

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

utilicé su camino mezcla, pero es no funciona: el resultado es una imagen en color RGB, pero pierde muchos colores.

Así que tienen una manera muy simple para convertir, y es un éxito

Este es el código de XCode:

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

Se convertirá lastImage al color RGB, con el estilo CV_8UC3.

Lo siento porque es la primera vez que comento y no sé cómo formatear esto.

Cuestiones relacionadas