1. 程式人生 > >影象復原與重建篇——運動模糊

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

運動模糊原理介紹

  • 運動模糊產生: 由於相機感測器或物體相對運動, 按快門瞬間造成影象產生運動模糊。
  • 假設影象 f ( x ,
    y )
    進行平面運動, x ( t 0 )
    y ( t 0 ) 風別是在x和y方向上隨時間變化的量。那麼介質上(如膠片或數字儲存器)上任意點的曝光總數是通過對時間間隔內瞬間曝光量的積分得到的, 影象系統的快門在該段時間是開著的。假設快門開關所用的時間很短,因此光學成像過程不會受到影象運動干擾。則運動模糊產生式:
    g ( x , y ) = 0 T f [ ( x x 0 ( t ) ) , ( y y 0 ( t ) ] d t ( 1 1 )
    • g ( x , y ) : 代表運動模糊後在座標(x,y)的結果
    • T:代表曝光時間
    • 還有一個曝光係數s(0-1), 最終結果 g ( x , y ) = g ( x , y ) s ,如果沒有曝光係數, 每個畫素灰度級都是0-255,積分後大部分個點都會超過255, 所以要曝光係數去微調,曝光係數值範圍(0,1)

運動模糊C++程式碼實現

/**
 * @brief motionBlur   實現運動模糊
 * @param srcImg       原圖
 * @param destImg      模糊後圖片
 * @param x            水平方向移動的距離
 * @param y            垂直方向移動距離
 * @param T            曝光時間
 * param s             曝光係數
 * @return  null
 * @note              by  jsc 0527
 *
 */
void motionBlur(cv::Mat srcImg, cv::Mat &destImg, double x, double y, int T, double s){
    int width;
    int height;
    width = srcImg.cols;
    height = srcImg.rows;
    if(srcImg.empty()){
        std::cout<<"image is empty!!";
        return;
    }
    double tempX;
    double tempY;
    int sumValue;
    int tempValue;
    destImg = cv::Mat::zeros(height,width, CV_64FC1);
    srcImg.convertTo(srcImg, CV_64FC1);
    for(int i = 0; i < height; i++){
        for(int j = 0; j < width; j++){
              tempX = 0;
              tempY =0;
              sumValue = 0;
              tempValue= 0;
              for(int t = 0; t < T; t++){
                  tempY = (double)i - (double)t / (double)T * x;  // 水平
                  tempX = (double)j - (double)t /  (double)T * y; // 垂直
                  tempX = (tempX - (int)tempX) >= 0.5 ? ceil(tempX) : floor(tempX);
                  tempY = (tempY - (int)tempY) >= 0.5 ? ceil(tempY) : floor(tempY);
                  tempX = tempX < 0 ? 0 : tempX;
                  tempY = tempY < 0 ? 0 : tempY;
                  tempX = tempX >= width ? width - 1  : tempX;
                  tempY = tempY >= height ? height - 1 : tempY;
                  tempValue =(int)( srcImg.at<double>((int)tempY, (int)tempX)*s); // 模糊後的畫素值
                  // std::cout << tempX <<" "<<tempY << " "<<tempValue<< std::endl;
                  sumValue += tempValue; // 積分累加
              }
              sumValue = sumValue > 255 ? 255 : sumValue;
              // std::cout << sumValue << std::endl;
              destImg.at<double>(i, j) = (double)sumValue;
        }
    }
    destImg.convertTo(destImg, CV_8UC1);
}
  • demo
    main.cpp
#include <opencv2/opencv.hpp>
#include <string.h>
#include <iostream>
#include <math.h>
void main(){
  cv::Mat img = cv::imread("../face.jpg");
    cv::Mat result;
    cv::Mat grayImage;
    cv::cvtColor(img,grayImage, CV_BGR2GRAY);
    motionBlur(grayImage, result, 10, 10, 10, 0.2);
    cv::imshow("gray", grayImage);
    cv::imshow("motionBlur Image", result);
    cv::waitKey();
}

這裡寫圖片描述