PhotoShop算法实现进阶-模糊滤镜-径向模糊(二十五)
径向模糊(Radial Blur)滤镜是一种产生螺旋效果的模糊滤镜,通常用来模拟摄影中前后移动或旋转相机镜头以产生一种聚焦或变焦的效果,使图像由中心向四周旋转辐射。
实现原理:径向模糊滤镜沿特定旋转方向,并以特定的强度进行模糊处理,它的实现方法类似我们前面介绍的运动模糊。首先,要解决图像径向模糊的角度问题,通过这个径向角度,使图像沿中心做旋转便宜处理;接着,要解决图像在旋转方向上的模糊强度问题,它就是将图像中的所有像素点沿图像中心做同心圆旋转,并叠加轨迹上的所有像素;最后,如果处理alpha分量,则会产生更好的效果。
算法实现比较复杂(实现参考联骏:图像编程精髓:从开发自己的Photoshop开始):
void PhotoShop::RadialBlur(Mat& img, Mat& dst, int iteration, int angle /* = 30 */)
{
angle = angle%360;
double radian = (double)angle/180.0*PI; // 角度转弧度
double radian2 = radian*radian;
int iteration2 = iteration*iteration;
int height = img.rows;
int width = img.cols;
int chns = img.channels();
int midX = width/2;
int midY = height/2;
if (dst.empty())
dst.create(height, width, img.type());
int i,j ,k, i0, j0, count;
double rSum, gSum, bSum;
double xoffset, yoffset, xoffsetCCW, yoffsetCCW, xoffsetCW, yoffsetCW;
for ( i=0; i<height; i++)
{
for ( j=0; j<width; j++)
{
xoffsetCCW = xoffsetCW = j-midX;
yoffsetCCW = yoffsetCW = i-midY;
rSum = gSum = bSum = 0;
count = 0;
count++;
rSum += getPixel(img, i, j, 0);
gSum += getPixel(img, i, j, 1);
bSum += getPixel(img, i, j, 2);
for ( k =0; k<iteration; k++)
{
xoffset = xoffsetCCW; //逆时针(正向)偏移
yoffset = yoffsetCCW;
// 插值算坐标
xoffsetCCW = xoffset - radian*yoffset/iteration - radian2*xoffset/iteration2;
yoffsetCCW = yoffset - radian*xoffset/iteration - radian2*yoffsetCCW/iteration2;
i0 = (int)yoffsetCCW + midY;
j0 = (int)xoffsetCCW + midX;
if ( i0>=0 && i0<height && j0>=0 && j0<width)
{
count++;
rSum += getPixel(img, i0, j0, 0);
gSum += getPixel(img, i0, j0, 1);
bSum += getPixel(img, i0, j0, 2);
}
// 顺时针偏移
xoffset = xoffsetCW;
yoffset = yoffsetCW;
xoffsetCW = xoffset + radian*yoffset/iteration - radian2*xoffset/iteration2;
yoffsetCW = yoffset - radian*xoffset/iteration2 - radian2*yoffset/iteration2;
i0 = (int)yoffsetCW + midY;
j0 = (int)xoffsetCW + midX;
if ( i0>=0 && i0<height && j0>=0 && j0<width)
{
count++;
rSum += getPixel(img, i0, j0, 0);
gSum += getPixel(img, i0, j0, 1);
bSum += getPixel(img, i0, j0, 2);
}
} // for k
setPixel(dst, i, j, 0, saturate_cast<uchar>(rSum/count+0.5));
setPixel(dst, i, j, 1, saturate_cast<uchar>(gSum/count+0.5));
setPixel(dst, i, j, 2, saturate_cast<uchar>(bSum/count+0.5));
}
}
}
测试效果:
最后再来两张养眼类似算法的图片:
养眼哈,再看下面一张,深呼吸。。。。。
有点唬人,Sorry~~~~~~