1. 程式人生 > >OpenCV3入門(十三)影象運動模糊

OpenCV3入門(十三)影象運動模糊

1、原理

運動模糊產生: 由於相機感測器或物體相對運動, 按快門瞬間造成影象產生運動模糊。

在用攝像機獲取景物影象時,如果在相機曝光期間景物和攝像機之間存在相對運動,例如用照相機拍攝快速運動的物體,或者從行駛中的汽車上拍攝外面靜止不動的景物時,拍得的照片都可能存在模糊的現象,這種由於相對運動造成影象模糊現象就是運動模糊。運動模糊是一種圖片“退化”現象,無法反應真實的場景。

假設影象f(x,y)進行平面運動,x(t0)和y(t0)分別是在x和y方向上隨時間變化的量。那麼介質上(如膠片或數字儲存器)上任意點的曝光總數是通過對時間間隔內瞬間曝光量的積分得到的, 影象系統的快門在該段時間是開著的。假設快門開關所用的時間很短,因此光學成像過程不會受到影象運動干擾。運動模糊產生式:

 g(x,y): 代表運動模糊後在座標(x,y)的結果

T:代表曝光時間

2、實現過程

1)對影象方向分解為x和y方向;

2)因為影象Mat座標對應影象的正下,所以翻轉Y軸;

3)分別計算影象位移;

4)合併多個畫素,防止溢位求平均值。

3、程式碼例項

實驗程式碼如下。只是簡單的實現了模糊原理,沒有考慮加性噪聲n(x)。

void MotionBlur(Mat& img, Mat& dst, int angle, int distance)
{
    angle = -1*angle % 360;
    double radian = ((double)angle + 180.0) / 180.0*3.1415926; 
    int dx = (int)((double)distance* cos(radian) + 0.5);
    int dy = (int)((double)distance* sin(radian) + 0.5);

    int sign = 0;
    int height = img.rows;
    int width = img.cols;
    int chns = img.channels();

    if (dst.empty())    dst.create(height, width, img.type());
    int i, j, k;
int i0=0, j0=0, p, sum, count;
    for (i = 0; i < height; i++)
    {
        unsigned char* dstData = (unsigned char*)dst.data + dst.step*i;
        for (j = 0; j < width; j++)
        {
            for (k = 0; k < chns; k++)
            {
                sum = 0, count = 0;
                sign = (dx > 0) ? 1 : -1;
                for (p = 0; p < abs(dx); p++)
                {
                    i0 = i; 
                    j0 = j+p * sign;
                    if (i0 >= 0 && i0 < height && j0 >= 0 && j0 < width)
                    {
                        count++;
                        sum += img.at<Vec3b>(i0, j0)[k];
                    }
                }
                sign = (dy > 0) ? 1 : -1;
                for (p = 0; p < abs(dy); p++)
                {
                    i0 = i + p * sign;
                    j0 = j; 
                    if (i0 >= 0 && i0 < height && j0 >= 0 && j0 < width)
                    {
                        count++;
                        sum += img.at<Vec3b>(i0, j0)[k];
                    }
                }

                if (count == 0)
                {
                    dstData[j*chns + k] = img.at<Vec3b>(i0, j0)[k];
                }
                else
                {
                    dstData[j*chns + k] = saturate_cast<uchar>(sum / (double)count + 0.5);
                }

            }            
        }
    }
}

void test_motion()
{
    Mat src_img = imread("D:\\WORK\\5.OpenCV\\LeanOpenCV\\pic_src\\pic14.bmp");
    imshow("原圖", src_img);

    Mat dst_img;
    MotionBlur(src_img, dst_img, 180, 20);
    imshow("motion", dst_img);
}

4、測試

測試1:驗證模糊的方向,輸入棋盤格圖,輸出為不同方向的模糊效果圖。

輸出效果圖如下。

測試2:模糊效果如下圖。

測試3:模糊效果如下圖。

5、參考文獻

1、Motion Deblur Filter

https://docs.opencv.org/3.4/d1/dfd/tutorial_motion_deblur_filter.html

2、影象復原與重建篇——運動模糊

https://blog.csdn.net/jmu201521121021/article/details/80634361

3、PhotoShop演算法實現進階-模糊濾鏡-運動模糊(二十四)

https://blog.csdn.net/kezunhai/article/details/41757681

4、《OpenCV3 程式設計入門》,電子工業出版社,毛星雨著

5、《學習OpenCV》,清華大學出版社,Gary Bradski, Adrian kaehler著

技術部落格,轉載請註明。

https://www.cnblogs.com/pingwen/p/12495168.html