opencv中imgproc库中函数详解(1)
BaseColumnFilter
單列核的基礎(chǔ)濾波器。
[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;
// 重置濾波器的狀態(tài)(IIR濾波器中可能用到)
virtual void reset();
int ksize; // 核的孔徑
int anchor; // 定位點坐標
// 處理過程中一般不使用
};
類 BaseColumnFilter是使用單列核對數(shù)據(jù)濾波的基礎(chǔ)類。濾波不一定是線性濾波,表示如下:
其中 F 是濾波函數(shù),但是用類來表示,因為類可以有其他的,如儲存之前處理的數(shù)據(jù)之類的附加功能。這個類只是定義一個接口并不直接使用。作為替代,OpenCV中有一些函數(shù)(你可以添加更多)實現(xiàn)了特定的濾波功能并返回指向派生類的指針。這些指針通過 FilterEngine構(gòu)造函數(shù)。 雖然濾波操作接口使用uchar 類型,具體實施時并限于8位數(shù)據(jù)。
BaseFilter
對2D圖像濾波的基礎(chǔ)類。
[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;
// 重置濾波器的狀態(tài)(IIR濾波器中可能用到)
virtual void reset();
Size ksize;
Point anchor;
};
類 BaseFilter 是使用2D核對數(shù)據(jù)濾波的基礎(chǔ)類。濾波不一定是線性的,可以表示如下:
BaseRowFilter
單列核濾波器的基礎(chǔ)類。
[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 是使用單列核對數(shù)據(jù)濾波的基礎(chǔ)類。濾波不一定是線性的,可以表示如下:
其中 F 是濾波函數(shù)。此類只是定義了一個接口并不直接使用。這個類只是定義一個接口并不直接使用。作為替代,OpenCV中有一些函數(shù)(你可以添加更多)實現(xiàn)了特定的濾波功能并返回指向派生類的指針。這些指針通過 FilterEngine 構(gòu)造函數(shù)。 雖然濾波操作接口使用uchar類型,具體實施時并限于8位數(shù)據(jù)。
FilterEngine
通用圖像濾波類。
[cpp] view plaincopy
class FilterEngine
{
public:
// 空的構(gòu)造函數(shù)
FilterEngine();
// 構(gòu)造2D的不可分的濾波器(!_filter2D.empty())或者
// 可分的濾波器 (!_rowFilter.empty() && !_columnFilter.empty())
// 輸入數(shù)據(jù)類型為 “srcType”, 輸出類型為”dstType”,
// 中間的數(shù)據(jù)類型為 “bufType”.
// _rowBorderType 何 _columnBorderType 決定圖像邊界如何被外推擴充
// 只有 _rowBorderType and/or _columnBorderType
// == BORDER_CONSTANT 時 _borderValue 才會被用到
FilterEngine(const Ptr& _filter2D,
const Ptr& _rowFilter,
const Ptr& _columnFilter,
int srcType, int dstType, int bufType,
int _rowBorderType=BORDER_REPLICATE,
int _columnBorderType=-1, // 默認使用 _rowBorderType
const Scalar& _borderValue=Scalar());
virtual ~FilterEngine();
// 初始引擎的分割函數(shù)
void init(const Ptr& _filter2D,
const Ptr& _rowFilter,
const Ptr& _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” 行
// 返回處理的行數(shù)
virtual int proceed(const uchar* src, int srcStep, int srcCount,
uchar* dst, int dstStep);
// 處理整個ROI的高層調(diào)用
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(); }
// 輸入圖中未被處理的行數(shù)
int remainingInputRows() const;
// 輸入中未被處理的行數(shù)
int remainingOutputRows() const;
// 源圖的開始和結(jié)束行
int startY, endY;
// 指向濾波器的指針
Ptr filter2D;
Ptr rowFilter;
Ptr columnFilter;
};
類 FilterEngine 可以被用于對任何一個圖像進行濾波。它包含了所有必要的緩沖區(qū),計算需要的圖像外的“虛”像素推算值等等。通過各種創(chuàng)建 *Filter 的函數(shù)(見下文)可以返回指向初始化的 FilterEngine 的實例,之后可以使用這些實例中的高層接口如 filter2D(), erode(),dilate() 等。因此,此類在OpenCV的很多濾波函數(shù)中起著關(guān)鍵的作用。
這個類使得濾波和其他函數(shù)結(jié)合更容易,如色彩空間轉(zhuǎn)換,閾值,算術(shù)運算,等操作。將幾個操作相結(jié)合在一起你可以得到更好的性能,因為數(shù)據(jù)都留在緩存中。例如以下是對浮點圖像執(zhí)行 Laplace 算子處理的簡單例子,Laplacian() 函數(shù)可以簡化為:
[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 Fxx = createSeparableLinearFilter(src.type(),
dst.type(), kd, ks, Point(-1,-1), 0, borderType, borderType, Scalar() );
Ptr 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的早期版本,現(xiàn)在的濾波操作支持圖像ROI概念,也就是說,在ROI圖像之外但在圖像之內(nèi)的像素點可以用于濾波操作。例如,你可以取單個像素作為ROI濾波。通過濾波器之后將范圍特定的像素。然而,通過傳遞FilterEngine::start或FilterEngine::apply 參數(shù) isolated=false 它有可能仍是舊的圖像。你可以明確指定傳遞ROI給 FilterEngine::apply 函數(shù)或者構(gòu)造新的矩陣頭:
[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 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);
探索中的數(shù)據(jù)類型。由于它是在 BaseFilter 描述中提到的具體的濾波器,雖然 Base*Filter::operator() 除了UCHAR的指針并其他類型的信息, 但實際它可以處理任何類型的數(shù)據(jù)。為了保證所有的函數(shù)可以運行,使用以下規(guī)則:
在分離濾波的情況下,首先應(yīng)用 FilterEngine::rowFilter 。它把輸入圖像數(shù)據(jù)(srcType類型)的中間結(jié)果存儲在內(nèi)部緩沖區(qū)(bufType類型)。然后,這些中間結(jié)果作為單通道數(shù)據(jù)由 FilterEngine:: columnFilter處理,結(jié)果存儲在輸出圖像(dstType類型)中。因此,輸入 RowFilter 類型是srcType 而輸出類型是 bufType。輸入 columnFilter 的類型是CV_MAT_DEPTH(bufType)而輸出的類型為CV_MAT_DEPTH(dstType)。
在非分離濾波的情況下,bufType 必須與 srcType 類型相同。如果需要,源數(shù)據(jù)會被復(fù)制到臨時緩沖區(qū)之后傳遞給 FilterEngine:: filter2D 。也就是說,輸入filter2D 類型為 scrType(= bufType),輸出類型是
總結(jié)
以上是生活随笔為你收集整理的opencv中imgproc库中函数详解(1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 混合高斯模型(Mixtures of G
- 下一篇: bilareralFilter双边滤波函