Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Поиск совпадающих картинок (http://www.flasher.ru/forum/showthread.php?t=195160)

bav 01.03.2013 12:34

Поиск совпадающих картинок
 
Вложений: 4
Привет, ребята :)
Вот в чем суть проблемы: есть папка A, в которой имеется порядка 10 000 изображений такого вида:
Вложение 29208 Вложение 29209
и есть папка B, в которой имеется порядка 100 изображений такого вида:
Вложение 29210 Вложение 29211
И задача состоит в том, что нужно среди изображений из папки A найти совпадающие с изображениями из папки B. Также известно следующее:
1) Водяной знак присутствует только на картинках из папки B, располагается в центре изображения и имеет фиксированные размеры.
2) Если картинки совпадают, как на примере выше, то они точно имеют одинаковые размеры и отличаются, по сути, только наличием водяного знака.
3) Картинки из папки A могут иметь различные размеры.
4) Фон картинки необязательно белый и может быть сколь угодно пестрым.
5) И самое коварное – неизвестно, есть ли в папке A изображение совпадающее с изображением из папки B.

Я попробовал решить задачу в лоб:
1) Берем очередную картинку из папки B и последовательно сравниваем ее со всеми картинками из папки A.
2) Если их размеры не совпадают, то переходим к следующей картинке из папки A.
3) Если размеры совпадают начинаем сравнивать их попиксельно. И если (кол-во совпавших пикселей / полное кол-во пикселей) > 0.8, то считаем изображения совпадающими.
Код AS3:

if (WMBitmapData.width == picBitmapData.width && WMBitmapData.height == picBitmapData.height)
{
        var coinCount:int = 0;
        var w:int = WMBitmapData.width;
        var h:int = WMBitmapData.height;
        for (var a:int = 0; a < w; ++a)
                for (var b:int = 0; b < h; ++b)
                {
                        if (WMBitmapData.getPixel32(a, b) == picBitmapData.getPixel32(a, b))
                                ++coinCount;
                }
        if (Number(coinCount) / Number(w * h) > 0.8)
        {
                // Фиксируем совпадение
                ...
        }
}

Столь монструозное количество сравнений некритично.
Проблема в том, что иногда алгоритм ошибается, неверно определяя совпадение картинок. Думаю здесь дело в большом количестве белого фона, что гарантирует превышение лимита совпадения в 0.8. Но дело в том, что я не представляю как подобрать нужную константу вместо 0.8, потому что картинка может быть и меньших размеров (приведенные выше были 500x500), и тогда водяной знак будет занимать значительную площадь изображения.

Подскажите, как быть?

P.S. Также вместо getPixel32 я использовал BitmapData.compare, но это не суть, так как относится уже к реализации.

caseyryan 01.03.2013 12:47

Я бы с blend mode поэксперементировал. Первое что пришло в голову.

Alex Lexcuk 01.03.2013 12:54

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

Hauts 01.03.2013 12:55

"Накладываем" попарно картинки друг на друга с каким-то блендмодом (точно не могу сказать, каким именно), смотрим область "разности" изображений. Если она очень близка к области вотермарка — считаем, это эти изображения идентичны. Я бы попробовал бы сначала так.

Котяра 01.03.2013 13:02

Есть метод BitmapData#compare
Потом получаем прямоугольник через getColorBoundsRect и смотрим его размер - если он близок к размеру ватермарка - значит изображения идентичные.
Правда это не сработает если идентичные картинки имеют разные размеры (правда какие же тогда они идентичные?)

Wolsh 01.03.2013 13:05

Цитата:

2) Если картинки совпадают, как на примере выше, то они точно имеют одинаковые размеры и отличаются, по сути, только наличием водяного знака.
Почему просто не скопировать область с ватермарком на предполагаемый исходник перед сравнением?

Добавлено через 8 минут
Есть только нюанс, что если картинки в jpeg, при сохранении после наложения ватермарка некоторые пиксели могут не соответствовать исходным (артефакты оптимизации). Поэтому коэфициент соответствия все же не будет 100%, надо подбирать.

bav 01.03.2013 13:27

Alex Lexcuk, вы немного неправильно поняли про пестрый фон. Совпадающие картинки не будут отличаться фоном. То есть и вы и Wolsh предложили одну и ту же схему – удаление либо вставка ватермарки, т.е. попытка сведения изображений к абсолютно идентичным. А caseyryan, Hauts и Котяра предлагают несколько иной подход (хотя в общем-то тоже сравнение, но встроенными функциями). Хотя оба подхода можно объединить :)
Спасибо всем большое :) вывели из тупика, пойду экспериментировать. Позже отпишусь о результатах. (да, про getColorBoundsRect я не знал)

Dip52 01.03.2013 13:42

Может быть придумать "похожесть"? Например, если картинка похожа на 90%, то с ней и работаем.

Hauts 01.03.2013 14:03

Dip52, как бы про это и речь, как эту "похожесть" придумать.

Dip52 01.03.2013 15:39

Цитата:

Сообщение от Hauts (Сообщение 1123057)
Dip52, как бы про это и речь, как эту "похожесть" придумать.

Программным образом нарисовать контуры мольбертов. Рисование будет происходить таким образом: чертим линию, допустим снизу, на коричневом цвете (если 1 пиксель коричневый, а 2 белый, то ищем в какой стороне есть коричневый). Сначала чертим эти линии на исходном, потом с ватермарком.
Потом полученные конторы помещаем в специальный объект (он уже там идёт по координате x=0 и y=0). Эти конторы сравниваем по признакам: если углы у линий похожи, то вероятность "похожести" повышается".

Так как фон не обязательно белый, то изначально задать список характерных цветов на картинке. Можно так: когда удастся начертить контуры мольберта, тогда вырезаем этот мольберт и выделяем характерные цвета для мольберта.


Часовой пояс GMT +4, время: 16:50.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.