【图像处理】基于OpenCV底层实现的滤波

高斯滤波

高斯滤波器介绍:wikipedia。高斯滤波器的未知数(或者说函数输入)有两个:(1)滤波器核半径;(2)σ(正态分布的标准偏差)。在连续二维空间中,这个函数长这样:

除了函数中心是极大值,周围都是围绕中心对称的。

这样有一个好处,因为滤波器实质上是卷积(convolution)操作,卷积操作需要将核函数围绕中心翻转之后,在与对应矩阵中各个数相乘(注意:此时不是矩阵相乘,只是函数核中每个数字单独的相乘,不涉及整体相乘求和)。而高斯函数的对称的,所以函数核翻不翻转都一样结果。

首先,我们需要根据核半径(代码中slab = 2*r + 1)、σ(sigma)求出高斯核函数矩阵:

// get Gaussian Kernel Function
void ycGaussianKernel(float* kernel, int sigma, int slab)
{
	int index;
	float dx2, dy2;
	float sum = 0;
	for(int i=0; i<slab; i++)
	{
		dx2 = pow(i - (slab - 1)/2.0, 2);
		for(int j=0; j<slab; j++)
		{
			dy2 = pow(j - (slab - 1)/2.0, 2);
			index = i*slab + j;
			kernel[index] = exp(-(dx2 + dy2)/2/pow(sigma, 2)) / (2*PI*pow(sigma, 2));
			//printf("%f\n", kernel[index]);
			sum += kernel[index];
		}
	}

	for(int k=0; k< slab*slab; k++)
	{
		kernel[k] = kernel[k] / sum;
		//printf("%f\n", kernel[k]);
	}
}

这样可以得到高斯滤波函数为:

// Gaussian filter
Mat filterGaussian(cv::Mat img, const float sigma, const int slab)
{
	cvtColor(img, img, CV_BGR2GRAY);
	Mat retMat = Mat::zeros(img.rows, img.cols, CV_8UC1);
	for(int i=0; i<img.rows; i++)
		for(int j=0; j<img.cols; j++)
			retMat.at<uchar>(i, j) = img.at<uchar>(i, j);

	// 一维数组模拟二维数组
	float* kernel = new float[slab * slab];
	int* xLocation = new int[slab];
	int* yLocation = new int[slab];
	ycGaussianKernel(kernel, sigma, slab);
	float sum;
	int index;

	// 对于边缘,这里采取直接舍弃不计算的方法。因此,循环起点是 slab/2
	for(int i= slab/2; i<img.rows - slab/2; i++)
	{
		xLocation[slab/2] = i;
		for(int delta = 0; delta <= slab/2; delta++)
		{
			xLocation[slab/2 - delta] = i - delta;
			xLocation[slab/2 + delta] = i + delta;
		}

		for(int j= slab/2; j<img.cols - slab/2; j++)
		{
			yLocation[slab/2] = j;
			for(int delta = 0; delta <= slab/2; delta++)
			{
				yLocation[slab/2 - delta] = j - delta;
				yLocation[slab/2 + delta] = j + delta;
			}

			sum = 0;
			for(int fi=0; fi < slab; fi++)
			{
				for(int fj=0; fj < slab; fj++)
				{
					index = fi*slab + fj;
					sum += kernel[index] * img.at<uchar>(xLocation[fi], yLocation[fj]);
				}
			}
			retMat.at<uchar>(i ,j) = sum;
		}
	}

	return retMat;
}

均值滤波

这个没啥好说的,就是函数核内所有像素点求和之后平均,平均值即为核中心上的像素值。需要输入滤波核半径。

// Mean filter: 均值滤波器
Mat filterMean(cv::Mat img, const int slab)
{
	cvtColor(img, img, CV_BGR2GRAY);
	Mat retMat = Mat::zeros(img.rows, img.cols, CV_8UC1);
	for(int i=0; i<img.rows; i++)
		for(int j=0; j<img.cols; j++)
			retMat.at<uchar>(i, j) = img.at<uchar>(i, j);

	int* xLocation = new int[slab];
	int* yLocation = new int[slab];
	float sum;
	int index;

	for(int i= slab/2; i<img.rows - slab/2; i++)
	{
		xLocation[slab/2] = i;
		for(int delta = 0; delta <= slab/2; delta++)
		{
			xLocation[slab/2 - delta] = i - delta;
			xLocation[slab/2 + delta] = i + delta;
		}

		for(int j= slab/2; j<img.cols - slab/2; j++)
		{
			yLocation[slab/2] = j;
			for(int delta = 0; delta <= slab/2; delta++)
			{
				yLocation[slab/2 - delta] = j - delta;
				yLocation[slab/2 + delta] = j + delta;
			}

			sum = 0;
			for(int fi=0; fi < slab; fi++)
			{
				for(int fj=0; fj < slab; fj++)
				{
					index = fi*slab + fj;
					sum += img.at<uchar>(xLocation[fi], yLocation[fj]);
				}
			}
			retMat.at<uchar>(i ,j) = sum/(slab * slab);
		}
	}

	return retMat;
}

中值滤波

中值滤波跟均值滤波听起来很像,但不是一回事。中值滤波是将滤波核内各个像素由从小到大顺序排列,然后取序列中值作为核中心像素的值。需要输入滤波核半径,并且对于现有的像素序列排序。排序函数我是用快排(quickSort)写的,见这里。滤波器代码:

// Median filter: 中值滤波器
Mat filterMedian(cv::Mat img, const int slab)
{
	cvtColor(img, img, CV_BGR2GRAY);
	Mat retMat = Mat::zeros(img.rows, img.cols, CV_8UC1);
	for(int i=0; i<img.rows; i++)
		for(int j=0; j<img.cols; j++)
			retMat.at<uchar>(i, j) = img.at<uchar>(i, j);

	int* xLocation	= new int[slab];
	int* yLocation	= new int[slab];
	int* tmpArr		= new int[slab * slab];
	float sum;
	int index;

	for(int i= slab/2; i<img.rows - slab/2; i++)
	{
		xLocation[slab/2] = i;
		for(int delta = 0; delta <= slab/2; delta++)
		{
			xLocation[slab/2 - delta] = i - delta;
			xLocation[slab/2 + delta] = i + delta;
		}

		for(int j= slab/2; j<img.cols - slab/2; j++)
		{
			yLocation[slab/2] = j;
			for(int delta = 0; delta <= slab/2; delta++)
			{
				yLocation[slab/2 - delta] = j - delta;
				yLocation[slab/2 + delta] = j + delta;
			}

			for(int fi = 0; fi<slab; fi++)
				for(int fj =0; fj<slab; fj++)
				{
					index = fi*slab + fj;
					tmpArr[index] = img.at<uchar>(xLocation[fi], yLocation[fj]);
				}

			quickSort(tmpArr, 0, slab*slab - 1);
			retMat.at<uchar>(i ,j) = tmpArr[slab * slab / 2];
		}
	}

	return retMat;
}

滤波效果

原图为lena图,即:

对于高斯滤波,当sigma = 3,核函数为 3*3(slab = 3,核半径为 1)时,结果为:

对于均值滤波,当核函数为 5*5(slab = 5,核半径为 2)时,结果为:

对于中值滤波,当核函数为 7*7(slab = 7,核半径为 3)时,结果为:

时间: 2024-08-10 00:05:35

【图像处理】基于OpenCV底层实现的滤波的相关文章

【图像处理】基于OpenCV底层实现的图片旋转

image processing 系列 [图像处理]直方图匹配 [图像处理]高斯滤波.中值滤波.均值滤波 图片旋转,本质上是对旋转后的图片中每一个像素点计算在原图的位置.然后照搬过来就好. (多说一句.假设计算出来在原图中的位置不是整数而是小数,由于像素点个数都是整数,就须要小数到整数的转换. 这个转换过程是有讲究的,须要用到插值:近期邻插值.双线性插值等等.这里我使用的是最简单的近期邻插值.即对小数四舍五入成整数.C/C++ 实现四舍五入见这里) 完整 github 代码:image-proc

基于Opencv和Mfc的图像处理增强库GOCVHelper(索引)

GOCVHelper(GreenOpen Computer Version Helper )是我在这几年编写图像处理程序的过程中积累下来的函数库.主要是对Opencv的适当扩展和在实现Mfc程序时候的功能增强. 这里将算法库开放源代码,并且编写一系列blog对函数实现进行说明.目的是在于“取之于互联网,用之于互联网”.并且也希望该库能够继续发展下去. 由于算法库基于Opencv和Mfc进行编写,所以要求阅读使用者具备一定基础. 最终提交的是GOCVHelper.h 和GOCVHelper版本号.

基于 OpenCV 的人脸识别

基于 OpenCV 的人脸识别 一点背景知识 OpenCV 是一个开源的计算机视觉和机器学习库.它包含成千上万优化过的算法,为各种计算机视觉应用提供了一个通用工具包.根据这个项目的关于页面,OpenCV 已被广泛运用在各种项目上,从谷歌街景的图片拼接,到交互艺术展览的技术实现中,都有 OpenCV 的身影. OpenCV 起始于 1999 年 Intel 的一个内部研究项目.从那时起,它的开发就一直很活跃.进化到现在,它已支持如 OpenCL 和 OpenGL 的多种现代技术,也支持如 iOS

基于OpenCV的图片卡通化处理

学习OpenCV已有一段时间,除了研究各种算法的内容,在空闲之余,根据书本及资料的引导,尝试结合图像处理算法和日常生活联系起来,首先在台式机上(带摄像头)完成一系列视频流处理功能,开发平台为Qt5.3.2+OpenCV2.4.9. 本次试验实现的功能主要有: 调用摄像头捕获视频流: 将帧图像转换为素描效果图片: 将帧图像卡通化处理: 简单地生成"怪物"形象: 人脸肤色变换. 本节所有的算法均由类cartoon中的函数cartoonTransform()来实现: // Frame:输入每

Csharp调用基于Opencv编写的类库文件

现在将Csharp调用基于Opencv编写的类库文件(Dll)的方法定下来,我取名叫做GreenOpenCsharpWarper,简称GOCW. 一.CLR编写的DLL部分 1.按照正常方法引入Opencv; 2.提供接口函数,进行图像处理(这里只是实现了cvtColor,实际过程中可以用自己编写的复杂函数) String^  Class1::Method(cli::array<unsigned char>^ pCBuf1){     pin_ptr<System::Byte> p

每日一练之自适应中值滤波器(基于OpenCV实现)

本文主要介绍了自适应的中值滤波器,并基于OpenCV实现了该滤波器,并且将自适应的中值滤波器和常规的中值滤波器对不同概率的椒盐噪声的过滤效果进行了对比.最后,对中值滤波器的优缺点了进行了总结. 空间滤波器 一个空间滤波器包括两个部分: 一个邻域,滤波器进行操作的像素集合,通常是一个矩形区域 对邻域中像素进行的操作 一个滤波器就是在选定的邻域像素上执行预先定义好的操作产生新的像素,并用新的像素替换掉原来像素形成新的图像. 通常,也可以将滤波器称之为核(kernel),模板(template)或者窗

基于opencv和QT的瞳孔精确检测程序

本文为作者为毕业设计所写的瞳孔精确检测程序,谢绝任何形式的转载. 本篇博客是在作者的前两篇博客 <基于QT和opencv的摄像头(本地图片)读取并输出程序>和< 基于opencv和QT的人脸(人眼)检测程序>的基础上进行开发的.主要原理是:针对已经检测到的人眼区域图像,利用边缘检测和Hough变换实现瞳孔的精确检测. 首先建立一个图像处理类,对每一帧图像进行处理. class ImgProcess { private: Mat inimg;//输入图像 Mat outimg;//输

Java基于opencv实现图像数字识别(二)—基本流程

Java基于opencv实现图像数字识别(二)-基本流程 做一个项目之前呢,我们应该有一个总体把握,或者是进度条:来一步步的督促着我们来完成这个项目,在我们正式开始前呢,我们先讨论下流程. 我做的主要是表格中数字的识别,但这个不是重点.重点是通过这个我们可以举一反三,来实现我们自己的业务. 图像的识别主要分为两步:图片预处理和图像识别:这两步都很重要 图像预处理: 1. 图像灰度化:二值化 2. 图像降噪,去除干扰线 3. 图像腐蚀.膨胀处理 4. 字符分割 5. 字符归一化 图像识别: 1.

基于opencv网络摄像头在ubuntu下的视频获取

 基于opencv网络摄像头在ubuntu下的视频获取 1  工具 原料 平台 :UBUNTU12.04 安装库  Opencv-2.3 2  安装编译运行步骤 安装编译opencv-2.3  参考http://blog.csdn.net/xiabodan/article/details/23547847 3  测试代码 编译 g++ cameraCaptrue.cpp -o test `pkg-config --libs --cflags opencv` cameraCaptrue.cpp