Создать маску из разницы между двумя изображениями (iPhone) - PullRequest
7 голосов
/ 10 октября 2010

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

sketch

РЕДАКТИРОВАТЬ: В настоящее время я использую этот код для получения значения 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?

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

Спасибо.

Ответы [ 5 ]

6 голосов
/ 17 октября 2010

Я думаю, что самый простой способ сделать это - использовать режим смешивания различий.Следующий код основан на коде, который я использую в 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;
}
2 голосов
/ 19 октября 2010

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

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

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

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

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

0 голосов
/ 13 октября 2010

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

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

0 голосов
/ 14 октября 2010

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

0 голосов
/ 12 октября 2010

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

...