图像缩放示例

二维图像的缩放属于仿射变换或者透视变换的范畴,一般可以通过OpenCV的warpAffine()或者warpPerspective()函数实现。

出于兴趣,根据仿射变换公式自己简单写了一个函数实现图像的缩放,缩放中心设置为图像中心。

代码如下:

  1 #include <iostream>
  2 #include <string>
  3 #include <opencv2/opencv.hpp>
  4 
  5 using namespace std;
  6 using namespace cv;
  7 
  8 void zoomInAndOut(const float scale, const Mat srcImg, Mat &dstImg)
  9 {
 10     Mat M=Mat::eye(3,3,CV_32FC1);
 11     int imgHeight=srcImg.rows;
 12     int imgWidth=srcImg.cols;
 13 
 14     uchar* pSrcData = (uchar*)srcImg.data;
 15     uchar* pDstData = (uchar*)dstImg.data;
 16 
 17     Point2f center(imgWidth / 2.0, imgHeight / 2.0);
 18     //计算仿射矩阵
 19     M.at<float>(0, 0) = scale;
 20     M.at<float>(0, 2) = (1 - scale)*center.x;
 21     M.at<float>(1, 1) = scale;
 22     M.at<float>(1, 2) = (1 - scale)*center.y;
 23 
 24     float a11 = M.at<float>(0, 0);
 25     float a12 = M.at<float>(0, 1);
 26     float a13 = M.at<float>(0, 2);
 27     float a21 = M.at<float>(1, 0);
 28     float a22 = M.at<float>(1, 1);
 29     float a23 = M.at<float>(1, 2);
 30     float a31 = M.at<float>(2, 0);
 31     float a32 = M.at<float>(2, 1);
 32     float a33 = M.at<float>(2, 2);
 33 
 34     float bx = a11*a22 - a21*a12;
 35     float by = a12*a21 - a11*a22;
 36     if ( abs(bx) > 1e-3 && abs(by) > 1e-3)
 37     {
 38         bx = 1.0 / bx;
 39         by = 1.0 / by;
 40         float cx = a13*a22 - a23*a12;
 41         float cy = a13*a21 - a23*a11;
 42 
 43         for (int j =0; j < imgHeight; j++)
 44         {
 45             for (int i = 0; i < imgWidth; i++)
 46             {
 47                 float u = (a22*i - a12*j - cx) *bx;
 48                 float v = (a21*i - a11*j - cy) *by;
 49 
 50                 int u0 = floor(u);
 51                 int v0 = floor(v);
 52                 int u1 = floor(u0 + 1);
 53                 int v1 = floor(v0 + 1);
 54                 if (u0 >= 0 && v0 >= 0 && u1 < imgWidth && v1 < imgHeight)
 55                 {
 56                     float dx = u - u0;
 57                     float dy = v - v0;
 58                     float weight1 = (1 - dx)*(1 - dy);
 59                     float weight2 = dx*(1 - dy);
 60                     float weight3 = (1 - dx)*dy;
 61                     float weight4 = dx*dy;
 62 
 63                     pDstData[j*imgWidth * 3 + i * 3 + 0] = weight1*pSrcData[v0*imgWidth * 3 + u0 * 3 + 0] +
 64                         weight2*pSrcData[v0*imgWidth * 3 + u1 * 3 + 0] +
 65                         weight3*pSrcData[v1*imgWidth * 3 + u0 * 3 + 0] +
 66                         weight4*pSrcData[v1*imgWidth * 3 + u1 * 3 + 0];
 67                     pDstData[j*imgWidth * 3 + i * 3 + 1] = weight1*pSrcData[v0*imgWidth * 3 + u0 * 3 + 1] +
 68                         weight2*pSrcData[v0*imgWidth * 3 + u1 * 3 + 1] +
 69                         weight3*pSrcData[v1*imgWidth * 3 + u0 * 3 + 1] +
 70                         weight4*pSrcData[v1*imgWidth * 3 + u1 * 3 + 1];
 71                     pDstData[j*imgWidth * 3 + i * 3 + 2] = weight1*pSrcData[v0*imgWidth * 3 + u0 * 3 + 2] +
 72                         weight2*pSrcData[v0*imgWidth * 3 + u1 * 3 + 2] +
 73                         weight3*pSrcData[v1*imgWidth * 3 + u0 * 3 + 2] +
 74                         weight4*pSrcData[v1*imgWidth * 3 + u1 * 3 + 2];
 75                 }
 76                 else
 77                 {
 78                     pDstData[j*imgWidth * 3 + i * 3 + 0] =0;
 79                     pDstData[j*imgWidth * 3 + i * 3 + 1] =0;
 80                     pDstData[j*imgWidth * 3 + i * 3 + 2] =0;
 81                 }
 82                     
 83             }
 84         }
 85     }
 86 }
 87 
 88 void main()
 89 {
 90     string imgPath="data/source_images/";
 91     Mat srcImg = imread(imgPath+"moon.jpg");
 92     pyrDown(srcImg, srcImg);
 93     pyrDown(srcImg, srcImg);
 94 
 95     Mat dstImg = srcImg.clone();
 96     dstImg.setTo(0);
 97 
 98     namedWindow("showImg");
 99     imshow("showImg", srcImg);
100     waitKey(10);
101 
102     float scale = 0;
103     while (scale <= 2)
104     {
105         scale += 0.1;
106         zoomInAndOut(scale, srcImg, dstImg);
107 
108         imshow("showImg", dstImg);
109         waitKey(10);
110     }
111 
112 }
View Code

代码中采用反向映射方法,使用用双线性插值技术得到目标图像像素值

posted @ 2017-08-23 22:15  一度逍遥  阅读(523)  评论(0编辑  收藏  举报