图像放大并进行BiCubic插值

构造BiCubic函数:

其中,a取-0.5.

[source: http://en.wikipedia.org/wiki/Bicubic_interpolation]

BiCubic函数具有如下形状:

图像放大并进行BiCubic插值_第1张图片

[source:  R. Keys, (1981). "Cubic convolution interpolation for digital image processing". IEEE Transactions on Signal Processing, Acoustics, Speech, and Signal Processing 29 (6): 1153–1160.]

对待插值的像素点(x,y)(x和y可以为浮点数),取其附近的4x4邻域点(xi,yj), i,j = 0,1,2,3。按如下公式进行插值计算:

图像放大并进行BiCubic插值_第2张图片

实现代码:

[cpp]  view plain copy
  1. #include "opencv2/imgproc/imgproc.hpp"  
  2. #include "opencv2/highgui/highgui.hpp"  
  3. #include <iostream>  
  4. #include <cmath>  
  5. #include <fstream>  
  6.   
  7. using namespace cv;  
  8. using namespace std;  
  9.   
  10. #define PI 3.14159265  
  11.   
  12. float BiCubicPoly(float x);  
  13. void MyScaleBiCubicInter(Mat& src, Mat& dst, float TransMat[3][3]);  
  14. /** 
  15.  * @function main 
  16.  */  
  17. int main( int argc, char** argv )  
  18. {  
  19.   // load image  
  20.   char* imageName = "images/Lenna_256.png";  
  21.   
  22.   Mat image;  
  23.   image = imread(imageName,1);  
  24.   if(!image.data)  
  25.   {  
  26.       cout << "No image data" << endl;  
  27.       return -1;  
  28.   }  
  29.   
  30.   // show image  
  31.   namedWindow("image", CV_WINDOW_AUTOSIZE);  
  32.   imshow("image", image);  
  33.     
  34.     
  35.   Mat dst;  
  36.   float transMat[3][3] = { {2.0, 0, 0}, {0, 2.0, 0}, {0, 0, 1} };  
  37.   MyScaleBiCubicInter(image, dst, transMat);  
  38.     
  39.   
  40.   namedWindow("out_image", CV_WINDOW_AUTOSIZE);  
  41.   imshow("out_image", dst);  
  42.   
  43.   imwrite("Lenna_scale_biCubic2.jpg", dst);  
  44.   
  45.   waitKey(0);  
  46.       
  47.       
  48.   
  49.   return 0;  
  50. }  
  51.   
  52. float BiCubicPoly(float x)  
  53. {  
  54.     float abs_x = abs(x);  
  55.     float a = -0.5;  
  56.     if( abs_x <= 1.0 )  
  57.     {  
  58.         return (a+2)*pow(abs_x,3) - (a+3)*pow(abs_x,2) + 1;  
  59.     }  
  60.     else if( abs_x < 2.0 )  
  61.     {  
  62.         return a*pow(abs_x,3) - 5*a*pow(abs_x,2) + 8*a*abs_x - 4*a;  
  63.     }  
  64.     else  
  65.         return 0.0;  
  66.   
  67.       
  68. }  
  69.   
  70.   
  71.   
  72. void MyScaleBiCubicInter(Mat& src, Mat& dst, float TransMat[3][3])  
  73. {  
  74.     CV_Assert(src.data);  
  75.     CV_Assert(src.depth() != sizeof(uchar));  
  76.       
  77.     // calculate margin point of dst image  
  78.     float left =  0;  
  79.     float right =  0;  
  80.     float top =  0;  
  81.     float down =  0;  
  82.   
  83.     float x = src.cols * 1.0f;  
  84.     float y = 0.0f;  
  85.     float u1 = x * TransMat[0][0] + y * TransMat[0][1];  
  86.     float v1 = x * TransMat[1][0] + y * TransMat[1][1];  
  87.     x = src.cols * 1.0f;  
  88.     y = src.rows * 1.0f;  
  89.     float u2 = x * TransMat[0][0] + y * TransMat[0][1];  
  90.     float v2 = x * TransMat[1][0] + y * TransMat[1][1];  
  91.     x = 0.0f;  
  92.     y = src.rows * 1.0f;  
  93.     float u3 = x * TransMat[0][0] + y * TransMat[0][1];  
  94.     float v3 = x * TransMat[1][0] + y * TransMat[1][1];  
  95.   
  96.     left =  min( min( min(0.0f,u1), u2 ), u3);  
  97.     right =  max( max( max(0.0f,u1), u2 ), u3);  
  98.     top =  min( min( min(0.0f,v1), v2 ), v3);  
  99.     down =  max( max( max(0.0f,v1), v2 ), v3);  
  100.   
  101.     // create dst image  
  102.     dst.create(int(abs(right-left)), int(abs(down-top)), src.type());  
  103.       
  104.   
  105.     CV_Assert( dst.channels() == src.channels() );  
  106.     int channels = dst.channels();  
  107.   
  108.     int i,j;  
  109.     uchar* p;  
  110.     uchar* q0;  
  111.     uchar* q1;  
  112.     uchar* q2;  
  113.     uchar* q3;  
  114.     for( i = 0; i < dst.rows; ++i)  
  115.     {  
  116.         p = dst.ptr<uchar>(i);  
  117.         for ( j = 0; j < dst.cols; ++j)  
  118.         {  
  119.             //   
  120.             x = (j+left)/TransMat[0][0]  ;   
  121.             y = (i+top)/TransMat[1][1] ;  
  122.   
  123.             int x0 = int(x) - 1;  
  124.             int y0 = int(y) - 1;  
  125.             int x1 = int(x);  
  126.             int y1 = int(y);  
  127.             int x2 = int(x) + 1;  
  128.             int y2 = int(y) + 1;  
  129.             int x3 = int(x) + 2;  
  130.             int y3 = int(y) + 2;  
  131.   
  132.             if( (x0 >= 0) && (x3 < src.cols) && (y0 >= 0) && (y3 < src.rows) )   
  133.             {  
  134.                 q0 = src.ptr<uchar>(y0);  
  135.                 q1 = src.ptr<uchar>(y1);  
  136.                 q2 = src.ptr<uchar>(y2);  
  137.                 q3 = src.ptr<uchar>(y3);  
  138.                   
  139.                 float dist_x0 = BiCubicPoly(x-x0);  
  140.                 float dist_x1 = BiCubicPoly(x-x1);  
  141.                 float dist_x2 = BiCubicPoly(x-x2);  
  142.                 float dist_x3 = BiCubicPoly(x-x3);  
  143.                 float dist_y0 = BiCubicPoly(y-y0);  
  144.                 float dist_y1 = BiCubicPoly(y-y1);  
  145.                 float dist_y2 = BiCubicPoly(y-y2);  
  146.                 float dist_y3 = BiCubicPoly(y-y3);  
  147.   
  148.                 float dist_x0y0 = dist_x0 * dist_y0;  
  149.                 float dist_x0y1 = dist_x0 * dist_y1;  
  150.                 float dist_x0y2 = dist_x0 * dist_y2;  
  151.                 float dist_x0y3 = dist_x0 * dist_y3;  
  152.                 float dist_x1y0 = dist_x1 * dist_y0;  
  153.                 float dist_x1y1 = dist_x1 * dist_y1;  
  154.                 float dist_x1y2 = dist_x1 * dist_y2;  
  155.                 float dist_x1y3 = dist_x1 * dist_y3;  
  156.                 float dist_x2y0 = dist_x2 * dist_y0;  
  157.                 float dist_x2y1 = dist_x2 * dist_y1;  
  158.                 float dist_x2y2 = dist_x2 * dist_y2;  
  159.                 float dist_x2y3 = dist_x2 * dist_y3;  
  160.                 float dist_x3y0 = dist_x3 * dist_y0;  
  161.                 float dist_x3y1 = dist_x3 * dist_y1;  
  162.                 float dist_x3y2 = dist_x3 * dist_y2;  
  163.                 float dist_x3y3 = dist_x3 * dist_y3;  
  164.                   
  165.   
  166.                 switch(channels)  
  167.                 {  
  168.                     case 1:  
  169.                         {  
  170.                             break;  
  171.                         }  
  172.                     case 3:  
  173.                         {  
  174.                             p[3*j] =    (uchar)(q0[3*x0] * dist_x0y0 +  
  175.                                                 q1[3*x0] * dist_x0y1 +  
  176.                                                 q2[3*x0] * dist_x0y2 +  
  177.                                                 q3[3*x0] * dist_x0y3 +  
  178.                                                 q0[3*x1] * dist_x1y0 +  
  179.                                                 q1[3*x1] * dist_x1y1 +  
  180.                                                 q2[3*x1] * dist_x1y2 +  
  181.                                                 q3[3*x1] * dist_x1y3 +  
  182.                                                 q0[3*x2] * dist_x2y0 +  
  183.                                                 q1[3*x2] * dist_x2y1 +  
  184.                                                 q2[3*x2] * dist_x2y2 +  
  185.                                                 q3[3*x2] * dist_x2y3 +  
  186.                                                 q0[3*x3] * dist_x3y0 +  
  187.                                                 q1[3*x3] * dist_x3y1 +  
  188.                                                 q2[3*x3] * dist_x3y2 +  
  189.                                                 q3[3*x3] * dist_x3y3 ) ;  
  190.   
  191.                             p[3*j+1] =  (uchar)(q0[3*x0+1] * dist_x0y0 +  
  192.                                                 q1[3*x0+1] * dist_x0y1 +  
  193.                                                 q2[3*x0+1] * dist_x0y2 +  
  194.                                                 q3[3*x0+1] * dist_x0y3 +  
  195.                                                 q0[3*x1+1] * dist_x1y0 +  
  196.                                                 q1[3*x1+1] * dist_x1y1 +  
  197.                                                 q2[3*x1+1] * dist_x1y2 +  
  198.                                                 q3[3*x1+1] * dist_x1y3 +  
  199.                                                 q0[3*x2+1] * dist_x2y0 +  
  200.                                                 q1[3*x2+1] * dist_x2y1 +  
  201.                                                 q2[3*x2+1] * dist_x2y2 +  
  202.                                                 q3[3*x2+1] * dist_x2y3 +  
  203.                                                 q0[3*x3+1] * dist_x3y0 +  
  204.                                                 q1[3*x3+1] * dist_x3y1 +  
  205.                                                 q2[3*x3+1] * dist_x3y2 +  
  206.                                                 q3[3*x3+1] * dist_x3y3 ) ;  
  207.   
  208.                             p[3*j+2] =  (uchar)(q0[3*x0+2] * dist_x0y0 +  
  209.                                                 q1[3*x0+2] * dist_x0y1 +  
  210.                                                 q2[3*x0+2] * dist_x0y2 +  
  211.                                                 q3[3*x0+2] * dist_x0y3 +  
  212.                                                 q0[3*x1+2] * dist_x1y0 +  
  213.                                                 q1[3*x1+2] * dist_x1y1 +  
  214.                                                 q2[3*x1+2] * dist_x1y2 +  
  215.                                                 q3[3*x1+2] * dist_x1y3 +  
  216.                                                 q0[3*x2+2] * dist_x2y0 +  
  217.                                                 q1[3*x2+2] * dist_x2y1 +  
  218.                                                 q2[3*x2+2] * dist_x2y2 +  
  219.                                                 q3[3*x2+2] * dist_x2y3 +  
  220.                                                 q0[3*x3+2] * dist_x3y0 +  
  221.                                                 q1[3*x3+2] * dist_x3y1 +  
  222.                                                 q2[3*x3+2] * dist_x3y2 +  
  223.                                                 q3[3*x3+2] * dist_x3y3 ) ;  
  224.   
  225.                             float thre = 198.0f;  
  226.                             if( (abs(p[3*j]-q1[3*x1]) > thre) || (abs(p[3*j+1]-q1[3*x1+1]) > thre) ||  
  227.                                 (abs(p[3*j+2]-q1[3*x1+2]) > thre) )  
  228.                             {  
  229.                                 p[3*j] = q1[3*x1];  
  230.                                 p[3*j+1] = q1[3*x1+1];  
  231.                                 p[3*j+2] = q1[3*x1+2];  
  232.                             }  
  233.                               
  234.   
  235.                             break;  
  236.                         }  
  237.                 }  
  238.             }  
  239.         }  
  240.     }  
  241. }  
转自 http://blog.csdn.net/lichengyu/article/details/8526629

你可能感兴趣的:(图像放大并进行BiCubic插值)