Я могу успешно пороговые изображения и найти края в изображении. То, с чем я борюсь, это попытка точно определить угол черных краев.
В настоящее время я беру крайние точки черного края и вычисляю угол с помощью функции atan2, но из-за наложения псевдонимов в зависимости от выбранной точки угол может иметь некоторую степень вариации. Есть ли надежный программируемый способ выбора точек для расчета угла?
Пример изображения:
Например, угол инструмента Gimp Measure при 3,12 °,
Если вы пишете свою собственную библиотеку, то создание надежного решения для этой проблемы позволит вам разработать несколько независимых кусков кода, которые вы можете объединить для решения других проблем. Я предполагаю, что вы хотите найти углы шахматной доски при произвольном вращении, при различных условиях освещения, при наличии шума на изображении, с небольшим нелинейным искажением подушкообразных / бочкообразных и т.д.
Хотя существуют простые методы на основе ядра, позволяющие находить целые пиксели в качестве краевых пикселей, при работе с закрашенными полигонами вы предпочитаете алгоритмы, которые могут находить края с точностью до субпикселя, чтобы вы могли выполнять точное подгонку линий. Даже если градиент от темного квадрата к белому квадрату пересекает несколько пикселей, «истинный» край будет найден в некоторой подпиксельной точке, и весьма вероятно, что это не та точка, которую вы догадались бы, щелкнув вручную.
Я попытался предоставить простую сводку по поиску преимуществ в этом старом посте SO:
Какая связь между краями изображения и градиентом?
Для таких проблем, как ваша, надежное решение состоит в том, чтобы находить граничные точки на переходах от темного к светлому с точностью до субпикселя, затем подгонять линии к краевым точкам и использовать углы линий. Если вы обрабатываете истинное изображение с камеры, и если на изображении есть не исправленные радиальные искажения, то есть некоторые потенциальные проблемы с точностью измерения, но мы их проигнорируем.
Если вы хотите найти точную подгонку для края, то было бы неплохо отсканировать субпиксельные края в направлении, перпендикулярном этому краю. Это предполагает, что у нас есть разумная оценка направления края для начала. Сначала мы можем найти приблизительную оценку ориентации кромки, а затем выполнить точное соответствие линии.
Алгоритм ниже может показаться слишком много шагов, но моя цель состоит в том, чтобы указать, как обеспечить надежное решение.
Затем вы переберите свой список больших двоичных объектов и выполните следующие действия для каждого большого двоичного объекта:
Этот алгоритм находит углы независимо для каждого черного квадрата шахматной доски. Это может быть излишним для этого одного приложения, но если вы разрабатываете библиотеку, возможно, она даст вам некоторые идеи о том, какие субалгоритмы реализовать и как их структурировать. Например, алгоритм будет опираться на реализации этих методов:
Все это говорит, если вы готовы согласиться на небольшую потерю точности, и если вы знаете, что изображение не страдает от радиальных искажений и т. Д., И если вам просто нужно найти угол параллельных линий, определяемый как все края доски, тогда вы можете попробовать ..
Есть и другие методы, которые менее точны, но проще в реализации:
И так далее, и так далее. По мере того, как вы разрабатываете свою библиотеку и создаете надежные реализации автономных функций, которые вы можете связать вместе для создания решений для конкретных приложений, вы, вероятно, обнаружите, что надежные решения основаны на большем количестве шагов, чем вы могли бы предположить, но это также быть более ясным, какой режим отказа будет на каждом шаге и как обращаться с этим режимом отказа.
Могу я спросить, какую библиотеку C ++ вы используете для написания этого кода?
Джерри прав, если вы на самом деле примените порог к изображению, он будет 2-битным, черным или белым. То, что вы, возможно, применили, является своего рода ограничителем.
Вы можете сделать функцию порога (если вы сами кодируете обработку изображений), применив ограничитель, который вы, возможно, использовали, и затем превратив все небелые пиксели в черный цвет. Если у вас есть правильные настройки, квадраты должны быть изолированы, и вы сможете рассчитать угол.
Как только это будет сделано, вы можете использовать алгоритм поиска пути, чтобы найти какое-либо ребро, подойдет любое ребро. Если вы найдете более или менее прямой путь, вы можете использовать крайние точки, как вы делаете сейчас, чтобы определить угол. Поскольку поворот шахматной доски имеет значение только в пределах 90 градусов, ваш угол должен быть по модулю 90 градусов или пи на 2 радиана.
Я не уверен, что это (где-то близко) Правильный ответ, но моей непосредственной реакцией будет порог дважды: один раз, когда все, кроме черного, рассматривается как белый, и один раз, когда все, кроме белого, рассматривается как черный.
Найти угол для каждого, а затем интерполировать между двумя углами.
У вашей проблемы есть несколько решений, но у всех есть одна очень важная проблема, которой вы, кажется, пренебрегаете. Примечание. Когда вы пытаетесь выполнить геометрические вычисления на изображении, используемые вами точки должны быть как можно дальше друг от друга. Вы берете 2 очка внутри одного квадрата. Эти точки расположены очень близко друг к другу, поэтому небольшая ошибка в расположении точек в пикселях приводит к большой ошибке в угле. Почему вы используете только один квадрат, когда у вас много квадратов на изображении?
Вот несколько решений:
(gx,gy)
, рассчитать угол наклона градиента в каждом пикселе atan(gy,gx)
и составить гистограмму углов. У вас будет 2 значительных пика около 3 и 93 градусов. Просто найдите вершины путем поиска максимума в гистограмме. Это будет работать, даже если у вас много шума на изображении, даже с сглаживанием и артефактами jpg, и даже если у вас есть другие рисунки на изображении. Но помните, вы должны сильно сгладить изображение, прежде чем вычислять производные.