鼠标的滑轮事件实现图像的缩放很方便,具体在回调函数中如下写:
其中scale可以在外部定义为全局变量,通过响应CV_EVENT_MOUSEWHEEL滑轮事件获取Scale的具体值。
获取Scale值需要关注两个问题,滑轮滑动的方向和滑动量的大小。滑动方向通过getMouseWheelDelta(flags)获取,当返回值>0时,表示向前滑动;当返回值<0时,表示向后滑动。滑动量根据滑动方向自行设置相应的滑动步长即可。
void onMouse(int event, int x, int y, int flags, void* )
{
double value;
float step=0.02;
switch (event)
{
case CV_EVENT_MOUSEWHEEL:
value = getMouseWheelDelta(flags);
if (value>0)
scale +=step;
else if(value<0)
scale -=step;
break;
default:
break;
}
}
下面是简单编写的滑动滑轮实现图像的缩放操作代码:
1 #include <iostream>
2 #include <string>
3 #include <opencv2/opencv.hpp>
4
5 using namespace std;
6 using namespace cv;
7
8 float scale=1.0;
9
10 void zoomInAndOut(const float scale, const Mat srcImg, Mat &dstImg)
11 {
12 Mat M=Mat::eye(3,3,CV_32FC1);
13 int imgHeight=srcImg.rows;
14 int imgWidth=srcImg.cols;
15
16 uchar* pSrcData = (uchar*)srcImg.data;
17 uchar* pDstData = (uchar*)dstImg.data;
18
19 Point2f center(imgWidth / 2.0, imgHeight / 2.0);
20 //计算仿射矩阵
21 M.at<float>(0, 0) = scale;
22 M.at<float>(0, 2) = (1 - scale)*center.x;
23 M.at<float>(1, 1) = scale;
24 M.at<float>(1, 2) = (1 - scale)*center.y;
25
26 float a11 = M.at<float>(0, 0);
27 float a12 = M.at<float>(0, 1);
28 float a13 = M.at<float>(0, 2);
29 float a21 = M.at<float>(1, 0);
30 float a22 = M.at<float>(1, 1);
31 float a23 = M.at<float>(1, 2);
32 float a31 = M.at<float>(2, 0);
33 float a32 = M.at<float>(2, 1);
34 float a33 = M.at<float>(2, 2);
35
36 float bx = a11*a22 - a21*a12;
37 float by = a12*a21 - a11*a22;
38 if ( abs(bx) > 1e-3 && abs(by) > 1e-3)
39 {
40 bx = 1.0 / bx;
41 by = 1.0 / by;
42 float cx = a13*a22 - a23*a12;
43 float cy = a13*a21 - a23*a11;
44
45 for (int j =0; j < imgHeight; j++)
46 {
47 for (int i = 0; i < imgWidth; i++)
48 {
49 float u = (a22*i - a12*j - cx) *bx;
50 float v = (a21*i - a11*j - cy) *by;
51
52 int u0 = floor(u);
53 int v0 = floor(v);
54 int u1 = floor(u0 + 1);
55 int v1 = floor(v0 + 1);
56 if (u0 >= 0 && v0 >= 0 && u1 < imgWidth && v1 < imgHeight)
57 {
58 float dx = u - u0;
59 float dy = v - v0;
60 float weight1 = (1 - dx)*(1 - dy);
61 float weight2 = dx*(1 - dy);
62 float weight3 = (1 - dx)*dy;
63 float weight4 = dx*dy;
64
65 for (int k=0; k<srcImg.channels(); k++)
66 {
67 pDstData[j*imgWidth * 3 + i * 3 + k] = weight1*pSrcData[v0*imgWidth * 3 + u0 * 3 + k] +
68 weight2*pSrcData[v0*imgWidth * 3 + u1 * 3 + k] +
69 weight3*pSrcData[v1*imgWidth * 3 + u0 * 3 + k] +
70 weight4*pSrcData[v1*imgWidth * 3 + u1 * 3 + k];
71 }
72 }
73 else
74 {
75 for (int k=0; k<srcImg.channels(); k++)
76 {
77 pDstData[j*imgWidth * 3 + i * 3 + k] = 0;
78 }
79 }
80 }
81 }
82 }
83 }
84
85 void onMouse(int event, int x, int y, int flags, void* )
86 {
87 double value;
88 float step=0.02;
89 switch (event)
90 {
91 case CV_EVENT_MOUSEWHEEL:
92 value = getMouseWheelDelta(flags);
93 if (value>0)
94 scale +=step;
95 else if(value<0)
96 scale -=step;
97 break;
98 default:
99 break;
100 }
101 }
102
103 void main()
104 {
105 string imgPath="data/source_images/";
106 Mat srcImg = imread(imgPath+"moon.jpg");
107 pyrDown(srcImg, srcImg);
108 pyrDown(srcImg, srcImg);
109
110 Mat dstImg = srcImg.clone();
111 dstImg.setTo(0);
112
113 string windowName="showImg";
114 namedWindow(windowName);
115 imshow(windowName, srcImg);
116 waitKey(10);
117
118 setMouseCallback(windowName, onMouse, NULL);
119 float scaleMin=0.5;
120 float scaleMax=2;
121 while (true)
122 {
123 scale = (scale<scaleMin)? (scaleMin): scale;
124 scale = (scale>scaleMax)? (scaleMax): scale;
125 zoomInAndOut(scale, srcImg, dstImg);
126 imshow(windowName, dstImg);
127 waitKey(10);
128 }
129 }