2013-07-16 91 views
2

如何使用vImage從圖像中「提取」僅一個通道? 我的方法現在的問題是:vImageConvert提取一個通道

vImage_Buffer redBuffer; 
redBuffer.data = (void*)redImageData.bytes; 
redBuffer.width = size.width; 
redBuffer.height = size.height; 
redBuffer.rowBytes = [redImageData length]/size.height; 
vImage_Buffer redBuffer2; 
redBuffer2.width = size.width; 
redBuffer2.height = size.height; 
redBuffer2.rowBytes = size.width; 
vImageConvert_RGB888toPlanar8(&redBuffer, &redBuffer2, nil, nil, kvImageNoFlags); 

redBuffer是一個工作的形象,與它沒有任何錯誤,但vImageConvert給了我一個EXC_BAD_ACCESS,我已經試過許多選項和一些導致EXC_BAD_ACCESS有的一個破碎的輸出圖片。我究竟做錯了什麼?

非常感謝Rob Keniger,我已經設法提取通道,但是如果我嘗試將它們與其他通道放在一起,則圖像會水平拉伸並在其中具有RGB條紋。爲什麼他們不正確地放在一起?這裏與提取通道,然後把他們重新走到一起的例子:

vImage_Buffer blueBuffer; 
    blueBuffer.data = (void*)blueImageData.bytes; 
    blueBuffer.width = size.width; 
    blueBuffer.height = size.height; 
    blueBuffer.rowBytes = [blueImageData length]/size.height; 

    vImage_Buffer rBuffer; 
    rBuffer.width = size.width; 
    rBuffer.height = size.height; 
    rBuffer.rowBytes = size.width; 
    void *rPixelBuffer = malloc(size.width * size.height); 
    if(rPixelBuffer == NULL) 
    { 
     NSLog(@"No pixelbuffer"); 
    } 
    rBuffer.data = rPixelBuffer; 

    vImage_Buffer gBuffer; 
    gBuffer.width = size.width; 
    gBuffer.height = size.height; 
    gBuffer.rowBytes = size.width; 
    void *gPixelBuffer = malloc(size.width * size.height); 
    if(gPixelBuffer == NULL) 
    { 
     NSLog(@"No pixelbuffer"); 
    } 
    gBuffer.data = gPixelBuffer; 

    vImage_Buffer bBuffer; 
    bBuffer.width = size.width; 
    bBuffer.height = size.height; 
    bBuffer.rowBytes = size.width; 
    void *bPixelBuffer = malloc(size.width * size.height); 
    if(bPixelBuffer == NULL) 
    { 
     NSLog(@"No pixelbuffer"); 
    } 
    bBuffer.data = bPixelBuffer; 

    vImageConvert_RGB888toPlanar8(&blueBuffer, &rBuffer, &gBuffer, &bBuffer, kvImageNoFlags); 

    size_t destinationImageBytesLength = size.width*size.height*3; 
    const void* destinationImageBytes = valloc(destinationImageBytesLength); 
    NSData* destinationImageData = [[NSData alloc] initWithBytes:destinationImageBytes length:destinationImageBytesLength]; 
    vImage_Buffer destinationBuffer; 
    destinationBuffer.data = (void*)destinationImageData.bytes; 
    destinationBuffer.width = size.width; 
    destinationBuffer.height = size.height; 
    destinationBuffer.rowBytes = [destinationImageData length]/size.height; 

    vImage_Error result = vImageConvert_Planar8toRGB888(&rBuffer, &gBuffer, &bBuffer, &destinationBuffer, 0); 
    NSImage* image = nil; 
    if(result == kvImageNoError) 
    { 
     //TODO: If you need color matching, use an appropriate colorspace here 
     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
     CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef)(destinationImageData)); 
     CGImageRef finalImageRef = CGImageCreate(size.width, size.height, 8, 24, destinationBuffer.rowBytes, colorSpace, kCGBitmapByteOrder32Big|kCGImageAlphaNone, dataProvider, NULL, NO, kCGRenderingIntentDefault); 
     CGColorSpaceRelease(colorSpace); 
     CGDataProviderRelease(dataProvider); 
     image = [[NSImage alloc] initWithCGImage:finalImageRef size:NSMakeSize(size.width, size.height)]; 
     CGImageRelease(finalImageRef); 
    } 
    free((void*)destinationImageBytes); 
    return image; 

回答

2

你沒有初始化的redBuffer2輸出緩衝區,所以你沒有任何地方來存儲函數的輸出。

//allocate a buffer for the output image and check it exists 
void *pixelBuffer = malloc(size.width * size.height); 
if(pixelBuffer == NULL) 
{ 
    NSLog(@"No pixelbuffer"); 
    //handle this somehow 
} 

//assign the allocated buffer to the vImage buffer struct 
redBuffer2.data = pixelBuffer; 
+0

謝謝你是這個問題:)但我沒有得到一個正確的圖像,當我把它們放回到一起(見編輯的問題) – thomasguenzel

+0

你應該創建第二個問題關於你的新問題。 –

2

vImageConvert_RGB888toPlanar8不接受vImage_Buffer結構的NULL指針。該函數被標記爲VIMAGE_NON_NULL(1,2,3,4),這應該會讓你的編譯器抱怨這種用法。

在OS X.10或iOS 8上增加了vImageExtractChannel_ARGB8888,但沒有RGB888等價物。如果你需要,你應該提交一個功能請求。 http://bugreporter.apple.com與此同時,您可以製作三個planar8輸出緩衝區並丟棄兩個。

3

溶液(或至少一個的開始):

err = vImageExtractChannel_ARGB8888(&_src, &_blu, 2, kvImageNoError); 
... 
uint8_t copyMask = 1; 
vImageOverwriteChannels_ARGB8888(&_blu, &_src, &_dst, copyMask, kvImageNoFlags); 

這爲我工作,但在我開發的iOS相機應用的OpenCV的版本;預覽窗口在一側顯示白色條紋,每次OpenCV都不喜歡我做某事的方式。我不認爲這會是你的問題,並且看到你的多行代碼只有三行代碼,所以值得一試。