Как в Python выполнить билатеральную фильтрацию? К сожалению
В модуле
Казалось бы,
Код:
Какая-то проблема с заполнением границ (запонение пустых полосок шириной в половину ширины kernel после свёртки с этим kernel), и результат не зависит от последнего параметра
Проблему придётся как-то обходить. Например, сделать свою оболочку для вызова функции
cv.Smooth()
с параметром cv.CV_BILATERAL
не работает. В модуле
cv
имеются функции-аналоги C++
интерфейса для OpenCV
(их имена начинаются со строчной буквы). Они недокументированны или я не нашёл к ним документации, и вообще упоминаний в интернете почти не нашёл. Казалось бы,
cv.bilateralFilter()
и есть требуемый метод. Но у него тоже проблемы. А именно. Натравливаю нехитрый код на всем известное и многострадальное изображение:Код:
import cv
import numpy as np
img = cv.LoadImageM('lena.jpg')
a = np.asarray(img)
filtered = cv.bilateralFilter(a, 50, 50, cv.BORDER_REFLECT)
cv.Copy(filtered, img)
cv.SaveImage('lena_f.jpg', img)
И вот, что получаю в 'lena_f.jpg':Какая-то проблема с заполнением границ (запонение пустых полосок шириной в половину ширины kernel после свёртки с этим kernel), и результат не зависит от последнего параметра
cv.BORDER_REFLECT
. Картинка получается сжатой по горизонтали на один пиксель, а граничные полоски как будто недозаполнены или заполнены не крайними строчками, а одним крайним столбцом. Проблему придётся как-то обходить. Например, сделать свою оболочку для вызова функции
cvSmooth
через ctypes
или, как я уже делал для cvCamshift
. Ещё можно просто попробовать PyrMeanShiftFiltering
.
А зачем Вам последний параметр, если и без него всё работает?
ОтветитьУдалитьbim = cv2.bilateralFilter(im, 3, 21, 3) #например
Вы, кажется, столько же параметров указали
УдалитьНе совсем ;)
УдалитьИз документации (версия 2.4):
cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]]) → dst
Значения пространственной и цветовой дистанции я наобум выставлял.
Если же Вам необходимо указать тип границ, то нужно писать вот так (я пользуюсь cv2, мне она кажется удобнее):
import cv2
a = cv2.imread('lena.jpg')
filtered = cv2.bilateralFilter(
a, 3, 50, 50, borderType=cv2.BORDER_REFLECT)
cv2.imwrite('lena_f.jpg',filtered)
И да, 50 - слишком большое значение для "ядра". 3, максимум 5 - если у вас некритичные к производительности приложения. Ну и результат необычный :)
Результаты:
Оригинал: https://dl.dropbox.com/u/15879991/share/pics/opencv/lena.jpg
d=3: https://dl.dropbox.com/u/15879991/share/pics/opencv/lena_f3.jpg
d=5:
https://dl.dropbox.com/u/15879991/share/pics/opencv/lena_f5.jpg
d=50: https://dl.dropbox.com/u/15879991/share/pics/opencv/lena_f50.jpg
Спасибо за комментарий, применю на досуге. Давно собирался 2.4 поюзать. Ну а о kernel так безотносительно нет смысла спорить. Мне тогда большой kernel нужен был для экспериментов с быстрой сегментацией/выделением контуров. Нужно было в реальном времени на видео с камеры эмоции на лице разглядеть. Ну мне казалось, что билатеральная фильтрация помогала контуры губ, например, точнее выделять
Удалить