iPhone 上的灰度图像的图像数据是如何解释的?

发布于 2024-10-07 22:22:54 字数 3685 浏览 6 评论 0原文

在给定以下场景的情况下,如何理解灰度图像的图像数据:我从“样本缓冲区”捕获视频数据并提取 80x20 部分,然后将其转换为灰度 UIImage。但是,当我检查原始像素字节时,我无法以一种允许我继续“二值化”它们(我真正的目标)的方式理解它们。

当我简单地使用 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 字节)

How do I make sense of the image data for a grayscale image given the following scenario: I capture video data from the "sample buffer" and extract an 80x20 section and then turn that into a grayscale UIImage. But when I examine the raw pixel bytes I am unable to make sense of them in a way that would allow me to go on and "binarize" them (my real goal).

When I simply save the UIImage to the photo album using UIImageWriteToSavedPhotosAlbum to verify just what kind of image data I have, I indeed get a plain, white 80x20 image (it's actually light-grayish). I captured a plain white image to simplify things, expecting to see only values between, say, 200 or so and 255, and yet there are sections of the image data full of zeroes, that clearly suggest rows of black pixels. Any help is appreciated. The relevant code and the image data (16 pixels at a time) are below.

Here is how I create the 80x20 grayscale image from a portion of the CMSampleBufferRef video data:

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

and then, when I use the following code to dump the pixel data to the Console:

    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]);
}

I consistently get output like following:

-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-

(this pattern repeats for the remaining bytes, 80 bytes of pixel data in the 200's, depending on lighting, followed by 240 bytes of zeros -- there's a total of 1600 bytes since the image is 80x20)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笑脸一如从前 2024-10-14 22:22:54

这:

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

应该是:

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

换句话说,对于8位灰度图像,每行的字节数与宽度相同。

This:

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

Should be:

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

In other words, for an 8 bit gray image, the number of bytes per row is the same as the width.

紙鸢 2024-10-14 22:22:54

您可能忘记了图像步幅 - 您假设图像存储为宽度*高度,但一些系统将它们存储为步幅*高度,其中步幅> 。宽度。零是您应该跳过的填充。

顺便问一下,“二值化”是什么意思?我猜你的意思是量化到较低的灰度级?

You've probably forgotten image stride - you're assuming that your images are stored as width*height but several systems store them as stride*height where stride > width. The zeros are padding that you should skip.

By the way, what do you mean "binarize" ? I guess you mean quantize to a less grey levels ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文