Я хотел бы сфотографировать этикетки на банке с едой и иметь возможность трансформировать их так, чтобы этикетка была плоской, а размер правой и левой сторон был изменен, чтобы быть равным центру изображения.
В идеале я хотел бы использовать контраст между меткой и фоном, чтобы найти края и применить коррекцию. В противном случае я могу попросить пользователя как-то определить углы и стороны изображения.
Я ищу общие методы и алгоритмы для получения изображения, сферически искаженного (в моем случае, цилиндрического) и способного сгладить изображение. В настоящее время изображение надписи, намотанной на банку или бутылку, будет содержать элементы и текст, которые уменьшаются по мере того, как они отступают вправо или влево от изображения. Кроме того, линии, обозначающие край метки, будут параллельны только в центре изображения и будут наклонены друг к другу справа и слева от метки.
После манипуляции с изображением мне бы хотелось, чтобы у меня оставался почти идеальный прямоугольник, где текст и элементы имеют одинаковый размер, как если бы я сделал снимок с этикеткой, когда ее не было на банке или бутылке.
Кроме того, мне бы хотелось, чтобы техника могла автоматически определять края метки, чтобы применить подходящую коррекцию. В противном случае мне пришлось бы попросить моего пользователя указать границы ярлыка.
Я уже гуглил и нашел такие статьи: сглаживание изогнутых документов , но я ищу что-то более простое, так как мои потребности в этикетках с простой кривой.
источник
Ответы:
Аналогичный вопрос был задан на Mathematica.Stackexchange . Мой ответ там развивался и в итоге получился довольно длинным, поэтому я кратко изложу алгоритм здесь.
Аннотация
Основная идея:
Алгоритм работает только для изображений, где:
Тем не менее, алгоритм является модульным. По крайней мере, в принципе, вы можете написать собственное обнаружение меток, которое не требует темного фона, или вы можете написать свою собственную функцию измерения качества, которая может справиться с эллиптическими или восьмиугольными метками.
Полученные результаты
Эти изображения были обработаны полностью автоматически, то есть алгоритм берет исходное изображение, работает в течение нескольких секунд, затем показывает отображение (слева) и неискаженное изображение (справа):
Следующие изображения были обработаны с помощью модифицированной версии алгоритма, в которой пользователь выбирает левую и правую границы банки (не метки), поскольку кривизна метки не может быть оценена по изображению во фронтальном снимке (т.е. полностью автоматический алгоритм будет возвращать изображения, которые слегка искажены):
Реализация:
1. Найдите этикетку
Яркий ярлык на темном фоне, поэтому я легко могу найти его с помощью бинаризации:
Я просто выбираю самый большой подключенный компонент и предполагаю, что это метка:
2. Найдите границы метки
Следующий шаг: найдите верхнюю / нижнюю / левую / правую границы, используя простые производные маски свертки:
Это небольшая вспомогательная функция, которая находит все белые пиксели в одном из этих четырех изображений и преобразует индексы в координаты (
Position
возвращает индексы, а индексы - это основанные на 1 {y, x} -туплицы, где y = 1 вверху изображение. Но все функции обработки изображения ожидают координаты, которые основаны на 0 (x, y} -тупле, где y = 0 - нижняя часть изображения):3. Найти отображение из изображения в координаты цилиндра
Теперь у меня есть четыре отдельных списка координат верхней, нижней, левой и правой границ метки. Я определяю отображение из координат изображения в координаты цилиндра:
Это цилиндрическое отображение, которое отображает координаты X / Y в исходном изображении в цилиндрические координаты. Отображение имеет 10 степеней свободы для высоты / радиуса / центра / перспективы / наклона. Я использовал ряд Тейлора для аппроксимации синуса дуги, потому что я не мог добиться оптимизации, работая с ArcSin напрямую.
Clip
вызовы - это моя специальная попытка предотвратить сложные числа во время оптимизации. Здесь есть компромисс: с одной стороны, функция должна быть как можно ближе к точному цилиндрическому отображению, насколько это возможно, чтобы дать минимально возможное искажение. С другой стороны, если это сложно, становится намного сложнее автоматически найти оптимальные значения для степеней свободы. (Хорошая особенность обработки изображений с помощью Mathematica заключается в том, что вы можете очень легко поиграть с такими математическими моделями, ввести дополнительные термины для различных искажений и использовать одни и те же функции оптимизации для получения окончательных результатов. Я никогда не мог ничего сделать например OpenCV или Matlab. Но я никогда не пробовал набор символов для Matlab, возможно, это делает его более полезным.)Далее я определяю «функцию ошибки», которая измеряет качество изображения -> отображение координат цилиндра. Это просто сумма квадратов ошибок для пикселей границы:
Эта функция ошибок измеряет «качество» сопоставления: она наименьшая, если точки на левой границе отображаются в (0 / [что угодно]), пиксели в верхней границе отображаются в ([что угодно] / 0) и т. Д. ,
Теперь я могу сказать Mathematica найти коэффициенты, которые минимизируют эту функцию ошибок. Я могу сделать «обоснованные предположения» о некоторых коэффициентах (например, радиус и центр банки на изображении). Я использую их в качестве отправных точек оптимизации:
FindMinimum
находит значения для 10 степеней свободы моей функции отображения, которые минимизируют функцию ошибок. Объедините общее отображение и это решение, и я получу отображение из координат изображения X / Y, которое соответствует области метки. Я могу визуализировать это отображение, используяContourPlot
функцию Mathematica :4. Преобразуйте изображение
Наконец, я использую
ImageForwardTransform
функцию Mathematica для искажения изображения в соответствии с этим отображением:Это дает результаты, как показано выше.
Версия с ручным управлением
Алгоритм выше полностью автоматический. Никаких корректировок не требуется. Это работает достаточно хорошо, если изображение сделано сверху или снизу. Но если это фронтальный выстрел, радиус банки нельзя оценить по форме этикетки. В этих случаях я получаю гораздо лучшие результаты, если я позволю пользователю вручную ввести левую / правую границу банки и явно установлю соответствующие степени свободы в отображении.
Этот код позволяет пользователю выбрать левую / правую границы:
Это альтернативный код оптимизации, где центр и радиус заданы явно.
источник