Создайте маску из разницы между двумя изображениями (iPhone)

Как я могу обнаружить разницу между двумя изображениями, создав маску области, которая отличается, чтобы обработать область, общую для обоих изображений (например, размытие по Гауссу)?

эскиз

EDIT: в настоящее время я использую этот код для получения значения пикселей 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 и деления на количество пикселей?). Как я мог это сделать, а затем перевести его в CMask?

Я знаю, что это сложный вопрос, поэтому любая помощь приветствуется.

Спасибо.


person Iñigo Beitia    schedule 10.10.2010    source источник


Ответы (5)


Я думаю, что самый простой способ сделать это — использовать разностный режим наложения. Следующий код основан на коде, который я использую в 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;
}
person Cory Kilger    schedule 17.10.2010
comment
Привет, Кори, код очень полезен, ему удалось создать элементы, которых нет ни на одной фотографии. Однако, похоже, он также создает черный фон, а не прозрачный фон. Есть ли способ убрать черный фон? - person wahkiz; 20.02.2013

Есть три причины, по которым пиксели будут меняться от одной фотографии iPhone к другой, изменение объекта, перемещение iPhone и случайный шум. Я предполагаю, что для этого вопроса вас больше всего интересуют изменения темы, и вы хотите обработать эффекты двух других изменений. Я также предполагаю, что приложение предназначено для того, чтобы пользователь удерживал iPhone достаточно неподвижно, поэтому изменения движения iPhone менее значительны, чем изменения предмета.

Чтобы уменьшить влияние случайного шума, просто немного размойте изображение. Простого усредняющего размытия, когда каждый пиксель результирующего изображения представляет собой среднее значение исходного пикселя с его ближайшими соседями, должно быть достаточно, чтобы сгладить любой шум на достаточно хорошо освещенном изображении iPhone.

Чтобы устранить движение iPhone, вы можете запустить алгоритм обнаружения функций на каждом изображении (для начала посмотрите определение функций в Википедии). Затем вычислите преобразования, необходимые для выравнивания наименее измененных обнаруженных объектов.

Примените это преобразование к размытым изображениям и найдите разницу между изображениями. Любые пиксели с достаточной разницей станут вашей маской. Затем вы можете обработать маску, чтобы устранить любые островки измененных пикселей. Например, субъект может быть одет в однотонную рубашку. Субъект может переходить от одного изображения к другому, но область однотонной рубашки может перекрываться, в результате чего получается маска с отверстием посередине.

Другими словами, это существенная и сложная проблема обработки изображений. Вы не найдете ответ в сообщении stackoverflow.com. Ответ вы найдете в учебнике по цифровой обработке изображений.

person Mr. Berna    schedule 19.10.2010
comment
Спасибо за ваш ответ, мистер Берна. Я знаю, что это сложный вопрос, и ценю ваши советы. Я обязательно проведу некоторое исследование обработки изображений, чтобы решить эту проблему. - person Iñigo Beitia; 19.10.2010

Разве вы не можете просто вычесть значения пикселей из изображений и обработать пиксели, где разница равна 0?

person Ross    schedule 12.10.2010
comment
@ Росс, спасибо за ответ. Моя проблема в том, что я не знаю, как создать маску пикселей, где значения RGBA разные. - person Iñigo Beitia; 12.10.2010

Каждый пиксель, который не имеет аналогичного пикселя на другом изображении в пределах определенного радиуса, может считаться частью маски. Он медленный (хотя и не так уж много, что было бы быстрее), но работает достаточно просто.

person TaslemGuy    schedule 13.10.2010

Пройдитесь по пикселям, скопируйте отличающиеся на нижнем изображении в новый (не непрозрачный).

Полностью размойте верхний, затем покажите новый сверху.

person Thyraz    schedule 13.10.2010
comment
Как именно я могу скопировать пиксели на новое изображение? - person Iñigo Beitia; 14.10.2010