二维图像的缩放属于仿射变换或者透视变换的范畴,一般可以通过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 }
代码中采用反向映射方法,使用用双线性插值技术得到目标图像像素值
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有