標籤:vs2013 python 影像處理
快樂蝦
http://blog.csdn.net/lights_joy/(QQ群:Visual EmbedLinux Tools 375515651)
歡迎轉載,但請保留作者資訊
濾波器在影像處理中的應用非常廣泛,OpenCV也有個直接使用濾波器掩碼(核)的函數filter2D,將映像與核進行卷積運算得到靶心圖表像。卷積是在每一個映像塊與某個運算元(核)之間進行的運算,而核就是一個固定大小的數值數組。
實際上,在OpenCV中很多演算法都是用卷積實現的,包括一些邊緣檢測的演算法。本文無意列舉這些演算法的原理,僅僅是考察一下OpenCV的實現,再嘗試用Python調用這些演算法,看看其效果。
採用的測試映像還是它:
因為我們的最終目標是識別此映像中的雜草與棉花植株!
1. FilterEngine
在OpenCV中濾波的操作由FilterEngine這個類來完成,在源碼的注釋裡清楚地說明了這個類的作用:
The Main Class for Image Filtering. The class can be used to apply an arbitrary filtering operation to an image. It contains all the necessary intermediate buffers, it computes extrapolated values of the "virtual" pixels outside of the image etc. Pointers to the initialized cv::FilterEngine instances are returned by various OpenCV functions, such as cv::createSeparableLinearFilter(), cv::createLinearFilter(), cv::createGaussianFilter(), cv::createDerivFilter(), cv::createBoxFilter() and cv::createMorphologyFilter(). Using the class you can process large images by parts and build complex pipelines that include filtering as some of the stages. If all you need is to apply some pre-defined filtering operation, you may use cv::filter2D(), cv::erode(), cv::dilate() etc. functions that create FilterEngine internally.
下面是FilterEngine的一個典型使用方式:
void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, InputArray _kernelX, InputArray _kernelY, Point anchor, double delta, int borderType ){ Mat src = _src.getMat(), kernelX = _kernelX.getMat(), kernelY = _kernelY.getMat(); if( ddepth < 0 ) ddepth = src.depth(); _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); Mat dst = _dst.getMat(); Ptr<FilterEngine> f = createSeparableLinearFilter(src.type(), dst.type(), kernelX, kernelY, anchor, delta, borderType & ~BORDER_ISOLATED ); f->apply(src, dst, Rect(0,0,-1,-1), Point(), (borderType & BORDER_ISOLATED) != 0 );}
當然,如注釋所說,我們幾乎不需要直接使用這個類,但是瞭解它的用法對於我們理解和調試OpenCV是很有好處的。
2. filter2D
下面試試直接給一個濾波器的矩陣看看效果。
# -*- coding: utf-8 -*- import cv2import numpy as np# filter2Dsrc = cv2.imread(‘f:\\tmp\\cotton.jpg‘)cv2.imshow(‘src‘, src)kernel = np.array([ [-1, -1, -1], [-1, 8, -1], [-1, -1, -1] ])dst = cv2.filter2D(src, -1, kernel)cv2.imshow(‘dst‘, dst)cv2.waitKey()
結果就是這樣的:
3. 從Python到C++
看看從Python的filter2D到FilterEngine的執行過程。
首先是filter2D的wrapper函數:
static PyObject* pyopencv_filter2D(PyObject* , PyObject* args, PyObject* kw){ PyObject* pyobj_src = NULL; Mat src; PyObject* pyobj_dst = NULL; Mat dst; int ddepth=0; PyObject* pyobj_kernel = NULL; Mat kernel; PyObject* pyobj_anchor = NULL; Point anchor=Point(-1,-1); double delta=0; int borderType=BORDER_DEFAULT; const char* keywords[] = { "src", "ddepth", "kernel", "dst", "anchor", "delta", "borderType", NULL }; if( PyArg_ParseTupleAndKeywords(args, kw, "OiO|OOdi:filter2D", (char**)keywords, &pyobj_src, &ddepth, &pyobj_kernel, &pyobj_dst, &pyobj_anchor, &delta, &borderType) && pyopencv_to(pyobj_src, src, ArgInfo("src", 0)) && pyopencv_to(pyobj_dst, dst, ArgInfo("dst", 1)) && pyopencv_to(pyobj_kernel, kernel, ArgInfo("kernel", 0)) && pyopencv_to(pyobj_anchor, anchor, ArgInfo("anchor", 0)) ) { ERRWRAP2( cv::filter2D(src, dst, ddepth, kernel, anchor, delta, borderType)); return pyopencv_from(dst); } return NULL;}
這個函數是swig自動產生的,簡單地對filter2D這個C++函數進行了封裝,處理了輸入參數和傳回值。接著看cv::filter2D的實現過程:
void cv::filter2D( InputArray _src, OutputArray _dst, int ddepth, InputArray _kernel, Point anchor, double delta, int borderType ){ Mat src = _src.getMat(), kernel = _kernel.getMat();..... Ptr<FilterEngine> f = createLinearFilter(src.type(), dst.type(), kernel, anchor, delta, borderType & ~BORDER_ISOLATED ); f->apply(src, dst, Rect(0,0,-1,-1), Point(), (borderType & BORDER_ISOLATED) != 0 );}
和前面提到的sepFilter2D函數非常的相似!
cv::filter2D也是OpenCV開放的一個C++介面。
??
Python影像處理(4):濾波器