學習OpenCV:濾鏡系列(5)——徑向模糊:縮放&旋轉

查志強發表於2014-11-25

【原文:http://blog.csdn.net/yangtrees/article/details/9103935

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

版權所有:小熊不去實驗室CSDN部落格

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


原理來自:Game Render

這效果在鬼泣4中切換場景時見過, 極品飛車12的運動模糊也有這種感覺.

PS裡稱為 徑向模糊->縮放, 還有一種 徑向模糊->旋轉。

縮放的原理:

確定一箇中心點(如0.5, 0.5), 跟當前畫素連一條線. 以當前畫素為中心, 線上上的附近畫素進行取樣, 最後取一下平均值.

同樣,旋轉的原理相似,就是相同半徑的一定鄰域內的均值。

縮放時,半徑變化,旋轉時,角度變化。


使用OpenCV實現


原圖:



徑向模糊->縮放:



  1. #include <math.h>  
  2. #include <opencv/cv.h>  
  3. #include <opencv/highgui.h>  
  4.   
  5. using namespace cv;  
  6. using namespace std;  
  7.   
  8. int num=40;//num:均值力度;  
  9.   
  10. int main()  
  11. {  
  12.     Mat src = imread("D:/test3.jpg",1);  
  13.     Mat src1u[3];  
  14.     split(src,src1u);  
  15.   
  16.     int width=src.cols;  
  17.     int heigh=src.rows;  
  18.     Mat img;  
  19.     src.copyTo(img);  
  20.     Point center(width/2,heigh/2);  
  21.   
  22.   
  23.     for (int y=0; y<heigh; y++)  
  24.     {  
  25.           
  26.         uchar *imgP  = img.ptr<uchar>(y);  
  27.   
  28.         for (int x=0; x<width; x++)  
  29.         {  
  30.             int R = norm(Point(x,y)-center);  
  31.             double angle = atan2((double)(y-center.y),(double)(x-center.x));  
  32.   
  33.             int tmp0=0,tmp1=0,tmp2=0;  
  34.               
  35.             for (int i=0;i<num;i++)      //num:均值力度 ,i為變化幅度;  
  36.             {  
  37.                 int tmpR = (R-i)>0?(R-i):0;  
  38.                   
  39.                 int newX = tmpR*cos(angle) + center.x;  
  40.                 int newY = tmpR*sin(angle) + center.y;  
  41.                   
  42.                 if(newX<0)newX=0;  
  43.                 if(newX>width-1)newX=width-1;  
  44.                 if(newY<0)newY=0;  
  45.                 if(newY>heigh-1)newY=heigh-1;  
  46.   
  47.                 tmp0 += src1u[0].at<uchar>(newY,newX);  
  48.                 tmp1 += src1u[1].at<uchar>(newY,newX);  
  49.                 tmp2 += src1u[2].at<uchar>(newY,newX);  
  50.   
  51.             }  
  52.             imgP[3*x]=(uchar)(tmp0/num);  
  53.             imgP[3*x+1]=(uchar)(tmp1/num);  
  54.             imgP[3*x+2]=(uchar)(tmp2/num);  
  55.         }  
  56.           
  57.     }  
  58.     imshow("徑向模糊",img);  
  59.     waitKey();  
  60.     imwrite("D:/徑向模糊(縮放).jpg",img);  
  61. }  


徑向模糊->旋轉:



  1. #include <math.h>  
  2. #include <opencv/cv.h>  
  3. #include <opencv/highgui.h>  
  4.   
  5. using namespace cv;  
  6. using namespace std;  
  7.   
  8. int num=20; //均值力度;  
  9.   
  10. int main()  
  11. {  
  12.     Mat src = imread("D:/test3.jpg",1);  
  13.     Mat src1u[3];  
  14.     split(src,src1u);  
  15.   
  16.     int width=src.cols;  
  17.     int heigh=src.rows;  
  18.     Mat img;  
  19.     src.copyTo(img);  
  20.     Point center(width/2,heigh/2);  
  21.   
  22.   
  23.     for (int y=0; y<heigh; y++)  
  24.     {  
  25.   
  26.         uchar *imgP  = img.ptr<uchar>(y);  
  27.   
  28.         for (int x=0; x<width; x++)  
  29.         {  
  30.             int R = norm(Point(x,y)-center);  
  31.             double angle = atan2((double)(y-center.y),(double)(x-center.x));  
  32.   
  33.             int tmp0=0,tmp1=0,tmp2=0;  
  34.   
  35.             for (int i=0;i<num;i++)  //均值力度;  
  36.             {  
  37.   
  38.                 angle+=0.01;        //0.01控制變化頻率,步長  
  39.   
  40.                 int newX = R*cos(angle) + center.x;  
  41.                 int newY = R*sin(angle) + center.y;  
  42.   
  43.                 if(newX<0)newX=0;  
  44.                 if(newX>width-1)newX=width-1;  
  45.                 if(newY<0)newY=0;  
  46.                 if(newY>heigh-1)newY=heigh-1;  
  47.   
  48.                 tmp0 += src1u[0].at<uchar>(newY,newX);  
  49.                 tmp1 += src1u[1].at<uchar>(newY,newX);  
  50.                 tmp2 += src1u[2].at<uchar>(newY,newX);  
  51.   
  52.             }  
  53.             imgP[3*x]=(uchar)(tmp0/num);  
  54.             imgP[3*x+1]=(uchar)(tmp1/num);  
  55.             imgP[3*x+2]=(uchar)(tmp2/num);  
  56.         }  
  57.   
  58.     }  
  59.     imshow("徑向模糊",img);  
  60.     waitKey();  
  61.     imwrite("D:/徑向模糊(旋轉).jpg",img);  
  62. }  



原理Reference:

http://blog.csdn.net/xoyojank/article/details/5146297

http://bbs.9ria.com/thread-111831-1-1.html


相關文章