学习OpenCV:滤镜系列(5)——径向模糊:缩放&旋转

==============================================

版权所有:小熊不去实验室CSDN博客

==============================================


原理来自:Game Render

这效果在鬼泣4中切换场景时见过, 极品飞车12的运动模糊也有这种感觉.

PS里称为 径向模糊->缩放, 还有一种 径向模糊->旋转。

缩放的原理:

确定一个中心点(如0.5, 0.5), 跟当前像素连一条线. 以当前像素为中心, 在线上的附近像素进行采样, 最后取一下平均值.

学习OpenCV:滤镜系列(5)——径向模糊:缩放&旋转_第1张图片

同样,旋转的原理相似,就是相同半径的一定邻域内的均值。

缩放时,半径变化,旋转时,角度变化。


使用OpenCV实现


原图:

学习OpenCV:滤镜系列(5)——径向模糊:缩放&旋转_第2张图片


径向模糊->缩放:

学习OpenCV:滤镜系列(5)——径向模糊:缩放&旋转_第3张图片


#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);
}


径向模糊->旋转:

学习OpenCV:滤镜系列(5)——径向模糊:缩放&旋转_第4张图片


#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


你可能感兴趣的:(学习OpenCV:滤镜系列(5)——径向模糊:缩放&旋转)