PHP - действительно быстрый способ обнаружения пробелов вокруг изображения?

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

ImageMagick работает слишком медленно, поэтому просматривает каждый пиксель с каждой стороны с помощью GD и проверяет, белый ли он. Мне нужно сделать около 500 000 000 изображений, поэтому каждая микросекунда имеет значение.

Кстати, изображение только черно-белое.

Если есть внешнее приложение, которое может это сделать, что я могу сделать exec с помощью PHP, то это будет хорошо.


person Alasdair    schedule 26.03.2012    source источник
comment
Является ли белая рамка красивой однородной рамкой вокруг изображения? Белый действительно белый или только очень яркий?   -  person KillerX    schedule 26.03.2012
comment
Нет, это совсем не однородно... может быть что угодно, и по-разному с каждой стороны. Изображение может быть даже полностью белым.   -  person Alasdair    schedule 26.03.2012
comment
Итак, я предполагаю, что вам нужен тот, который больше всего выделяется с каждой стороны? PS: Вы, скорее всего, получите более высокую скорость обработки, выполняя фактическую обработку на C или C++.   -  person KillerX    schedule 26.03.2012
comment
500 м изображений — уф! Должен любить знать ваш вариант использования!   -  person halfer    schedule 26.03.2012
comment
Это звучит как работа для распараллеливания. Если бы вы раздали ее нескольким серверам или даже сети настольных ПК, вы бы сделали это намного быстрее. Тем не менее, вы пробовали imagemagick с SSD или RAM-накопителя?   -  person halfer    schedule 26.03.2012
comment
Можете ли вы дать нам более подробное описание того, как выглядят фотографии? У меня есть алгоритм, но я не уверен, что он будет применим. Что меня интересует, так это общие формы на ваших фотографиях. Преимущественно прямоугольные формы повернуты/слегка деформированы? В основном круговой? Совершенно непредсказуемый (как X, E, T...)?   -  person KillerX    schedule 26.03.2012
comment
@halfer: он отдан на откуп группе серверов, и да, каждый использует RAM-диск для временного хранения.   -  person Alasdair    schedule 26.03.2012
comment
@KillerX: текст, рисунок, фото и т. д.   -  person Alasdair    schedule 26.03.2012
comment
Сколько серверов входит в группу? ;)   -  person halfer    schedule 26.03.2012
comment
Я не вижу, как PHP является подходящей рабочей лошадкой для этого. Если у вас так много изображений, вы должны использовать родной язык и использовать все мыслимые трюки с производительностью для каждого конкретного формата файла.   -  person Gleno    schedule 26.03.2012
comment
@Gleno, это не совсем подходит, но я использую именно его. C++ был бы намного лучше, Assemby еще лучше, а специальное ядро ​​ОС для выполнения только того, что я хочу, было бы еще лучше, но PHP — это то, с чем я работаю для практических целей. В любом случае, PHP объединяет только то, что в основном делают различные другие приложения, написанные на C или C++ — так уж получилось, что PHP используется для этой части.   -  person Alasdair    schedule 26.03.2012


Ответы (2)


есть ли какая-либо дополнительная информация, которую вы знаете об изображениях, которые можно использовать, чтобы помочь?

Например, изображения начинаются белыми, затем становятся черными, а затем остаются черными? или может ли любой пиксель быть белым или черным, и тот факт, что какой-либо из них белый или черный, ничего не говорит вам о других?

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

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

Я думаю, что вы могли бы в конечном итоге с компромиссом между скоростью и точностью здесь. Самый точный способ — разрезать каждый столбец и строку, начиная с концов, проверяя каждый пиксель. Как только вы нашли попадание в столбец, вы нашли край с одной стороны. Это можно сделать параллельно, так как каждая проверка независима. вы могли бы ускорить это, как вы сказали, проверяя только каждый n-й пиксель, но это, вероятно, иногда происходит, особенно с таким большим набором данных. это может быть или не быть приемлемым. вы можете улучшить это, проверив область, в которой вы нашли совпадение, чтобы убедиться, что совпадение является точным. Таким образом, если вы проверяете каждый третий пиксель и обнаруживаете попадание в 15-й пиксель, то проверьте 14-й, чтобы увидеть, является ли он попаданием (и 13-й, если 14-й). используя это, вы можете уйти с меньшим количеством проверок.

person Sam Holder    schedule 26.03.2012
comment
Черные пиксели естественным образом располагаются в блоках, поэтому я мог пропустить каждый второй пиксель или даже проверить только 1 из 3. Помимо этого, это может быть текст, рисунок или размытая фотография на изображении. - person Alasdair; 26.03.2012

Один алгоритм, который может работать, если у вас есть в основном непрерывная граница более темных пикселей: Левая сторона:

  1. Возьмите средний пиксель и начните проверять пиксели справа, пока не найдете черный.
  2. Затем двигайтесь оттуда вверх/вниз, пока не наткнетесь на черный пиксель.
  3. Когда вы найдете черный пиксель, двигайтесь влево, пока не наткнетесь на белый.
  4. Повторяйте 2,3, пока не окажетесь вверху/внизу.

Это, конечно, не сработает, если есть пробелы, как в тексте.

person KillerX    schedule 26.03.2012
comment
Дело в том, что в середине изображения может быть большое белое пространство с черными пикселями по углам. - person Alasdair; 26.03.2012
comment
Теоретически вы можете начать, скажем, с 10% сверху и перейти прямо к 50% ширины. Если вы ничего не нажмете, переместитесь на одну строку вверх, а затем переместитесь на 2 строки вниз и т. Д. Скорее всего, вам все равно потребуется покрыть меньше пикселей, чем при сканировании строки за строкой / столбцом за столбцом. - person KillerX; 26.03.2012