1. 程式人生 > >OpenCV實現運動模糊影象的模擬

OpenCV實現運動模糊影象的模擬

        產生模糊和噪聲的原因有很多,比如拍攝環境的不穩定、拍攝裝置的不精密、拍攝物件的快速運動、空氣氣流的擾動、儲存與傳輸過程電路產生的錯誤等,本文要考慮的是由於拍攝物件和拍攝裝置相對運動引起的運動模糊。關於噪聲,其種類和產生的原因也是多種多樣,比如白噪聲、椒鹽噪聲、閃爍噪聲、褐色噪聲等。由於本文關注的重點在於對運動模糊的處理,所以對噪聲統一處理為加性的隨機噪聲。

運動模糊的數學原理

運動模糊,是在拍攝裝置快門開啟的時間內,物體在成像平面上的投影發生平移或旋轉,使接受的影像彼此發生重疊。

        為了便於用數學語言描述影象及其變換,現作如下規定:影象的左上角為座標原點(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;
}

一些問題

    對邊界的處理

        最簡單的處理方法是忽略,也就是在邊界附近僅利用現有的影象內畫素進行計算。這樣會在邊界處留有一列未處理的畫素,在其內側的畫素逐漸獲得模糊處理直到模糊長度達到預設值。 從程式碼可以看出,我的處理方法是讓邊界處儘量利用內側的畫素,但這樣使影象的邊緣看起來像是拉伸過一樣。         實際上,還可以使用數學方法推算邊界外的影象資訊,利用它們完成對邊界的正確處理。

    顏色的不連續

        從影象可以發現,這個方法對圖案較複雜的影象可以產生很好的效果,但在顏色變化比較平緩的區域,模糊之後容易產生很明顯的色階。這說明僅僅靠疊加一系列相鄰畫素獲得模糊效果是不夠的,還需要在模糊處理的過程中進行平滑濾波操作,使模糊後的影象更平滑。
更新: