(轉)OpenCV濾波之copyMakeBorder和borderInterpolate

在OpenCV濾波算法中,有兩個非常重要的基本工具函數,copyMakeBorder和borderInterpolate


copyMakeBorder

函數原型

void copyMakeBorder( const Mat& src, Mat& dst,
int top, int bottom, int left, int right,
int borderType, const Scalar& value=Scalar() );

源碼在utils.cpp中


功能

擴充src的邊緣,將圖像變大,然後以各種外插方式自動填充圖像邊界,這個函數實際上調用了函數cv::borderInterpolate,這個函數最重要的功能就是爲了處理邊界,比如均值濾波或者中值濾波中,使用copyMakeBorder將原圖稍微放大,然後我們就可以處理邊界的情況了

其中:

src,dst:原圖與目標圖像

top,bottom,left,right分別表示在原圖四周擴充邊緣的大小

borderType:擴充邊緣的類型,就是外插的類型,OpenCV中給出以下幾種方式

  * BORDER_REPLICATE
  * BORDER_REFLECT
  * BORDER_REFLECT_101
  * BORDER_WRAP
  * BORDER_CONSTANT

實際中,還有其他的宏定義

//! various border interpolation methods
enum { BORDER_REPLICATE=IPL_BORDER_REPLICATE, BORDER_CONSTANT=IPL_BORDER_CONSTANT,
       BORDER_REFLECT=IPL_BORDER_REFLECT, BORDER_WRAP=IPL_BORDER_WRAP,
       BORDER_REFLECT_101=IPL_BORDER_REFLECT_101,          BORDER_REFLECT101=BORDER_REFLECT_101,
       BORDER_TRANSPARENT=IPL_BORDER_TRANSPARENT,
       BORDER_DEFAULT=BORDER_REFLECT_101, BORDER_ISOLATED=16 };

這幾種方式到底什麼意思呢?

OpenCV給出瞭解釋:

代碼來自源碼:filter.cpp

/*
 Various border types, image boundaries are denoted with '|'
 * BORDER_REPLICATE:     aaaaaa|abcdefgh|hhhhhhh

 * BORDER_REFLECT:       fedcba|abcdefgh|hgfedcb
 * BORDER_REFLECT_101:   gfedcb|abcdefgh|gfedcba
 * BORDER_WRAP:          cdefgh|abcdefgh|abcdefg
 * BORDER_CONSTANT:      iiiiii|abcdefgh|iiiiiii  with some specified 'i'
 */

個人覺得OpenCV解釋的還是挺形象的

這裏我們重點看下面這非常常見的幾種


BORDER_REPLICATE:複製法,也就是複製最邊緣像素。


如上圖,紅色區域爲src的最邊界像素,藍色區域是擴充的邊界,我們將邊緣擴大了5個像素(right=5),藍色區域的寬度就是5,複製了5次紅色區域的值

這種方式也就是OpenCV中的中值濾波medianBlur採用的邊界處理方式


BORDER_REFLECT_101:對稱法,也就是以最邊緣像素爲軸,對稱。

下面我們看圖


綠色區域是src最邊界的像素,藍色區域是我們擴充的5個像素的擴充邊界,而紅色區域就是藍色區域在src的對稱部分

 這種方式也是OpenCV邊界處理的默認方式(BORDER_DEFAULT=BORDER_REFLECT_101)

也是filter2D,blur,GaussianBlur,bilateralFilter的默認處理方式,所以這種方式在邊界處理中應用還是非常廣泛的


BORDER_CONSTANT:常量法。

常量法就是以一個常量像素值(由參數 value給定)填充擴充的邊界值,這種方式在仿射變換,透視變換中非常常見

如下圖,

我們使用了默認的value,黑色填充了邊界,所以紅色區域的擴充的5個像素寬的邊界是黑色的

在copyMakeBorder的內部,調用了函數borderInterpolate


borderInterpolate


函數原型

int borderInterpolate( int p, int len, int borderType );

源碼在filter.cpp中


功能

根據不同的外插方法(borderType),如  BORDER_REPLICATE,計算外插像素對應於原圖中的1D座標,一般不單獨使用,而在其他函數內部使用,如在copyMakeBorder中使用

其中

p:擴充邊緣的像素的座標(橫座標或者縱座標)

len:src對於p所在的維的大小

borderType:與函數copyMakeBorder中的意思一樣,這裏就不重複了


示例:

比如我們在X方向使用BORDER_WRAP邊界方式,Y方向採用BORDER_REFLECT_101方式,那麼計算擴充邊界像素Point(-5,100)對應原圖中的位置就是

float val = img.at<float>(borderInterpolate(100, img.rows, BORDER_REFLECT_101),
borderInterpolate(-5, img.cols, BORDER_WRAP));


之前的博客中的濾波算法,沒有采用上面的函數,其實,如果採用上面的函數,處理濾波將會非常方便,下面的幾篇博客中,我將會修改之前的算法,採用OpenCV提供的函數處理濾波


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章