OpenCV實現運動模糊影象的模擬
阿新 • • 發佈:2019-02-20
產生模糊和噪聲的原因有很多,比如拍攝環境的不穩定、拍攝裝置的不精密、拍攝物件的快速運動、空氣氣流的擾動、儲存與傳輸過程電路產生的錯誤等,本文要考慮的是由於拍攝物件和拍攝裝置相對運動引起的運動模糊。關於噪聲,其種類和產生的原因也是多種多樣,比如白噪聲、椒鹽噪聲、閃爍噪聲、褐色噪聲等。由於本文關注的重點在於對運動模糊的處理,所以對噪聲統一處理為加性的隨機噪聲。
運動模糊的數學原理
運動模糊,是在拍攝裝置快門開啟的時間內,物體在成像平面上的投影發生平移或旋轉,使接受的影像彼此發生重疊。
為了便於用數學語言描述影象及其變換,現作如下規定:影象的左上角為座標原點(0,0),影象的長度方向為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; }
一些問題
對邊界的處理
最簡單的處理方法是忽略,也就是在邊界附近僅利用現有的影象內畫素進行計算。這樣會在邊界處留有一列未處理的畫素,在其內側的畫素逐漸獲得模糊處理直到模糊長度達到預設值。 從程式碼可以看出,我的處理方法是讓邊界處儘量利用內側的畫素,但這樣使影象的邊緣看起來像是拉伸過一樣。 實際上,還可以使用數學方法推算邊界外的影象資訊,利用它們完成對邊界的正確處理。顏色的不連續
更新: