2012-03-30 12 views
6

Sto cercando di utilizzare la funzione di rilevamento di persone in OpenCV:CGBitmapContextCreate per CV_8UC3 (da utilizzare in 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); 

Ma ottengo il seguente asserzione:

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

e ha senso perché Sto passando un'immagine CV_8UC4.

Quindi ho indovinato che dovrei creare un cvmat con queste caratteristiche. In questo momento ho questi 2 metodi. che mi permettono di ottenere grigi oa colori cvmats (CV_8UC1/CV_8UC4)

Per Colore:

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

Per Scala di grigi:

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

e questa è la mia ipotesi di fare 3 canali:

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

ma ottengo il seguente errore:

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

Quindi la mia domanda è: qual è il modo corretto di creare un CGBitmapContext compatibile 8UC3? (presumo che l'8UC3 significhi 8 bit per pixel con canali RGB)

Grazie.

PD: il codice di trasformazione dell'immagine è di Robin Summerhill.

risposta

0

Si sta creando correttamente un'immagine a 3 canali utilizzando CV_8UC3. Poiché CGBitmapContextCreate prevede 9792 byte/riga, ciò significa che devono essere presenti colonne 3264 (di pixel a 3 canali). Se si esegue il seguente codice,

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

emette 9792 come richiesto dalla CGBitmapContextCreate. Puoi dire cosa sta restituendo nel tuo codice cvMat.step[0]? Sembra corretto, ma forse sta succedendo qualcos'altro.

Inoltre, nota che OpenCV archivia in modo nativo i dati nel formato BGR se si ottengono i dati di immagine da funzioni OpenCV come imread ecc. Quindi, se il colore è strano, prestare attenzione.

+0

Ciao questo è il risultato: – Pochi

+0

cols: 2448.000000, righe: 3264.000000, 7344, Ma non capisco, questa funzione funziona per i miei altri formati. Questa immagine proviene dall'iPhone. – Pochi

+0

Qualcosa di strano sta succedendo qui ... Il passo di 7344 è esattamente 2448.0 * 3. Quindi, sembra che le colonne e le righe vengano scambiate da qualche parte. Anche se, non sembra dal tuo codice. Qualcosa come l'inclinazione dello schermo si verifica causando la trasposizione delle dimensioni? – mevatron

3

Un approccio diverso potrebbe essere la creazione di una matrice CV_8UC4 e poi dividere i canali, ottenendo una matrice BGR, e una matrice alfa (scartato in questo 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

ho usato il tuo modo mix, ma è non funziona: il risultato è un'immagine a colori RGB, ma perde molti colori.

Così ho un modo molto semplice per la conversione, ed è successo

Questo codice è in XCode:

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

Sarà convertire lastImage al colore RGB, con stile CV_8UC3.

Siamo spiacenti perché è la prima volta che commento e non so come formattare questo.

Problemi correlati