PhotoShop算法实现进阶-模糊滤镜-运动模糊(二十四)
造成图像退化或者说使图像模糊的原因有很多种,如果是因为在摄像时相机和被摄景物之间有相对运动而造成的图像模糊则称为运动模糊。所得到图像中的景物往往会模糊不清,我们称之为运动模糊图像。运动模糊(Motion Blur)是一种抓取物体运动状态效果的滤镜,主要应用物体运动时曝光的摄影手法,模拟出在摄像中拍摄运动物体的间接曝光功能,从而使图像产生出一种动态效果。它通常用来制造物体掠过或移动的效果。
实现原理:运动模糊滤镜沿特定的方向,并以特定的强度进行模糊处理。首先,在数学上,Y轴向上为正,而在图像处理中,Y轴向下为正,所以在获取用户指定方向角度后,应先将其沿正方形旋转180°;接着,解决图像在指定方向上的位移问题。运动莫不是简单地将图像在指定的图像上移来移去,而是在距离限定的范围内,按某种方式复制并叠加像素。简单地可以看成,将一幅图像的多张副本叠放在指定的方向上,然后取其平均值;最后,要解决的问题就是图像的透明度,处理Alpha分类,这样最终产生的模糊效果才更理想。
实现算法:
// 添加运动模糊效果
// angle:运动的方向, distance:运动的距离
// 这里只是粗略的计算,以dx的长度为准,也可以以dy或dx+dy等长度为准
// 如果需要更精确的计算,请参考有关专业文献
void PhotoShop::MotionBlur(Mat& img, Mat& dst, int angle/* =30 */, int distance/* =100 */)
{
angle = angle%360;
if ( distance <1 ) distance = 1;
if ( distance > 200) distance = 200;
double radian = ((double)angle+180.0)/180.0*PI; // 角度转弧度
int dx = (int)((double)distance* cos(radian)+0.5);
int dy = (int)((double)distance* sin(radian)+0.5);
int sign;
if ( dx<0) sign = -1;
if ( dx>0) sign = 1;
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, i0, j0, 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;
for ( p=0; p<abs(dx); p++)
{
i0 = i + p*sign;
j0 = j + p*sign;
if ( i0>=0 && i0<height && j0>=0 && j0<width)
{
count++;
sum += getPixel(img, i0, j0, k);
}
}
if ( count == 0)
{
dstData[j*chns+k] = getPixel(img, i, j, k);
}
else
{
dstData[j*chns+k] = saturate_cast<uchar>(sum/(double)count+0.5);
}
}// for k
} // for j
}
}
测试效果(angle=60, distance = 50):
再来张女神的最爱:
下面这篇文章详细介绍了运动模糊,有兴趣的读者可以参考:
2、 高质量单幅图片运动去模糊