图像复原与重建篇——运动模糊

运动模糊原理介绍

  • 运动模糊产生: 由于相机传感器或物体相对运动, 按快门瞬间造成图像产生运动模糊。
  • 假设图像f(x,y)进行平面运动,x(t0)y(t0)风别是在x和y方向上随时间变化的量。那么介质上(如胶片或数字存储器)上任意点的曝光总数是通过对时间间隔内瞬间曝光量的积分得到的, 图像系统的快门在该段时间是开着的。假设快门开关所用的时间很短,因此光学成像过程不会受到图像运动干扰。则运动模糊产生式:
    g(x,y)=0Tf[(xx0(t)),(yy0(t)]dt(11)

    • 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();
}

这里写图片描述

展开阅读全文
©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值