zoukankan      html  css  js  c++  java
  • 图像缩放示例

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

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

    --------------------------------- 业精于勤而荒于嬉 行成于思而毁于随 ---------------------------------
  • 相关阅读:
    Vue 从入门到进阶之路(十四)
    Vue 从入门到进阶之路(十三)
    Vue 从入门到进阶之路(十二)
    Vue 从入门到进阶之路(十一)
    vue-cli 3.x 开发插件并发布到 npm
    2018 年终总结 & 2019 年度计划
    帝都夜话
    移动端实现拖拽的两种方法
    前端面试(原生js篇)
    在前端获取图片宽高
  • 原文地址:https://www.cnblogs.com/riddick/p/7420526.html
Copyright © 2011-2022 走看看