专栏首页一棹烟波OpenCV鼠标滑轮事件

OpenCV鼠标滑轮事件

鼠标的滑轮事件实现图像的缩放很方便,具体在回调函数中如下写:

其中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 }

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 图像缩放示例

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

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

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

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

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

    一棹烟波
  • 图像缩放示例

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

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

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

    点云PCL博主
  • UBports的“helloworld”和甜甜圈

    把手机变成C++学习机,当然也能变Python学习机,单片机学习机,机器人学习机,后续一点一点更新,有空就会更新快一点。

    zhangrelay
  • View绘制系列(13)-Canvas渐变属性绘制

    这种渐变效果我们能画吗?不得不说,Android系统的基础构架还是很强大的,我们可以使用LinearGradient进行绘制,与其相关的还有SweepGradi...

    小海编码日记
  • Head First设计模式——观察者模式

    前言: 这篇文章我们以Head First设计模式中讲解的气象站为例,通过它的案列进行学分析和编码(C#)测试,并归纳总结出观察者模式。

    SpringSun
  • 【分享】 PetaLinux工程出现大量Taskhash mismatch错误的原因

    Hank Fu (付汉杰) Staff FAE embedded, Xilinx, Inc. hankf@xilinx.com

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

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

    测试小兵

扫码关注云+社区

领取腾讯云代金券