专栏首页一棹烟波图像缩放示例

图像缩放示例

二维图像的缩放属于仿射变换或者透视变换的范畴,一般可以通过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 }

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • OpenCV鼠标滑轮事件

    鼠标的滑轮事件实现图像的缩放很方便,具体在回调函数中如下写: 其中scale可以在外部定义为全局变量,通过响应CV_EVENT_MOUSEWHEEL滑轮事件获取...

    一棹烟波
  • 仿射变换与透视变换

    仿射变换保证物体形状的“平直性”和“平行性”。透视变换不能保证物体形状的“平行性”。仿射变换是透视变换的特殊形式。 将透视变换写成3*3矩阵形式,即为M; 以下...

    一棹烟波
  • 图像添加径向畸变

    通常摄像机的镜头都会有镜头畸变,尤其是广角镜头,在做图像处理中往往会通过摄像机标定获取镜头的畸变系数,然后进行畸变校正。而在某些特殊的情况下,你可能会需要往图像...

    一棹烟波
  • OpenCV鼠标滑轮事件

    鼠标的滑轮事件实现图像的缩放很方便,具体在回调函数中如下写: 其中scale可以在外部定义为全局变量,通过响应CV_EVENT_MOUSEWHEEL滑轮事件获取...

    一棹烟波
  • PCL中可用的PointT类型

    PointXYZ是使用最常见的一个点数据类型,因为他之包含三维XYZ坐标信息,这三个浮点数附加一个浮点数来满足存储对齐,可以通过points[i].d...

    点云PCL博主
  • React Native Fetch网络请求

    ZY_FlyWay
  • 面试题五期-中高级测试工程师基础知识必备之selenium篇

    引言:自动化永远是避不开的,反正你入职的岗位要不要用自动化,你必须得会一点,加分项。这一块包括,自动化一些理念和自动化的工具使用。

    测试小兵
  • 那些你曾错过的Java题(一)

    这个专题主要是写一些我刷牛客网时遇到的一些错题和一些有趣的题目,大家也可以跟我一起做做

    Python进击者
  • 眼球轨迹大数据告诉你,看帅哥美女时,男女的关注点分别在哪里。

    当我们漫不经心浏览网站时,如果蹦出一张美女图,您的眼睛会盯向哪里?近日国外有一间调查公司借助眼球追踪技术,分析了消费者的网站浏览重点。其中有几项调查是针对男女生...

    小莹莹
  • 爬取微信公众号所有历史文章 - (03) python结合tesseract-ocr做图文识别

    前面我们讲到了adb的封装,里面具体讲到到了在一副图片中寻找目标的坐标并点击。这篇文章我们讲讲对一副图片的特定区域做截取,并利用开源库做图纹识别。

    efonfighting

扫码关注云+社区

领取腾讯云代金券