PhotoShop算法实现进阶-模糊滤镜-运动模糊(2104)
kezunhai@gmail.com
http://blog.csdn.net/kezunhai
造成图象退化或说使图象模糊的缘由有很多种,如果是由于在摄像时相机和被摄景物之间有相对运动而酿成的图象模糊则称为运动模糊。所得到图象中的景物常常会模糊不清,我们称之为运动模糊图象。运动模糊(Motion Blur)是1种抓取物体运动状态效果的滤镜,主要利用物体运动时暴光的摄影手法,摹拟出在摄像中拍摄运动物体的间接暴光功能,从而使图象产生出1种动态效果。它通经常使用来制造物体掠过或移动的效果。
实现原理:运动模糊滤镜沿特定的方向,并以特定的强度进行模糊处理。首先,在数学上,Y轴向上为正,而在图象处理中,Y轴向下为正,所以在获得用户指定方向角度后,应先将其沿正方形旋转180°;接着,解决图象在指定方向上的位移问题。运动莫不是简单地将图象在指定的图象上移来移去,而是在距离限定的范围内,按某种方式复制并叠加像素。简单地可以看成,将1幅图象的多张副本叠放在指定的方向上,然后取其平均值;最后,要解决的问题就是图象的透明度,处理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 = ⑴;
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):
再来张女神的最爱:
下面这篇文章详细介绍了运动模糊,有兴趣的读者可以参考:
1、甚么是运动模糊(Motion Blur)
2、 高质量单幅图片运动去模糊
作者:kezunhai 出处:http://blog.csdn.net/kezunhai 欢迎转载或分享,但请务必声明文章出处。