Как сгладить кривые (контуры) в OpenCV? - PullRequest
11 голосов
/ 14 сентября 2011

Я работаю над черно-белым изображением так же, как первое по ссылке: http://imageshack.us/g/33/firstwm.png/ В нем много "шума", поэтому я применил фильтр Медианы для его сглаживания, таким образом получая второе изображение.

cvSmooth(TempImage, TempImage, CV_MEDIAN, 5, 0);

После этого я получаю контуры и рисую их на другом изображении, как на третьем изображении по ссылке.Моя проблема в том, что контуры все еще немного пикселированы (резкие).Есть ли способ сгладить черно-белое изображение, чтобы получить более четкие контуры?Или, может быть, сделать что-то с контурами.Я также пробовал Дилат и Эрод с разными ядрами, но проблема остается той же.Спасибо за все, что помогает.

РЕДАКТИРОВАТЬ: Также пробовал:

cvSmooth(TempImage, TempImage, CV_GAUSSIAN, 9, 9, 3);
cvThreshold(TempImage, TempImage, 127, 255, CV_THRESH_BINARY);

Те же результаты, что и медианный фильтр, хорошо, но все еще оставляет некоторые пиксельные контуры.

1 Ответ

8 голосов
/ 14 сентября 2011

enter image description here

Если это результат сглаживания, к которому вы стремитесь, его можно получить, применив размытие по Гауссу с последующим пороговым значением. То есть используя cvSmooth с CV_GAUSSIAN в качестве параметра. Затем следует cvThreshold.

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

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

Таким образом, пороговый оператор очень прост, однако можно использовать любую другую общую функцию отображения. По сути это функция f(i), где i - это значение пикселя интенсивности (в диапазоне 0-255), а f(i) - это отображаемое значение. Для порога эта функция проста

 f(i) = {   0, for i  < threshold
          255, for i >= threshold

То, что у вас есть, - это сглаженное изображение (с помощью cvSmooth, использующего ядро ​​Гаусса, которое дает вам «самое сглаженное» сглаживание, если это имеет смысл). Таким образом, у вас есть плавный переход значений по краям, в диапазоне от 0 до 255. Что вы хотите сделать, это сделать этот переход намного меньшим, чтобы получить хорошее ребро. Если вы выберете баллистический режим, вы сразу перейдете от 0 до 255, что соответствует бинарному порогу, который вы уже сделали.

Теперь рассмотрим функцию, которая отображает, возможно, диапазон из 4 значений интенсивности (127 + - 4) на полный диапазон 0-255. * 1025 Т.е. *

         f(i) = {   0,  for i  < 123
                  255,  for i >= 131
       linear mapping,  for 123 <= i < 131

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

обновление 2 Контурная версия будет выглядеть примерно так:

              f(i) = { 255,  for        i < 122
   linear mapping (255->0),  for 122 <= i < 126
                         0,  for 126 <= i < 127
   linear mapping (0->255),  for 127 <= i < 131
                       255,  for 131 <= i
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...