==============================================
版权所有:小熊不去实验室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