快乐虾
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 cv2 import numpy as np # filter2D src = 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++接口。
??
时间: 2024-11-10 00:11:27