Используя Opencv, как обнаружить коробку на изображении, исключая объекты, напечатанные внутри коробки?

Я пытаюсь разработать приложение для сортировки коробок в qt и использую opencv. Я хочу измерить ширину и длину коробки.

Входное изображение

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

Что я попробовал:

  1. Сначала я попробовал использовать Findcontours() и выбранный контур с максимальной площадью, но контур внешнего края многократно не заключен (где-то поврежден в хитром выводе) и, следовательно, не обнаруживается как контур.

  2. Несмотря на то, что преобразование строк дает мне слишком много строк, я не знаю, как получить только четыре строки, которые меня интересуют.

  3. Я попробовал мой алгоритм как,

    Преобразовать изображение в оттенки серого.

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

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

    Также найдите линии, параллельные оси y. Теперь у меня есть четыре массива точек, по одному на каждую сторону.

Теперь это дает хорошие результаты, если бокс расположен таким образом, что его стороны точно параллельны осям X и Y. Если поле расположено немного ориентировано в каком-либо направлении, это дает мне диагональные линии, что очевидно, как показано на рисунке ниже.

Неверный вывод

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

введите описание изображения здесь

Теперь мой вопрос

Есть ли какой-нибудь более простой способ в opencv получить только внешние края (прямоугольник) коробки и получить там размеры, игнорируя все, что напечатано на коробке и ориентировано в каком-либо направлении?

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

0

Решение

Я бы предложил следующие шаги:

1: сделать маску изображения с помощью cv::inRange() (документация), чтобы выбрать цвет фона. Тогда используйте cv::not() инвертировать эту маску. Это даст вам только коробку.

2: Если вас не волнуют тени, эффекты глубины, делающие ваши измерения неточными, вы можете сразу же приступить к использованию cv::findContours() снова. Вы выбираете самый большой контур и сохраняете его cv::rotatedRect,

3: это cv::rotatedRect даст вам rotatedRect.size, который определяет ширину и высоту вашего блока в пикселях

2

Другие решения

Так как прямоугольник расположен на контрастном фоне, вы можете использовать пороговое значение Otsu.

  • пороговое изображение (используйте метод Otsu)
  • отфильтровывать любые паразитные пиксели, находящиеся за пределами области прямоугольника (будем надеяться, что таких пикселей не так много, и их можно легко удалить с помощью медианного или морфологического фильтра)
  • найти контуры
  • объединить все точки контура и получить их выпуклую оболочку (идея состоит в том, чтобы найти выпуклую область, которая ограничивает все эти контуры в области блока независимо от их связности)
  • примените к этому выпуклому корпусу приближение многоугольника (окПолиДП) и проверьте, есть ли у вас четырехугольник
  • если нет искажений перспективы, вы должны получить прямоугольник, в противном случае вам придется его исправить
  • если вы получите прямоугольник, у вас есть его размеры. Вы также можете найти прямоугольник минимальной площади (minAreaRect) выпуклой оболочки, который должен непосредственно дать вам RotatedRect
0

По вопросам рекламы [email protected]