OpenCV3入门(十三)图像运动模糊

  • 2020 年 3 月 14 日
  • 筆記

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、参考文献

Motion Deblur Filter

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

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

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

PhotoShop算法实现进阶-模糊滤镜-运动模糊(二十四)

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

 

技术博客,转载请注明。

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