AVFoundation缓冲区与已保存图像的比较

时间:2011-01-16 14:59:05

标签: iphone ios camera buffer avfoundation

我是一名长期读者,第一次在StackOverflow上发表海报,并且必须说它对我来说是一个很好的知识来源。

我试图了解AVFoundation框架。

我想要做的是保存相机看到的内容,然后检测到某些内容发生变化

这是我将图像保存到UIImage的部分:

if (shouldSetBackgroundImage) {
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    // Create a bitmap graphics context with the sample buffer data
    CGContextRef context = CGBitmapContextCreate(rowBase, bufferWidth,
        bufferHeight, 8, bytesPerRow,
        colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    // Create a Quartz image from the pixel data in the bitmap graphics context
    CGImageRef quartzImage = CGBitmapContextCreateImage(context); 

    // Free up the context and color space
    CGContextRelease(context); 
    CGColorSpaceRelease(colorSpace);

    // Create an image object from the Quartz image
    UIImage * image = [UIImage imageWithCGImage:quartzImage];
    [self setBackgroundImage:image];
    NSLog(@"reference image actually set");

    // Release the Quartz image
    CGImageRelease(quartzImage);

    //Signal that the image has been saved
    shouldSetBackgroundImage = NO;

}

这是我检查相机看到的图像是否有任何变化的部分:

else {

    CGImageRef cgImage = [backgroundImage CGImage];
    CGDataProviderRef provider = CGImageGetDataProvider(cgImage);
    CFDataRef bitmapData = CGDataProviderCopyData(provider);
    char* data = CFDataGetBytePtr(bitmapData);

    if (data != NULL)
    {
        int64_t numDiffer = 0, pixelCount = 0;
        NSMutableArray * pointsMutable = [NSMutableArray array];

        for( int row = 0; row < bufferHeight; row += 8 ) {
            for( int column = 0; column < bufferWidth; column += 8 ) {

                //we get one pixel from each source (buffer and saved image)
                unsigned char *pixel = rowBase + (row * bytesPerRow) + (column * BYTES_PER_PIXEL);
                unsigned char *referencePixel = data + (row * bytesPerRow) + (column * BYTES_PER_PIXEL);

                pixelCount++;

                if ( !match(pixel, referencePixel, matchThreshold) ) {
                    numDiffer++;
                    [pointsMutable addObject:[NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH - (column/ (float) bufferHeight)* SCREEN_WIDTH - 4.0, (row/ (float) bufferWidth)* SCREEN_HEIGHT- 4.0)]];
                }
            }
        }
        numberOfPixelsThatDiffer = numDiffer;
        points = [pointsMutable copy];
    }

出于某种原因,这不起作用,这意味着iPhone几乎检测到所有与保存图像不同的内容,即使我在匹配功能中设置了非常低的检测阈值......

你知道我做错了什么吗?

2 个答案:

答案 0 :(得分:1)

人类的眼睛与照相机(即使是非常昂贵的照片)的方式大不相同,因为我们没有感觉到最小的光线变化或小的运动变化。相机DO,他们非常敏感,但根本不聪明!

使用您当前的方法(似乎您正在比较每个像素): 如果帧向右移动1个像素会发生什么?!您可以对算法的结果进行正确的图像,对吗?人类将不会感知任何东西或几乎什么都不会。

还存在相机快门问题:这意味着每个画面可能没有相同的光量。因此,逐像素比较方法太容易失败。

您希望至少预处理图像并提取一些基本功能。也许边缘,角落等OpenCV很容易,但我不确定在iPhone中进行这样的处理会很快。 (这取决于你的图像大小)

或者,您可以尝试天真的template matching algorithm,其模板大小会比您的孔视图大小略短。

图像处理的计算成本很高,所以不要期望它从第一次开始就会很快,特别是在移动设备中,如果你没有图像处理/计算机视觉方面的经验,那就更好了。

希望它有所帮助;)

答案 1 :(得分:1)

我可以想到三种可能性,为什么你可能会看到几乎每个像素都不同:色彩空间转换,像素位置的不正确映射,或者你的阈值对于iPhone相机的实际移动过于敏感。前两个不太可能,所以我认为它可能是第三个,但它们值得检查。

将像素放置在UIImage中时可能会进行一些颜色校正,然后再将其提取出来。您可以尝试简单地将它们从缓冲区存储到其本机状态,然后使用原始缓冲区作为比较点,而不是UIImage的后备数据。

另外,请检查以确保您的行/列算法适用于两个图像中的实际像素位置。也许生成差异图像减去两个图像的绝对差异,然后使用简单的黑/白分割区域作为相机的测试图像。

最可能的情况是整个图像仅仅通过握住它的人手来移动多个像素。这些全帧图像偏移可能导致几乎每个像素在简单比较中不同。您可能需要调整阈值或进行更智能的运动估计,就像在视频压缩程序中使用的那样。

最后,在进行比较操作时,我建议您查看OpenGL ES 2.0着色器以执行此操作。在CPU上进行逐像素比较时,您应该看到一个巨大的加速(在我的基准测试中为14-28倍)。我展示了如何使用this article中的GPU进行基于颜色的阈值处理,其中this iPhone sample application使用GLSL着色器实时跟踪彩色对象。