Как сгладить кривые (контуры) в OpenCV?

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

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

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

EDIT: Также попробовали:

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

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

Ответ 1

enter image description here

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

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

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

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

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

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

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

         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