OpenCV实现运动模糊图像的模拟
2012-12-03 13:58
417 查看
产生模糊和噪声的原因有很多,比如拍摄环境的不稳定、拍摄设备的不精密、拍摄对象的快速运动、空气气流的扰动、储存与传输过程电路产生的错误等,本文要考虑的是由于拍摄对象和拍摄设备相对运动引起的运动模糊。关于噪声,其种类和产生的原因也是多种多样,比如白噪声、椒盐噪声、闪烁噪声、褐色噪声等。由于本文关注的重点在于对运动模糊的处理,所以对噪声统一处理为加性的随机噪声。
为了便于用数学语言描述图像及其变换,现作如下规定:图像的左上角为坐标原点(0,0),图像的长度方向为x轴,宽度方向为y轴,整个图像落在第一象限。
假设无任何模糊和噪声的真实图像为f(x,y),模糊图像为g(x,y)。由于运动模糊是由图像彼此重叠造成的,所以成立:
其中,Cx为图像在方向上的平移速度,Cy为在方向上的平移速度,T为快门打开时间即产生模糊图像的时间,n(x,y)为加性噪声。
对于真实图像,模糊图像自然是原始图像的叠加,但对于数字图像,由于像素信息由数值表示,不能简单地将相应像素值相加,而是将像素信息缩小后相加,否则会使亮度成倍增加,使图像严重失真。
模糊处理后的图像:
从代码可以看出,我的处理方法是让边界处尽量利用内侧的像素,但这样使图像的边缘看起来像是拉伸过一样。
实际上,还可以使用数学方法推算边界外的图像信息,利用它们完成对边界的正确处理。
更新:
@RuifDu 提到色阶是用char计算累加的运算误差造成的,我改用浮点数计算,产生了正常的结果。我把图片和代码都已经更新。并在博客内提供了cpp版本代码:http://johnhany.net/2013/12/opencv-filter-template/
运动模糊的数学原理
运动模糊,是在拍摄设备快门打开的时间内,物体在成像平面上的投影发生平移或旋转,使接受的影像彼此发生重叠。为了便于用数学语言描述图像及其变换,现作如下规定:图像的左上角为坐标原点(0,0),图像的长度方向为x轴,宽度方向为y轴,整个图像落在第一象限。
假设无任何模糊和噪声的真实图像为f(x,y),模糊图像为g(x,y)。由于运动模糊是由图像彼此重叠造成的,所以成立:
其中,Cx为图像在方向上的平移速度,Cy为在方向上的平移速度,T为快门打开时间即产生模糊图像的时间,n(x,y)为加性噪声。
计算机实现细节
为了简化计算过程,我假设只有运动模糊而没有任何加性噪声,而且产生模糊的运动是沿x方向的。对于真实图像,模糊图像自然是原始图像的叠加,但对于数字图像,由于像素信息由数值表示,不能简单地将相应像素值相加,而是将像素信息缩小后相加,否则会使亮度成倍增加,使图像严重失真。
例子一枚
原图像:模糊处理后的图像:
代码
/* opencv version 2.3.1 */ #include "stdafx.h" #include "highgui.h" #include "cv.h" void motionblur(IplImage* in, IplImage* out, int steps_x) { int cnl,step; int length=in->widthStep; for(int y=0;y<in->height;y++) { uchar* pin=(uchar*)(in->imageData+y*in->widthStep); uchar* pout=(uchar*)(out->imageData+y*out->widthStep); int temp; for(int x=0;x<in->width;x++) { for(cnl=0;cnl<3;cnl++) { float sum = (float)pin[3*x+cnl]/steps_x; for(step=1;step<steps_x;step++) { if(step<=x) temp=step; else temp=step+x; sum += (float)pin[3*x+cnl-temp*3]/steps_x; } pout[3*x+cnl] = (uchar)sum; } } } } int main() { IplImage* img = cvLoadImage("H:\\original.jpg"); cvNamedWindow("Origin",CV_WINDOW_AUTOSIZE); cvNamedWindow("Blur",CV_WINDOW_AUTOSIZE); cvShowImage("Origin",img); IplImage* blur = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3); motionblur(img,blur,10); cvShowImage("Blur",blur); cvSaveImage("H:\\original_mblur.jpg",blur); cvWaitKey(0); cvReleaseImage(&img); cvReleaseImage(&blur); cvDestroyWindow("From"); cvDestroyWindow("To"); return 0; }
一些问题
对边界的处理
最简单的处理方法是忽略,也就是在边界附近仅利用现有的图像内像素进行计算。这样会在边界处留有一列未处理的像素,在其内侧的像素逐渐获得模糊处理直到模糊长度达到预设值。从代码可以看出,我的处理方法是让边界处尽量利用内侧的像素,但这样使图像的边缘看起来像是拉伸过一样。
实际上,还可以使用数学方法推算边界外的图像信息,利用它们完成对边界的正确处理。
颜色的不连续
从图像可以发现,这个方法对图案较复杂的图像可以产生很好的效果,但在颜色变化比较平缓的区域,模糊之后容易产生很明显的色阶。这说明仅仅靠叠加一系列相邻像素获得模糊效果是不够的,还需要在模糊处理的过程中进行平滑滤波操作,使模糊后的图像更平滑。更新:
@RuifDu 提到色阶是用char计算累加的运算误差造成的,我改用浮点数计算,产生了正常的结果。我把图片和代码都已经更新。并在博客内提供了cpp版本代码:http://johnhany.net/2013/12/opencv-filter-template/
相关文章推荐
- PCL+OpenCV+WebCam实现模拟深度图像实时点云数据采集
- 运动模糊图像处理(一)----- 模糊角度估计的算法研究及matlab实现
- OPENCV2学习(1)_生成运动模糊核(OPENCV2 实现Matlab中fspecial的motion功能)
- OpenCV实现静止背景下运动目标的检测
- OpenCV下实现单窗口显示多幅图像的源码!
- 高斯图像模糊算法及其 C 实现
- 图像处理中几个常用函数(Opencv实现)
- OpenCV学习--实现两幅图像的融合
- 从单幅图像高质量去除运动模糊——读JiaYaJia同名英文论文总结
- OpenCV图像模糊
- opencv读图像C语言实现canny边缘检测
- DCT简单图像压缩的OpenCV实现
- 毕业设计基于OpenCV的图像特征提取软件的设计与实现,部分展示
- 基于OpenCV的图像模糊与否检测
- Opencv 基础学习三 (OpenCV实现图像合并主要有两种方法)
- opencv缩放图像的实现
- VS2010实现opencv基于DCT的图像压缩
- 利用OpenCV实现图像拼接的代码!
- opencv2.4.10+vs2008实现图像的拼接
- OpenCV图像增强算法实现(直方图均衡化、拉普拉斯、Log、Gamma)