Я пытаюсь разработать приложение для сортировки коробок в qt и использую opencv. Я хочу измерить ширину и длину коробки.
Как показано на изображении выше, я хочу обнаружить только самые внешние линии (т.е. края коробки), что даст мне ширину и длину коробки, независимо от того, что напечатано внутри коробки.
Что я попробовал:
Сначала я попробовал использовать Findcontours()
и выбранный контур с максимальной площадью, но контур внешнего края многократно не заключен (где-то поврежден в хитром выводе) и, следовательно, не обнаруживается как контур.
Несмотря на то, что преобразование строк дает мне слишком много строк, я не знаю, как получить только четыре строки, которые меня интересуют.
Я попробовал мой алгоритм как,
Преобразовать изображение в оттенки серого.
Возьмите один столбец изображения, сравните каждый пиксель со следующим последующим пикселем этого столбца, если разница в этом значении больше некоторого порога (скажем, 100), что пиксель принадлежит краю, поэтому сохраните его в массиве. Сделайте это для всех столбцов, и верхняя линия прямоугольника будет параллельна оси x.
Следуйте той же процедуре, но из последнего столбца и последней строки (т.е. снизу вверх), нижняя линия будет параллельна оси x.
Также найдите линии, параллельные оси y. Теперь у меня есть четыре массива точек, по одному на каждую сторону.
Теперь это дает хорошие результаты, если бокс расположен таким образом, что его стороны точно параллельны осям X и Y. Если поле расположено немного ориентировано в каком-либо направлении, это дает мне диагональные линии, что очевидно, как показано на рисунке ниже.
Как показано на рисунке ниже, я удалил первые 10 и последние 10 точек из всех четырех массивов точек (которые отвечают за рисование диагональных линий) и нарисовал линии, что не будет работать, когда окно наклонено больше, а также измерения будут идти неправильно ,
Теперь мой вопрос
Есть ли какой-нибудь более простой способ в opencv получить только внешние края (прямоугольник) коробки и получить там размеры, игнорируя все, что напечатано на коробке и ориентировано в каком-либо направлении?
Я не обязательно прошу исправить / улучшить мой алгоритм, но любые предложения по этому вопросу также приветствуются. Извините за такой большой пост.
Я бы предложил следующие шаги:
1: сделать маску изображения с помощью cv::inRange()
(документация), чтобы выбрать цвет фона. Тогда используйте cv::not()
инвертировать эту маску. Это даст вам только коробку.
2: Если вас не волнуют тени, эффекты глубины, делающие ваши измерения неточными, вы можете сразу же приступить к использованию cv::findContours()
снова. Вы выбираете самый большой контур и сохраняете его cv::rotatedRect
,
3: это cv::rotatedRect
даст вам rotatedRect.size, который определяет ширину и высоту вашего блока в пикселях
Так как прямоугольник расположен на контрастном фоне, вы можете использовать пороговое значение Otsu.