Как сравнить одно изображение с другим, чтобы увидеть, насколько они похожи на определенный процент на iPhone? - PullRequest
13 голосов
/ 27 июня 2011

Я в основном хочу взять два изображения, снятые с камеры на iPhone или iPad 2, и сравнить их друг с другом, чтобы увидеть, являются ли они практически одинаковыми. Очевидно, что из-за света и т. Д. Изображение никогда не будет ТОЧНО одинаковым, поэтому я хотел бы проверить совместимость примерно на 90%.

Все остальные подобные вопросы, которые я видел здесь, были либо не для iOS, либо для поиска объектов на изображениях. Я просто хочу увидеть, похожи ли два изображения.

Спасибо.

Ответы [ 2 ]

8 голосов
/ 27 июня 2011

В качестве быстрого и простого алгоритма я бы предложил перебирать около 1% пикселей в каждом изображении и либо сравнивать их непосредственно друг с другом, либо сохранять скользящее среднее, а затем сравнивать два средних значения цвета в конце.

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

Тогда вы можете использовать алгоритм, примерно такой:

float numDifferences = 0.0f;
float totalCompares = width * height / 100.0f;
for (int yCoord = 0; yCoord < height; yCoord += 10) {
    for (int xCoord = 0; xCoord < width; xCoord += 10) {
        int img1RGB[] = [image1 getRGBForX:xCoord andY: yCoord];
        int img2RGB[] = [image2 getRGBForX:xCoord andY: yCoord];
        if (abs(img1RGB[0] - img2RGB[0]) > 25 || abs(img1RGB[1] - img2RGB[1]) > 25 || abs(img1RGB[2] - img2RGB[2]) > 25) {
            //one or more pixel components differs by 10% or more
            numDifferences++;
        }
    }
}

if (numDifferences / totalCompares <= 0.1f) {
    //images are at least 90% identical 90% of the time
}
else {
    //images are less than 90% identical 90% of the time
}
2 голосов
/ 30 октября 2013

Исходя из идеи Арофа, это моя полная реализация.Он проверяет, совпадают ли некоторые случайные пиксели.Для того, что мне было нужно, он работает безупречно.

- (bool)isTheImage:(UIImage *)image1 apparentlyEqualToImage:(UIImage *)image2 accordingToRandomPixelsPer1:(float)pixelsPer1
{
    if (!CGSizeEqualToSize(image1.size, image2.size))
    {
        return false;
    }

    int pixelsWidth = CGImageGetWidth(image1.CGImage);
    int pixelsHeight = CGImageGetHeight(image1.CGImage);

    int pixelsToCompare = pixelsWidth * pixelsHeight * pixelsPer1;

    uint32_t pixel1;
    CGContextRef context1 = CGBitmapContextCreate(&pixel1, 1, 1, 8, 4, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipFirst);
    uint32_t pixel2;
    CGContextRef context2 = CGBitmapContextCreate(&pixel2, 1, 1, 8, 4, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipFirst);

    bool isEqual = true;

    for (int i = 0; i < pixelsToCompare; i++)
    {
        int pixelX = arc4random() % pixelsWidth;
        int pixelY = arc4random() % pixelsHeight;

        CGContextDrawImage(context1, CGRectMake(-pixelX, -pixelY, pixelsWidth, pixelsHeight), image1.CGImage);
        CGContextDrawImage(context2, CGRectMake(-pixelX, -pixelY, pixelsWidth, pixelsHeight), image2.CGImage);

        if (pixel1 != pixel2)
        {
            isEqual = false;
            break;
        }
    }
    CGContextRelease(context1);
    CGContextRelease(context2);

    return isEqual;
}

Использование:

[self isTheImage:image1 apparentlyEqualToImage:image2
accordingToRandomPixelsPer1:0.001]; // Use a value between 0.0001 and 0.005

Согласно моим тестам производительности, 0,005 (0,5% пикселей) являетсямаксимальное значение, которое вы должны использовать.Если вам нужна большая точность, просто сравните все изображения , используя эту .0,001 кажется безопасным и хорошо работающим значением.Для больших изображений (например, от 0,5 до 2 мегапикселей или миллионов пикселей) я использую 0,0001 (0,01%) , и он работает великолепно и невероятно быстро, никогда не ошибается.

Но, конечно, коэффициент ошибок будет зависеть от типа изображений, которые вы используете.Я использую скриншоты UIWebView, и 0,0001 работает хорошо, но вы, вероятно, можете использовать гораздо меньше, если сравниваете реальные фотографии (даже фактически сравниваете только один случайный пиксель).Если вы имеете дело с очень похожими изображениями, разработанными на компьютере, вам определенно нужна большая точность.

Примечание. Я всегда сравниваю изображения ARGB без учета альфа-канала.Возможно, вам придется адаптировать его, если это не совсем ваш случай.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...