2

次のシナリオでは、グレースケール イメージのイメージ データをどのように理解すればよいでしょうか。「サンプル バッファー」からビデオ データをキャプチャし、80x20 セクションを抽出して、それをグレースケール UIImage に変換します。しかし、生のピクセルバイトを調べると、続けて「2値化」できるような方法でそれらを理解することができません(私の本当の目標)。

UIImageWriteToSavedPhotosAlbum を使用して UIImage をフォト アルバムに保存して、どのような種類の画像データがあるかを確認すると、実際には無地の白い 80x20 画像 (実際には薄い灰色がかった画像) が得られます。200 程度から 255 の間の値のみが表示されることを期待して、物事を単純化するために真っ白な画像をキャプチャしましたが、画像データにはゼロでいっぱいのセクションがあり、明らかに黒いピクセルの行を示しています。どんな助けでも大歓迎です。関連するコードと画像データ (一度に 16 ピクセル) は以下のとおりです。

CMSampleBufferRef ビデオ データの一部から 80x20 グレースケール イメージを作成する方法を次に示します。

UIImage *imageFromImage(UIImage *image, CGRect rect)
{   
    CGImageRef sourceImageRef = [image CGImage];  
    CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, rect);  
    
    CGImageRef grayScaleImg = grayscaleCGImageFromCGImage(newImageRef);
    CGImageRelease(newImageRef);  
    
    UIImage *newImage = [UIImage imageWithCGImage:grayScaleImg scale:1.0 orientation:UIImageOrientationLeft]; 
    
    return newImage;  
}  

CGImageRef grayscaleCGImageFromCGImage(CGImageRef inputImage) 
{
    size_t width = CGImageGetWidth(inputImage);
    size_t height = CGImageGetHeight(inputImage);
    
    // Create a gray scale context and render the input image into that
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
    CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 
                    4*width, colorspace, kCGBitmapByteOrderDefault);
    
    CGContextDrawImage(context, CGRectMake(0,0, width,height), inputImage);
    
    // Get an image representation of the grayscale context which the input
    //    was rendered into.
    CGImageRef outputImage = CGBitmapContextCreateImage(context);
    
    // Cleanup
    CGContextRelease(context);
    CGColorSpaceRelease(colorspace);
    
    return (CGImageRef)[(id)outputImage autorelease];
}

次に、次のコードを使用してピクセル データをコンソールにダンプします。

    CGImageRef inputImage = [imgIn CGImage];
CGDataProviderRef dataProvider = CGImageGetDataProvider(inputImage);
CFDataRef imageData = CGDataProviderCopyData(dataProvider);
const UInt8 *rawData = CFDataGetBytePtr(imageData);

size_t width = CGImageGetWidth(inputImage);
    size_t height = CGImageGetHeight(inputImage);

    size_t numPixels = height * width;
for (int i = 0; i < numPixels ; i++)
{   
   if ((i % 16) == 0)
          NSLog(@" -%i-%i-%i-%i-%i-%i-%i-%i-%i-%i-%i-%i-%i-%i-%i-%i-\n\n", rawData[i],         
             rawData[i+1], rawData[i+2], rawData[i+3], rawData[i+4], rawData[i+5], 
             rawData[i+6], rawData[i+7], rawData[i+8], rawData[i+9], rawData[i+10], 
             rawData[i+11], rawData[i+12], rawData[i+13], rawData[i+14], rawData[i+15]);
}

次のような出力が一貫して得られます。

-216-217-214-215-217-215-216-213-214-214-214-215-215-217-216-216-

-219-219-216-219-220-217-212-214-215-214-217-220-219-217-214-219-

-216-216-218-217-218-221-217-213-214-212-214-212-212-214-214-213-

-213-213-212-213-212-214-216-214-212-210-211-210-213-210-213-208-

-212-208-208-210-206-207-206-207-210-205-206-208-209-210-210-207-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-

(このパターンは、照明に応じて 200 年代の 80 バイトのピクセル データの残りのバイトに対して繰り返され、その後に 240 バイトのゼロが続きます。画像は 80x20 であるため、合計 1600 バイトになります)

4

2 に答える 2

1

これ:

CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 
                4*width, colorspace, kCGBitmapByteOrderDefault);

する必要があります:

CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 
                width, colorspace, kCGBitmapByteOrderDefault);

つまり、8ビットのグレー画像の場合、1行あたりのバイト数は幅と同じです。

于 2010-12-13T23:41:52.923 に答える
0

画像のストライドを忘れている可能性があります。画像は幅*高さとして保存されていると想定していますが、ストライド > 幅のストライド*高さとして保存するシステムもいくつかあります。ゼロは、スキップする必要があるパディングです。

ところで、「二値化」って何?より少ないグレーレベルに量子化することを意味していると思いますか?

于 2010-12-13T23:19:29.747 に答える