Подтвердить что ты не робот

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

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

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

Спасибо.

4b9b3361

Ответ 1

Как быстрый, простой алгоритм, я предлагаю перебирать около 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

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

- (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 без учета альфа-канала. Возможно, вам нужно будет адаптировать его, если это не совсем ваш случай.