日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

图像滤波 Image Filtering

發布時間:2025/3/21 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图像滤波 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();??
  • ????//?用以被用戶重寫??
  • ????//??
  • ????//?對列的集合進行濾波操作??
  • ????//?輸入"dstcount?+?ksize?-?1"?行,輸出"dstcount"?行,??
  • ????//?輸入和輸出的每行含有"width"個元素,??
  • ????//?濾波之后的行寫入緩存"dst"中.??
  • ????virtual?void?operator()(const?uchar**?src,?uchar*?dst,?int?dststep,??
  • ????int?dstcount,?int?width)?=?0;??
  • ????//?重置濾波器的狀態(IIR濾波器中可能用到)??
  • ????virtual?void?reset();??
  • ????int?ksize;?//?核的孔徑??
  • ????int?anchor;?//?定位點坐標??
  • ????//?處理過程中一般不使用??
  • };??
  • 類?BaseColumnFilter是使用單列核對數據濾波的基礎類。濾波不一定是線性濾波,表示如下:

    其中?F?是濾波函數,但是用類來表示,因為類可以有其他的,如儲存之前處理的數據之類的附加功能。這個類只是定義一個接口并不直接使用。作為替代,OpenCV中有一些函數(你可以添加更多)實現了特定的濾波功能并返回指向派生類的指針。這些指針通過?FilterEngine構造函數。 雖然濾波操作接口使用uchar?類型,具體實施時并限于8位數據。

    BaseFilter

    對2D圖像濾波的基礎類。 [cpp]?view plaincopy
  • class?BaseFilter??
  • {??
  • ????public:??
  • ????virtual?~BaseFilter();??
  • ????//?用以被用戶重寫??
  • ????//??
  • ????//?對列的集合進行濾波操作??
  • ????//?輸入"dstcount?+?ksize.height?-?1"?行,輸出"dstcount"?行,??
  • ????//?輸入的每行含有"(width?+?ksize.width-1)*cn"個元素??
  • ????//?輸出的每行含有"width*cn"個元素,??
  • ????//?濾波之后的行寫入緩存"dst"中.??
  • ????virtual?void?operator()(const?uchar**?src,?uchar*?dst,?int?dststep,??
  • ????int?dstcount,?int?width,?int?cn)?=?0;??
  • ????//?重置濾波器的狀態(IIR濾波器中可能用到)??
  • ????virtual?void?reset();??
  • ????Size?ksize;??
  • ????Point?anchor;??
  • };??
  • 類?BaseFilter?是使用2D核對數據濾波的基礎類。濾波不一定是線性的,可以表示如下:


    BaseRowFilter

    單列核濾波器的基礎類。
    [cpp]?view plaincopy
  • class?BaseRowFilter??
  • {??
  • ????public:??
  • ????virtual?~BaseRowFilter();??
  • ????//?用以被用戶重寫??
  • ????//??
  • ????//?對輸入的單列進行濾波操作??
  • ????//?輸入列有?"width"個元素,?每個元素有?"cn"?個通道.??
  • ????//?濾波之后的行寫入緩存"dst"中.??
  • ????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();??
  • ????//?構造2D的不可分的濾波器(!_filter2D.empty())或者??
  • ????//?可分的濾波器?(!_rowFilter.empty()?&&?!_columnFilter.empty())??
  • ????//?輸入數據類型為?"srcType",?輸出類型為"dstType",??
  • ????//?中間的數據類型為?"bufType".??
  • ????//?_rowBorderType?何?_columnBorderType?決定圖像邊界如何被外推擴充??
  • ????//?只有?_rowBorderType?and/or?_columnBorderType??
  • ????//?==?BORDER_CONSTANT?時?_borderValue?才會被用到??
  • ????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,?//?默認使用?_rowBorderType??
  • ????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());??
  • ????//?定義圖像尺寸"wholeSize"為ROI開始濾波.??
  • ????//?返回圖像開始的y-position坐標.??
  • ????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);??
  • ????//?處理源圖像的另一部分??
  • ????//?從"src"到"dst"處理"srcCount"?行??
  • ????//?返回處理的行數??
  • ????virtual?int?proceed(const?uchar*?src,?int?srcStep,?int?srcCount,??
  • ????uchar*?dst,?int?dstStep);??
  • ????//?處理整個ROI的高層調用??
  • ????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());??
  • ????//?get?the?derivative?and?smooth?kernels?for?d2I/dx2.??
  • ????//?for?d2I/dy2?consider?using?the?same?kernels,?just?swapped??
  • ????Mat?kd,?ks;??
  • ????getSobelKernels(?kd,?ks,?2,?0,?ksize,?false,?ktype?);??
  • ????//?process?10?source?rows?at?once??
  • ????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;??
  • ????//?allocate?the?buffers?for?the?spatial?image?derivatives;??
  • ????//?the?buffers?need?to?have?more?than?DELTA?rows,?because?at?the??
  • ????//?last?iteration?the?output?may?take?max(kd.rows-1,ks.rows-1)??
  • ????//?rows?more?than?the?input.??
  • ????Mat?Ixx(?DELTA?+?kd.rows?-?1,?src.cols,?dst.type()?);??
  • ????Mat?Iyy(?DELTA?+?kd.rows?-?1,?src.cols,?dst.type()?);??
  • ????//?inside?the?loop?always?pass?DELTA?rows?to?the?filter??
  • ????//?(note?that?the?"proceed"?method?takes?care?of?possibe?overflow,?since??
  • ????//?it?was?given?the?actual?image?height?in?the?"start"?method)??
  • ????//?on?output?you?can?get:??
  • ????//?*?<?DELTA?rows?(initial?buffer?accumulation?stage)??
  • ????//?*?=?DELTA?rows?(settled?state?in?the?middle)??
  • ????//?*?>?DELTA?rows?(when?the?input?image?is?over,?generate??
  • ????//?"virtual"?rows?using?the?border?mode?and?filter?them)??
  • ????//?this?variable?number?of?output?rows?is?dy.??
  • ????//?dsty?is?the?current?output?row.??
  • ????//?sptr?is?the?pointer?to?the?first?input?row?in?the?portion?to?process??
  • ????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)??
  • {??
  • ????//?check?matrix?types??
  • ????CV_Assert(?src.type()?==?srcType?&&?dst.type()?==?dstType?);??
  • ????//?handle?the?"whole?image"?case??
  • ????Rect?_srcRoi?=?srcRoi;??
  • ????if(?_srcRoi?==?Rect(0,0,-1,-1)?)??
  • ????_srcRoi?=?Rect(0,0,src.cols,src.rows);??
  • ????//?check?if?the?destination?ROI?is?inside?dst.??
  • ????//?and?FilterEngine::start?will?check?if?the?source?ROI?is?inside?src.??
  • ????CV_Assert(?dstOfs.x?>=?0?&&?dstOfs.y?>=?0?&&??
  • ????dstOfs.x?+?_srcRoi.width?<=?dst.cols?&&??
  • ????dstOfs.y?+?_srcRoi.height?<=?dst.rows?);??
  • ????//?start?filtering??
  • ????int?y?=?start(src,?_srcRoi,?isolated);??
  • ????//?process?the?whole?ROI.?Note?that?"endY?-?startY"?is?the?total?number??
  • ????//?of?the?source?rows?to?process??
  • ????//?(including?the?possible?rows?outside?of?srcRoi?but?inside?the?source?image)??
  • ????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::startFilterEngine::apply?參數?isolated=false?它有可能仍是舊的圖像。你可以明確指定傳遞ROI給?FilterEngine::apply?函數或者構造新的矩陣頭: [cpp]?view plaincopy
  • //?compute?dI/dx?derivative?at?src(x,y)??
  • //?method?1:??
  • //?form?a?matrix?header?for?a?single?value??
  • 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);??
  • //?method?2:??
  • //?form?a?matrix?header?for?a?single?value??
  • 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的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。