Простой алгоритм обрезки пустых границ из изображения по коду? - PullRequest
12 голосов
/ 16 августа 2011

В настоящее время я ищу довольно быстрый и достаточно точный алгоритм в C # /. NET для выполнения этих шагов в коде:

  1. Загрузка изображения в память.
  2. Начиная с цвета в позиции (0,0), найдите свободное место.
  3. Обрезать это ненужное пространство.

Я проиллюстрировал, чего хочу достичь:

Example illustration

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

Я просто боюсь, что это действительно очень медленно.

Итак, мой вопрос:

Известны ли вам какие-либо быстрые алгоритмы (в идеале без сторонних библиотек) для удаления "пустых" границ из изображения / растрового изображения в памяти?

Примечание: алгоритм должен быть «разумно точным», а не точным на 100%. Какой-то допуск, например, слишком много или слишком мало обрезанных строк, вполне подойдет.

Дополнение 1:

Я только что закончил реализацию своего алгоритма грубой силы самым простым способом. См. Код на Pastebin.com .

Ответы [ 5 ]

4 голосов
/ 16 августа 2011

Если вы знаете, что ваше изображение отцентрировано, вы можете попробовать идти по диагонали (то есть (0,0), (1,1), ... (n, n)) до тех пор, пока не получите удар, затем вернитесь на одну строку назадпроверка времени, пока вы не найдете «пустую» строку (в каждом измерении).Для изображения, которое вы разместили, было бы много сравнений.

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

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

Одним из улучшений, которое вы могли бы сделать, является придание вашему «цвету удара» некоторого допуска (возможно, регулируемого?)

1 голос
/ 02 декабря 2013

Хотя я предпочитаю ответ Таранга, я хотел бы дать несколько советов о том, как «изолировать» объекты на изображении, ссылаясь на заданный цвет переднего плана и цвет фона, который называется «сегментация» и используется при работе вполе «оптического контроля», где изображение не просто обрезается до некоторого обнаруженного объекта, но объекты подсчитываются и также измеряются, вещи, которые вы можете измерить на объекте, это площадь, контур, диаметр и т. д.

First ofвсе, обычно вы начнете действительно проходить по своему изображению, начиная с координат x / y 0,0 и проходя слева направо и сверху вниз, пока не найдете пиксель с другим значением в качестве фона.Чувствительность сегментации определяется путем определения значения оттенков серого фона и значения оттенков серого переднего плана.Возможно, вы пройдете по изображению, как сказано, по координатам, но из представления программ вы просто пройдете через массив пикселей.Это означает, что вам придется работать с формулой, которая вычисляет координату x / y для индекса пикселя в массиве пикселей.Эта формула обязательно требует ширины и высоты изображения.

Если вы хотите обрезать, я думаю, что когда вы нашли так называемую «точку поворота» вашего объекта переднего плана, вы обычно будете идти по найденномуобъект с помощью формулы, которая обнаруживает соседние пиксели с одинаковым значением переднего плана.Если есть только один объект для обнаружения, как в вашем случае, легко сохранить те координаты пикселей, которые являются самыми северными, самыми восточными, самыми южными и самыми западными.Эти 4 координаты отмечают прямоугольник, в который помещается ваш объект. С помощью этой информации вы можете вычислить ширину и высоту новых изображений (обрезанное изображение).

1 голос
/ 17 августа 2011

Во-первых, вы можете преобразовать ваше растровое изображение в byte[], используя LockBits(), это будет намного быстрее, чем GetPixel() и не потребует от вас unsafe.

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

Бинарный поиск может улучшить чуть-чуть, но это не так важно, так как, возможно, сэкономит вам строку поиска для каждого направления в лучшем случае.

1 голос
/ 17 августа 2011

Для начала, ваш текущий алгоритм в основном наилучший из возможных.

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

Если вы остаетесь в c #, вы можете распараллеливать расширения для запуска его на нескольких ядрах.Это не уменьшит нагрузку на машину, но уменьшит задержку, если таковая имеется.

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

1 голос
/ 17 августа 2011

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

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

начинайте с центральной линии (0, длина / 2) и начинайте в одном направлении за раз, исследуйте линии, как мы это делаем в бинарном поиске.

делаем это для всех сторон.

это уменьшит сложность входа в базу 2

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