运动模糊原理介绍
运动模糊产生: 由于相机传感器或物体相对运动, 按快门瞬间造成图像产生运动模糊。 假设图像
f ( x , y )
f
(
x
,
y
)
进行平面运动,
x ( t 0 )
x
(
t
0
)
和
y ( t 0 )
y
(
t
0
)
风别是在x和y方向上随时间变化的量。那么介质上(如胶片或数字存储器)上任意点的曝光总数是通过对时间间隔内瞬间曝光量的积分得到的, 图像系统的快门在该段时间是开着的。假设快门开关所用的时间很短,因此光学成像过程不会受到图像运动干扰。则运动模糊产生式:
g ( x , y ) = ∫ T 0 f [ ( x − x 0 ( t ) ) , ( y − y 0 ( t ) ] d t ( 1 − 1 )
g
(
x
,
y
)
=
∫
0
T
f
[
(
x
−
x
0
(
t
)
)
,
(
y
−
y
0
(
t
)
]
d
t
(
1
−
1
)
g ( x , y )
g
(
x
,
y
)
: 代表运动模糊后在坐标(x,y)的结果T:代表曝光时间 还有一个曝光系数s(0-1), 最终结果
g ( x , y )
g
(
x
,
y
)
=
g ( x , y ) ∗ s
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);
sumValue += tempValue;
}
sumValue = sumValue > 255 ? 255 : sumValue;
destImg.at<double >(i, j) = (double )sumValue;
}
}
destImg.convertTo(destImg, CV_8UC1);
}
#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 ();
}