生活随笔
收集整理的這篇文章主要介紹了
图像滤波 Image Filtering
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
譯自《The OpenCV Reference Manual Release 2.3》
CHAPTER THREE: IMGPROC. IMAGE PROCESSING ?3.1 Image Filtering
轉載請注明出處:http://blog.csdn.net/xiaowei_cqu/article/details/7718831
本節描述對2D圖像執行的各種線性和非線性的濾波操作。即用圖像中每個像素點(x,y)臨近的點進行運算。如果是線性濾波器,結果是每個像素值的加權和;如果是形態操作,結果是最小或最大值之類的。對每個坐標的像素操作的輸出結果也在同一個坐標(x,y)處,這就意味著輸出圖像和輸入圖像有相同的大小。通常情況下,這些函數支持多通道圖像,即對每個通道單獨進行操作。因此,輸出圖像也與輸入圖像有相同的通道數。
本節描述的函數與類的另一個共同的特點是,不同于簡單的算術運算,他們需要對一些不存在的像素值進行推測。例如,你想使用 3*3的高斯濾波器,處理圖像每行最左側的像素時還需要其左側的像素,也就是圖像外的像素。你可以讓這些像素等于源圖像最左側的像素(“復制邊(replicated border)”外推法),或者假設所有不存在的像素值為零(“恒量邊(constant border)”外推法),等等。OpenCV允許你指定外推方法。詳情請參閱?borderInterpolate()函數的功能及其參數描述。
BaseColumnFilter
單列核的基礎濾波器。
[cpp]?view plaincopy
class?BaseColumnFilter?? {?? ????public:?? ????virtual?~BaseColumnFilter();?? ?????? ?????? ?????? ?????? ?????? ?????? ????virtual?void?operator()(const?uchar**?src,?uchar*?dst,?int?dststep,?? ????int?dstcount,?int?width)?=?0;?? ?????? ????virtual?void?reset();?? ????int?ksize;??? ????int?anchor;??? ?????? };?? 類?
BaseColumnFilter是使用單列核對數據濾波的基礎類。濾波不一定是線性濾波,表示如下:
其中
?F?是濾波函數,但是用類來表示,因為類可以有其他的,如儲存之前處理的數據之類的附加功能。這個類只是定義一個接口并不直接使用。作為替代,OpenCV中有一些函數(你可以添加更多)實現了特定的濾波功能并返回指向派生類的指針。這些指針通過?
FilterEngine構造函數。 雖然濾波操作接口使用
uchar?類型,具體實施時并限于8位數據。
BaseFilter
對2D圖像濾波的基礎類。
[cpp]?view plaincopy
class?BaseFilter?? {?? ????public:?? ????virtual?~BaseFilter();?? ?????? ?????? ?????? ?????? ?????? ?????? ?????? ????virtual?void?operator()(const?uchar**?src,?uchar*?dst,?int?dststep,?? ????int?dstcount,?int?width,?int?cn)?=?0;?? ?????? ????virtual?void?reset();?? ????Size?ksize;?? ????Point?anchor;?? };?? 類?
BaseFilter?是使用2D核對數據濾波的基礎類。濾波不一定是線性的,可以表示如下:
BaseRowFilter
單列核濾波器的基礎類。
[cpp]?view plaincopy
class?BaseRowFilter?? {?? ????public:?? ????virtual?~BaseRowFilter();?? ?????? ?????? ?????? ?????? ?????? ????virtual?void?operator()(const?uchar*?src,?uchar*?dst,?? ????int?width,?int?cn)?=?0;?? ????int?ksize,?anchor;?? };?? 類?
BaseRowFilter?是使用單列核對數據濾波的基礎類。濾波不一定是線性的,可以表示如下:
其中
?F?是濾波函數。此類只是定義了一個接口并不直接使用。這個類只是定義一個接口并不直接使用。作為替代,OpenCV中有一些函數(你可以添加更多)實現了特定的濾波功能并返回指向派生類的指針。這些指針通過?
FilterEngine?構造函數。 雖然濾波操作接口使用
uchar類型,具體實施時并限于8位數據。
FilterEngine
通用圖像濾波類。
[cpp]?view plaincopy
class?FilterEngine?? {?? public:?? ?????? ????FilterEngine();?? ?????? ?????? ?????? ?????? ?????? ?????? ?????? ????FilterEngine(const?Ptr<BaseFilter>&?_filter2D,?? ????const?Ptr<BaseRowFilter>&?_rowFilter,?? ????const?Ptr<BaseColumnFilter>&?_columnFilter,?? ????int?srcType,?int?dstType,?int?bufType,?? ????int?_rowBorderType=BORDER_REPLICATE,?? ????int?_columnBorderType=-1,??? ????const?Scalar&?_borderValue=Scalar());?? ????virtual?~FilterEngine();?? ?????? ????void?init(const?Ptr<BaseFilter>&?_filter2D,?? ????const?Ptr<BaseRowFilter>&?_rowFilter,?? ????const?Ptr<BaseColumnFilter>&?_columnFilter,?? ????int?srcType,?int?dstType,?int?bufType,?? ????int?_rowBorderType=BORDER_REPLICATE,?int?_columnBorderType=-1,?? ????const?Scalar&?_borderValue=Scalar());?? ?????? ?????? ????virtual?int?start(Size?wholeSize,?Rect?roi,?int?maxBufRows=-1);?? ?????? ????virtual?int?start(const?Mat&?src,?const?Rect&?srcRoi=Rect(0,0,-1,-1),?? ????bool?isolated=false,?int?maxBufRows=-1);?? ?????? ?????? ?????? ????virtual?int?proceed(const?uchar*?src,?int?srcStep,?int?srcCount,?? ????uchar*?dst,?int?dstStep);?? ?????? ????virtual?void?apply(?const?Mat&?src,?Mat&?dst,?? ????const?Rect&?srcRoi=Rect(0,0,-1,-1),?? ????Point?dstOfs=Point(0,0),?? ????bool?isolated=false);?? ????bool?isSeparable()?const?{?return?filter2D.empty();?}?? ?????? ????int?remainingInputRows()?const;?? ?????? ????int?remainingOutputRows()?const;?? ?????? ????int?startY,?endY;?? ?????? ????Ptr<BaseFilter>?filter2D;?? ????Ptr<BaseRowFilter>?rowFilter;?? ????Ptr<BaseColumnFilter>?columnFilter;?? };?? 類?
FilterEngine?可以被用于對任何一個圖像進行濾波。它包含了所有必要的緩沖區,計算需要的圖像外的“虛”像素推算值等等。通過各種創建 *Filter 的函數(見下文)可以返回指向初始化的?
FilterEngine?的實例,之后可以使用這些實例中的高層接口如
?filter2D(),
?erode(),
dilate()?等。因此,此類在OpenCV的很多濾波函數中起著關鍵的作用。?
這個類使得濾波和其他函數結合更容易,如色彩空間轉換,閾值,算術運算,等操作。將幾個操作相結合在一起你可以得到更好的性能,因為數據都留在緩存中。例如以下是對浮點圖像執行 Laplace 算子處理的簡單例子,
Laplacian()?函數可以簡化為:
[cpp]?view plaincopy
void?laplace_f(const?Mat&?src,?Mat&?dst)?? {?? ????CV_Assert(?src.type()?==?CV_32F?);?? ????dst.create(src.size(),?src.type());?? ?????? ?????? ????Mat?kd,?ks;?? ????getSobelKernels(?kd,?ks,?2,?0,?ksize,?false,?ktype?);?? ?????? ????int?DELTA?=?std::min(10,?src.rows);?? ????Ptr<FilterEngine>?Fxx?=?createSeparableLinearFilter(src.type(),?? ????dst.type(),?kd,?ks,?Point(-1,-1),?0,?borderType,?borderType,?Scalar()?);?? ????Ptr<FilterEngine>?Fyy?=?createSeparableLinearFilter(src.type(),?? ????dst.type(),?ks,?kd,?Point(-1,-1),?0,?borderType,?borderType,?Scalar()?);?? ????int?y?=?Fxx->start(src),?dsty?=?0,?dy?=?0;?? ????Fyy->start(src);?? ????const?uchar*?sptr?=?src.data?+?y*src.step;?? ?????? ?????? ?????? ?????? ????Mat?Ixx(?DELTA?+?kd.rows?-?1,?src.cols,?dst.type()?);?? ????Mat?Iyy(?DELTA?+?kd.rows?-?1,?src.cols,?dst.type()?);?? ?????? ?????? ?????? ?????? ?????? ?????? ?????? ?????? ?????? ?????? ?????? ????for(?;?dsty?<?dst.rows;?sptr?+=?DELTA*src.step,?dsty?+=?dy?)?? ????{?? ????????Fxx->proceed(?sptr,?(int)src.step,?DELTA,?Ixx.data,?(int)Ixx.step?);?? ????????dy?=?Fyy->proceed(?sptr,?(int)src.step,?DELTA,?d2y.data,?(int)Iyy.step?);?? ????????if(?dy?>?0?)?? ????????{?? ????????????Mat?dstripe?=?dst.rowRange(dsty,?dsty?+?dy);?? ????????????add(Ixx.rowRange(0,?dy),?Iyy.rowRange(0,?dy),?dstripe);?? ????????}?? ????}?? }?? 如果你不需要對濾波過程的控制,你可以簡單地使用?
FilterEngine:: apply方法。
[cpp]?view plaincopy
void?FilterEngine::apply(const?Mat&?src,?Mat&?dst,?? ????????const?Rect&?srcRoi,?Point?dstOfs,?bool?isolated)?? {?? ?????? ????CV_Assert(?src.type()?==?srcType?&&?dst.type()?==?dstType?);?? ?????? ????Rect?_srcRoi?=?srcRoi;?? ????if(?_srcRoi?==?Rect(0,0,-1,-1)?)?? ????_srcRoi?=?Rect(0,0,src.cols,src.rows);?? ?????? ?????? ????CV_Assert(?dstOfs.x?>=?0?&&?dstOfs.y?>=?0?&&?? ????dstOfs.x?+?_srcRoi.width?<=?dst.cols?&&?? ????dstOfs.y?+?_srcRoi.height?<=?dst.rows?);?? ?????? ????int?y?=?start(src,?_srcRoi,?isolated);?? ?????? ?????? ?????? ????proceed(?src.data?+?y*src.step,?? ????????(int)src.step,?endY?-?startY,?? ????????dst.data?+?dstOfs.y*dst.step?+?? ????????dstOfs.x*dst.elemSize(),?(int)dst.step?);?? }?? 不同于OpenCV的早期版本,現在的濾波操作支持圖像ROI概念,也就是說,在ROI圖像之外但在圖像之內的像素點可以用于濾波操作。例如,你可以取單個像素作為ROI濾波。通過濾波器之后將范圍特定的像素。然而,通過傳遞
FilterEngine::start或
FilterEngine::apply?參數
?isolated=false?它有可能仍是舊的圖像。你可以明確指定傳遞ROI給
?FilterEngine::apply?函數或者構造新的矩陣頭:
[cpp]?view plaincopy
?? ?? ?? float?val1?=?0;?? Mat?dst1(1,1,CV_32F,&val1);?? Ptr<FilterEngine>?Fx?=?createDerivFilter(CV_32F,?CV_32F,?? 1,?0,?3,?BORDER_REFLECT_101);?? Fx->apply(src,?Rect(x,y,1,1),?Point(),?dst1);?? ?? ?? float?val2?=?0;?? Mat?dst2(1,1,CV_32F,&val2);?? Mat?pix_roi(src,?Rect(x,y,1,1));?? Sobel(pix_roi,?dst2,?dst2.type(),?1,?0,?3,?1,?0,?BORDER_REFLECT_101);?? 探索中的數據類型。由于它是在 BaseFilter 描述中提到的具體的濾波器,雖然 ?Base*Filter::operator() ?除了UCHAR的指針并其他類型的信息, 但實際它可以處理任何類型的數據。為了保證所有的函數可以運行,使用以下規則:
- 在分離濾波的情況下,首先應用?FilterEngine::rowFilter?。它把輸入圖像數據(srcType類型)的中間結果存儲在內部緩沖區(bufType類型)。然后,這些中間結果作為單通道數據由?FilterEngine:: columnFilter處理,結果存儲在輸出圖像(dstType類型)中。因此,輸入 RowFilter 類型是srcType 而輸出類型是 bufType。輸入 columnFilter 的類型是CV_MAT_DEPTH(bufType)而輸出的類型為CV_MAT_DEPTH(dstType)。
- 在非分離濾波的情況下,bufType 必須與 srcType 類型相同。如果需要,源數據會被復制到臨時緩沖區之后傳遞給?FilterEngine:: filter2D?。也就是說,輸入filter2D 類型為 scrType(= bufType),輸出類型是dstType。
總結
以上是生活随笔為你收集整理的图像滤波 Image Filtering的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。