【问题标题】:Create a mask from difference between two images (iPhone)根据两个图像之间的差异创建蒙版 (iPhone)
【发布时间】:2010-10-10 17:48:31
【问题描述】:

如何检测两张图像之间的差异,创建不同区域的蒙版以处理两张图像共有的区域(例如高斯模糊)?

编辑:我目前正在使用此代码来获取像素的 RGBA 值:

+ (NSArray*)getRGBAsFromImage:(UIImage*)image atX:(int)xx andY:(int)yy count:(int)count
{
    NSMutableArray *result = [NSMutableArray arrayWithCapacity:count];

    // First get the image into your data buffer
    CGImageRef imageRef = [image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    unsigned char *rawData = malloc(height * width * 4);
    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                    bitsPerComponent, bytesPerRow, colorSpace,
                    kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);

    // Now your rawData contains the image data in the RGBA8888 pixel format.
    int byteIndex = (bytesPerRow * yy) + xx * bytesPerPixel;
    for (int ii = 0 ; ii < count ; ++ii)
    {
        CGFloat red   = (rawData[byteIndex]     * 1.0) / 255.0;
        CGFloat green = (rawData[byteIndex + 1] * 1.0) / 255.0;
        CGFloat blue  = (rawData[byteIndex + 2] * 1.0) / 255.0;
        CGFloat alpha = (rawData[byteIndex + 3] * 1.0) / 255.0;
        byteIndex += 4;

        UIColor *acolor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
        [result addObject:acolor];
    }

  free(rawData);

  return result;
}

问题是,图像是从 iPhone 的摄像头捕获的,因此它们的位置并不完全相同。我需要创建几个像素的区域并提取该区域的一般颜色(也许通过将 RGBA 值相加并除以像素数?)。我怎样才能做到这一点,然后将其翻译成 CGMask?

我知道这是一个复杂的问题,因此非常感谢任何帮助。

谢谢。

【问题讨论】:

    标签: iphone image-processing core-graphics mask


    【解决方案1】:

    我认为最简单的方法是使用差异混合模式。以下代码基于我在CKImageAdditions 中使用的代码。

    + (UIImage *) differenceOfImage:(UIImage *)top withImage:(UIImage *)bottom {
        CGImageRef topRef = [top CGImage];
        CGImageRef bottomRef = [bottom CGImage];
    
        // Dimensions
        CGRect bottomFrame = CGRectMake(0, 0, CGImageGetWidth(bottomRef), CGImageGetHeight(bottomRef));
        CGRect topFrame = CGRectMake(0, 0, CGImageGetWidth(topRef), CGImageGetHeight(topRef));
        CGRect renderFrame = CGRectIntegral(CGRectUnion(bottomFrame, topFrame));
    
        // Create context
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        if(colorSpace == NULL) {
            printf("Error allocating color space.\n");
            return NULL;
        }
    
        CGContextRef context = CGBitmapContextCreate(NULL,
                                                     renderFrame.size.width,
                                                     renderFrame.size.height,
                                                     8,
                                                     renderFrame.size.width * 4,
                                                     colorSpace,
                                                     kCGImageAlphaPremultipliedLast);
        CGColorSpaceRelease(colorSpace);
    
        if(context == NULL) {
            printf("Context not created!\n");
            return NULL;
        }
    
        // Draw images
        CGContextSetBlendMode(context, kCGBlendModeNormal);
        CGContextDrawImage(context, CGRectOffset(bottomFrame, -renderFrame.origin.x, -renderFrame.origin.y), bottomRef);
        CGContextSetBlendMode(context, kCGBlendModeDifference);
        CGContextDrawImage(context, CGRectOffset(topFrame, -renderFrame.origin.x, -renderFrame.origin.y), topRef);
    
        // Create image from context
        CGImageRef imageRef = CGBitmapContextCreateImage(context);
        UIImage * image = [UIImage imageWithCGImage:imageRef];
        CGImageRelease(imageRef);
    
        CGContextRelease(context);
    
        return image;
    }
    

    【讨论】:

    • 你好 Cory,代码非常有用,它设法生成了任何一张照片中都不存在的元素。但是,它似乎也会产生黑色背景,而不是透明背景。有没有办法去除黑色背景?
    【解决方案2】:

    像素从一张 iPhone 照片到另一张照片的变化有以下三个原因:主题改变、iPhone 移动和随机噪点。我假设对于这个问题,您对主题更改最感兴趣,并且您希望处理其他两个更改的影响。我还假设该应用旨在让用户合理地保持 iPhone 静止,因此 iPhone 的移动变化不如主题变化那么重要。

    要减少随机噪声的影响,只需稍微模糊一下图像即可。一个简单的平均模糊,其中生成图像中的每个像素都是原始像素及其最近邻像素的平均值,应该足以消除光线充足的 iPhone 图像中的任何噪点。

    要解决 iPhone 的移动问题,您可以对每张图像运行特征检测算法(首先在 Wikipedia 上查找特征检测)。然后计算对齐最小变化的检测到的特征所需的变换。

    将该变换应用于模糊图像,并找出图像之间的差异。任何具有足够差异的像素都将成为您的蒙版。然后,您可以处理蒙版以消除任何已更改像素的孤岛。例如,对象可能穿着纯色衬衫。拍摄对象可能会从一个图像移动到下一个图像,但纯色衬衫的区域可能会重叠,从而导致中间有孔的蒙版。

    换句话说,这是一个重大而困难的图像处理问题。您不会在 stackoverflow.com 帖子中找到答案。您将在数字图像处理教科书中找到答案。

    【讨论】:

    • 感谢伯纳先生的回答。我知道这是一个复杂的问题,并感谢您的提示。为了解决这个问题,我一定会做一些图像处理研究。
    【解决方案3】:

    你不能只从图像中减去像素值,然后处理差为 0 的像素吗?

    【讨论】:

    • @罗斯,谢谢你的回答。我的问题是我不知道如何创建 RGBA 值不同的像素的蒙版。
    【解决方案4】:

    在某个半径范围内,在其他图像中没有适当相似像素的每个像素都可以被视为掩码的一部分。它很慢,(虽然没有什么比这更快的了)但它的工作原理相当简单。

    【讨论】:

      【解决方案5】:

      遍历像素,将下图中不同的像素复制到新的像素(不透明)。

      完全模糊上面的,然后显示上面的新的。

      【讨论】:

      • 如何将像素复制到新图像上?
      猜你喜欢
      • 2014-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-27
      • 2013-07-20
      • 2019-06-07
      相关资源
      最近更新 更多