opencv-均值滤波blur解析

滤波器的种类有很多, 在新版本的OpenCV中,提供了如下五种常用的图像平滑处理操作方法,且他们分别被封装在单独的函数中,使用起来非常方便:

·        方框滤波——boxblur函数

·        均值滤波——blur函数

·        高斯滤波——GaussianBlur函数

·        中值滤波——medianBlur函数

·        双边滤波——bilateralFilter函数

本文主要以blur展开解析:

CV_EXPORTS_W void blur( InputArray src, OutputArray dst,

                        Size ksize, Point anchor=Point(-1,-1),

                        int

·        第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。

·        第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。

·        第三个参数,Size类型(对Size类型稍后有讲解)的ksize,内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小

·        第四个参数,Point类型的anchor,表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。

·        第五个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT

borderType参数解析如下:

    /*

    Various border types, image boundaries aredenoted with '|'

 

    * BORDER_REPLICATE:     aaaaaa|abcdefgh|hhhhhhh

    * BORDER_REFLECT:       fedcba|abcdefgh|hgfedcb

    * BORDER_REFLECT_101:   gfedcb|abcdefgh|gfedcba

    * BORDER_WRAP:          cdefgh|abcdefgh|abcdefg

    * BORDER_CONSTANT:      iiiiii|abcdefgh|iiiiiii  with some specified 'i'

*/

   根据borderInterpolate可知其只支持上面五种边缘插值方法,上面的插值按照右边的字符串很形象的表示了。

在OpenCV滤波算法中,有两个非常重要的基本工具函数,copyMakeBorder和borderInterpolate

void copyMakeBorder( const Mat& src,Mat& dst,int top, int bottom, int left, int right,
int borderType, const Scalar& value=Scalar() );

源码在utils.cpp中

功能

扩充src的边缘,将图像变大,然后以各种外插方式自动填充图像边界,这个函数实际上调用了函数cv::borderInterpolate,这个函数最重要的功能就是为了处理边界,比如均值滤波或者中值滤波中,使用copyMakeBorder将原图稍微放大,然后我们就可以处理边界的情况了

// borderInterpolate源码在 filter.cpp里面

BORDER_REPLICATE:复制法,也就是复制最边缘像素。边缘扩大的像素个数根据你的模板大小

BORDER_REFLECT :  对称法,也就是以最边缘像素的边为轴,即该边缘像素会复制一遍

BORDER_REFLECT_101对称法,也就是以最边缘像素为轴,对称,该边缘像素不会复制一遍

BORDER_CONSTANT:常量法:边界填充特点常量,默认为0(没有发现可以修改该值,望补充,MAtlib的可以修改)

BORDER_WRAP:镜像对称复制,但是 blur(Mat(M), tempM, cv::Size(3, 3), Point(-1, -1), BORDER_WRAP);提示错误

         根据错误提示你会发现问题来到FilterEngine 类解析——OpenCV图像滤波核心引擎

FilterEngine类是OpenCV关于图像滤波的主力军类,OpenCV图像滤波功能的核心引擎。各种滤波函数比如blur, GaussianBlur,到头来其实是就是在函数末尾处定义了一个Ptr<FilterEngine>类型的f,然后f->apply( src, dst )了一下而已。

这个类可以把几乎是所有的滤波操作施加到图像上。它包含了所有必要的中间缓存器。有很多和滤波相关的create系函数的返回值直接就是Ptr<FilterEngine>。比如cv::createSeparableLinearFilter()。

源码解析BORDER_WRAP在blur(Mat(M), tempM, cv::Size(3, 3), Point(-1, -1), BORDER_WRAP)里面使用错误:

http://www.opencv.org.cn/opencvdoc/2.3.2/html/modules/imgproc/doc/filtering.html?highlight=filterengine#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());
发现init函数出现如下代码:

if (_columnBorderType < 0)
		_columnBorderType = _rowBorderType;

	rowBorderType = _rowBorderType;
	columnBorderType = _columnBorderType;

	CV_Assert(columnBorderType != BORDER_WRAP);

所以可知 BORDER_WRAP使用不当

Blur()源码在opencv目录下面

E:\opencv\sources\modules\imgproc\src

filter.cpp

smooth.cpp

最后送各种模板边缘插值测试程序一枚:

#include "stdafx.h"
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
using namespace cv;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
	vector<double> vecortImg(9);
	CvMat* M = cvCreateMat(3, 3, CV_64FC1);
	double num =-1;
	for (int i = 0; i < 3; i++){
		for (int j = 0; j < 3; j++){
			cvmSet(M, i, j, ++num);
			cout << num <<"	";
			vecortImg.at(i*3+j) =  num;//因为滤波的不同导致的不同呀…………
		}	
	    	cout << endl;
	}
	//! various border interpolation methods
	/*
	Various border types, image boundaries are denoted with '|'

	* BORDER_REPLICATE:     aaaaaa|abcdefgh|hhhhhhh
	* BORDER_REFLECT:       fedcba|abcdefgh|hgfedcb
	* BORDER_REFLECT_101:   gfedcb|abcdefgh|gfedcba
	* BORDER_WRAP:          cdefgh|abcdefgh|abcdefg
	* BORDER_CONSTANT:      iiiiii|abcdefgh|iiiiiii  with some specified 'i'
	*/
	cout <<"平滑后"<<endl;
	Mat tempM;
	try{
		blur(Mat(M), tempM, cv::Size(3, 3), Point(-1, -1), BORDER_WRAP);
	}
	catch (cv::Exception e){
		cout << e.what();
	}
	Mat hh = tempM;
	vector<double> markdata1;
	int row = hh.rows ;
	int col = hh.cols;
	double* pMatdata = (double*)hh.data;
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++){
			cout << *(pMatdata + i * 3 + j)<<"	";
			markdata1.push_back(*(pMatdata + i*3+j));
		}
		cout << endl;
	}
	cvReleaseMat(&M);
 
	system("PAUSE");
	return 0;
}






你可能感兴趣的:(opencv,blur,均值滤波,BORDER_WRAP)