【原文:http://blog.csdn.net/yangtrees/article/details/9103935】
==============================================
版权所有:小熊不去实验室CSDN博客
==============================================
原理来自:Game Render
这效果在鬼泣4中切换场景时见过, 极品飞车12的运动模糊也有这种感觉.
PS里称为 径向模糊->缩放, 还有一种 径向模糊->旋转。
缩放的原理:
确定一个中心点(如0.5, 0.5), 跟当前像素连一条线. 以当前像素为中心, 在线上的附近像素进行采样, 最后取一下平均值.
同样,旋转的原理相似,就是相同半径的一定邻域内的均值。
缩放时,半径变化,旋转时,角度变化。
使用OpenCV实现
原图:
径向模糊->缩放:
- #include <math.h>
- #include <opencv/cv.h>
- #include <opencv/highgui.h>
- using namespace cv;
- using namespace std;
- int num=40;//num:均值力度;
- int main()
- {
- Mat src = imread("D:/test3.jpg",1);
- Mat src1u[3];
- split(src,src1u);
- int width=src.cols;
- int heigh=src.rows;
- Mat img;
- src.copyTo(img);
- Point center(width/2,heigh/2);
- for (int y=0; y<heigh; y++)
- {
- uchar *imgP = img.ptr<uchar>(y);
- for (int x=0; x<width; x++)
- {
- int R = norm(Point(x,y)-center);
- double angle = atan2((double)(y-center.y),(double)(x-center.x));
- int tmp0=0,tmp1=0,tmp2=0;
- for (int i=0;i<num;i++) //num:均值力度 ,i为变化幅度;
- {
- int tmpR = (R-i)>0?(R-i):0;
- int newX = tmpR*cos(angle) + center.x;
- int newY = tmpR*sin(angle) + center.y;
- if(newX<0)newX=0;
- if(newX>width-1)newX=width-1;
- if(newY<0)newY=0;
- if(newY>heigh-1)newY=heigh-1;
- tmp0 += src1u[0].at<uchar>(newY,newX);
- tmp1 += src1u[1].at<uchar>(newY,newX);
- tmp2 += src1u[2].at<uchar>(newY,newX);
- }
- imgP[3*x]=(uchar)(tmp0/num);
- imgP[3*x+1]=(uchar)(tmp1/num);
- imgP[3*x+2]=(uchar)(tmp2/num);
- }
- }
- imshow("径向模糊",img);
- waitKey();
- imwrite("D:/径向模糊(缩放).jpg",img);
- }
径向模糊->旋转:
- #include <math.h>
- #include <opencv/cv.h>
- #include <opencv/highgui.h>
- using namespace cv;
- using namespace std;
- int num=20; //均值力度;
- int main()
- {
- Mat src = imread("D:/test3.jpg",1);
- Mat src1u[3];
- split(src,src1u);
- int width=src.cols;
- int heigh=src.rows;
- Mat img;
- src.copyTo(img);
- Point center(width/2,heigh/2);
- for (int y=0; y<heigh; y++)
- {
- uchar *imgP = img.ptr<uchar>(y);
- for (int x=0; x<width; x++)
- {
- int R = norm(Point(x,y)-center);
- double angle = atan2((double)(y-center.y),(double)(x-center.x));
- int tmp0=0,tmp1=0,tmp2=0;
- for (int i=0;i<num;i++) //均值力度;
- {
- angle+=0.01; //0.01控制变化频率,步长
- int newX = R*cos(angle) + center.x;
- int newY = R*sin(angle) + center.y;
- if(newX<0)newX=0;
- if(newX>width-1)newX=width-1;
- if(newY<0)newY=0;
- if(newY>heigh-1)newY=heigh-1;
- tmp0 += src1u[0].at<uchar>(newY,newX);
- tmp1 += src1u[1].at<uchar>(newY,newX);
- tmp2 += src1u[2].at<uchar>(newY,newX);
- }
- imgP[3*x]=(uchar)(tmp0/num);
- imgP[3*x+1]=(uchar)(tmp1/num);
- imgP[3*x+2]=(uchar)(tmp2/num);
- }
- }
- imshow("径向模糊",img);
- waitKey();
- imwrite("D:/径向模糊(旋转).jpg",img);
- }
原理Reference:
http://blog.csdn.net/xoyojank/article/details/5146297
http://bbs.9ria.com/thread-111831-1-1.html