opencv实现鼠标画矩形框、显示十字线、缩放图片

  • 简介
  • 材料收集
  • 开始设计
    • 1,将鼠标响应函数封装到类
    • 2.合理的显示图像
  • 全部代码
  • 项目资源

简介

实现一个在图片上框选区域的类,可以缩放图像方便操作,当图片过大的时候,只显示其中一部分,可以通过鼠标选定显示的区域中心。

材料收集

在csdn找到了两篇很有帮助的文章

第一篇,了解一下鼠标响应的基础
关于opencv2中鼠标响应操作.

我是在下面的项目下进行修改
opencv实现鼠标画矩形框、显示十字线、滚轮缩放.

开始设计

1,将鼠标响应函数封装到类

opencv的鼠标响应函数:

 CV_EXPORTS void setMouseCallback(const string& winname, MouseCallback onMouse, void* userdata = 0);

在将普通的类成员函数,定义为鼠标响应函数时,会发生参数个数不匹配的问题,因为普通成员函数都‘隐藏’了一个参数,一个指向对象本身的指针this,我们可以通过this指针访问对象成员

// 相当于
//void DetetColor::setColorId(int id,int colorSize,DetetColor * this)
void DetetColor::setColorId(int id,int colorSize)
{this->id=id;
}

静态成员函数不能访问对象的普通成员函数,普通数据成员,所以默认不包括指向对象的指针this。我们通过void * 指针传入对象指针,访问对象成员函数

void displayPicture::on_Mouse_ComplexRect(int event, int x, int y,int flag)//实现画矩形框
{if (event == EVENT_RBUTTONDOWN)        //按下右键,减少一个已框选区域,重画{。。。。}
}void displayPicture::on_Mouse_ComplexRect(int events, int x, int y, int flag, void* userdata)
{displayPicture* temp = reinterpret_cast<displayPicture*>(userdata);temp->on_Mouse_ComplexRect( events,x,y,flag);
}

2.合理的显示图像

显示器的界面是有限的,图片是大小不一的,合理的显示图像应该考虑的
1.图片小于窗口,显示全部图片
2.图片大于窗口,根据选定的中心,显示部分图片

void displayPicture::showImageInRange()
{int x1,x2,y1,y2;Point zoomCenter=Point(imageCenter.x*scale,imageCenter.y*scale);if(zoomImage.cols<rangewidth){x1=0;x2=zoomImage.cols-1;}else if(zoomCenter.x<rangewidth/2){x1=0;x2=rangewidth;}else if(zoomImage.cols-rangewidth/2<zoomCenter.x){x1=zoomImage.cols-rangewidth;x2=zoomImage.cols-1;}else{x1=zoomCenter.x-rangewidth/2;x2=zoomCenter.x+rangewidth/2;}if(zoomImage.rows<rangeheight){y1=0;y2=zoomImage.rows-1;}else if(zoomCenter.y<rangeheight/2){y1=0;y2=rangeheight;}else if(zoomImage.rows-rangeheight/2<zoomCenter.y){y1=zoomImage.rows-rangeheight;y2=zoomImage.rows-1;}else{y1=zoomCenter.y-rangeheight/2;y2=zoomCenter.y+rangeheight/2;}Rect roi(x1,y1,x2-x1,y2-y1);rectOfRoi=roi;rectOfRoi.x/=scale;rectOfRoi.y/=scale;rectOfRoi.width/=scale;rectOfRoi.height/=scale;roiImage=zoomImage(roi);
}

全部代码

头文件

#pragma once
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
class displayPicture
{public:displayPicture(Mat image);~displayPicture(void);void display();//选定感兴趣区域,获得与图像大小相同的maskvoid getMask(Mat &mask);//选定不感兴趣区域,获得maskvoid getMaskINV(Mat &mask);int rangewidth;int rangeheight;vector<Rect> selectRect;private:Mat srcImage;     Mat zoomImage;    //缩放的图片Mat roiImage;     //区域图像Mat showImage;    //显示的图片Point imageCenter;  //图像的中心Rect rectOfRoi;Point g_center;bool select_flag;double scale;double step;string WINNAME;void changeScale(double newscale);void on_Mouse_ComplexRect(int event, int x, int y,int flag);static void on_Mouse_ComplexRect(int events, int x, int y, int, void* userdata);void drawAllRectangle();void draw_crossline(Mat &img, const Point &pt);void showImageInRange();};

cpp文件

#include "displayPicture.h"displayPicture::displayPicture(Mat image)
{scale=1;step=0.05;select_flag=false;rangewidth=1600;rangeheight=900;imageCenter=Point(0,0);WINNAME="画板";srcImage=image;zoomImage=srcImage.clone();showImageInRange();showImage=roiImage.clone();
}displayPicture::~displayPicture(void)
{}
void displayPicture::changeScale(double newscale)
{scale=newscale;if(newscale>1)scale=1;if(newscale<0.1)scale=0.1;resize(srcImage,zoomImage,Size(),scale,scale);showImageInRange();drawAllRectangle();
}void displayPicture::display()
{namedWindow(WINNAME, 1);//添加鼠标相应setMouseCallback(WINNAME, displayPicture::on_Mouse_ComplexRect, this);drawAllRectangle();imshow(WINNAME,showImage);int key;while (1){key = waitKey(40);if (key == ' '){cv::destroyWindow(WINNAME);break;}else if (key == toascii('q')){changeScale(scale -step);imshow(WINNAME,showImage);//zoom(mouseParam.img, mouseParam.imgZoomBackup, mouseParam.pt1, mouseParam.scale);}else if (key == toascii('e')){changeScale(scale + step);imshow(WINNAME,showImage);//zoom(mouseParam.img, mouseParam.imgZoomBackup, mouseParam.pt1, mouseParam.scale);}}}void displayPicture::draw_crossline(Mat &img, const Point &pt)
{int width = img.cols;int height = img.rows;cv::Point ptv1;cv::Point ptv2;cv::Point pth1;cv::Point pth2;ptv1 = cv::Point(pt.x, 0);ptv2 = cv::Point(pt.x, height);pth1 = cv::Point(0, pt.y);pth2 = cv::Point(width, pt.y);cv::line(img, ptv1, ptv2, Scalar(255, 255, 0), 1);ptv1.x+=1;ptv2.x+=1;cv::line(img, ptv1, ptv2, Scalar(0, 0, 255), 1);cv::line(img, pth1, pth2, Scalar(255, 255, 0), 1);pth1.y+=1;pth2.y+=1;cv::line(img, pth1, pth2, Scalar(0, 0, 255), 1);
}void displayPicture::showImageInRange()
{int x1,x2,y1,y2;Point zoomCenter=Point(imageCenter.x*scale,imageCenter.y*scale);if(zoomImage.cols<rangewidth){x1=0;x2=zoomImage.cols-1;}else if(zoomCenter.x<rangewidth/2){x1=0;x2=rangewidth;}else if(zoomImage.cols-rangewidth/2<zoomCenter.x){x1=zoomImage.cols-rangewidth;x2=zoomImage.cols-1;}else{x1=zoomCenter.x-rangewidth/2;x2=zoomCenter.x+rangewidth/2;}if(zoomImage.rows<rangeheight){y1=0;y2=zoomImage.rows-1;}else if(zoomCenter.y<rangeheight/2){y1=0;y2=rangeheight;}else if(zoomImage.rows-rangeheight/2<zoomCenter.y){y1=zoomImage.rows-rangeheight;y2=zoomImage.rows-1;}else{y1=zoomCenter.y-rangeheight/2;y2=zoomCenter.y+rangeheight/2;}Rect roi(x1,y1,x2-x1,y2-y1);rectOfRoi=roi;rectOfRoi.x/=scale;rectOfRoi.y/=scale;rectOfRoi.width/=scale;rectOfRoi.height/=scale;roiImage=zoomImage(roi);
}
void displayPicture::on_Mouse_ComplexRect(int event, int x, int y,int flag)//实现画矩形框
{static Point p1, p2;if (event == EVENT_RBUTTONDOWN)        //按下右键,减少一个已框选区域,重画{//      selectRect.clear();selectRect.pop_back();drawAllRectangle();imshow(WINNAME, showImage);}else if ((flag&CV_EVENT_FLAG_CTRLKEY) &&event == EVENT_MOUSEMOVE)    //按下ctrl并移动鼠标{Mat temp;showImage.copyTo(temp);Point clickPoint(x,y);draw_crossline(temp, clickPoint);imshow(WINNAME, temp);}else if( event == EVENT_LBUTTONDOWN&&flag-event ==CV_EVENT_FLAG_CTRLKEY)  //Crtl+左键点击{imageCenter.x=rectOfRoi.x+x/scale;imageCenter.y=rectOfRoi.y+y/scale;showImageInRange();drawAllRectangle();}else if (event == EVENT_LBUTTONDOWN)     //左键点击{p1.x = x;p1.y = y;g_center=p1;select_flag = true;}else if (select_flag &&flag==CV_EVENT_FLAG_LBUTTON)   //鼠标拖拽{Mat temp;showImage.copyTo(temp);p2 = Point(x, y);rectangle(temp, p1, p2, Scalar(0, 255, 0), 2);imshow(WINNAME, temp);}else if (select_flag && event == EVENT_LBUTTONUP)     //松开鼠标{Rect roi = Rect(p1, Point(x, y));if (roi.width && roi.height)//点一下时会没有反应{roi.x/=scale;roi.y/=scale;roi.width/=scale;roi.height/=scale;roi.x+=rectOfRoi.x;roi.y+=rectOfRoi.y;selectRect.push_back(roi);drawAllRectangle();}select_flag = false;}}void displayPicture::on_Mouse_ComplexRect(int events, int x, int y, int flag, void* userdata)
{displayPicture* temp = reinterpret_cast<displayPicture*>(userdata);temp->on_Mouse_ComplexRect( events,x,y,flag);
}void displayPicture::drawAllRectangle()
{showImage=roiImage.clone();for(int i=0;i<selectRect.size();i++){Scalar color(125,255,0);Rect rect=selectRect[i];rect.x-=rectOfRoi.x;rect.y-=rectOfRoi.y;rect.x*=scale;rect.y*=scale;rect.width*=scale;rect.height*=scale;rectangle(showImage,rect,color,2);}string  temp="zoom with 'q' or 'e' ,set the Image center with ctrl+click ,out with space";  //将鼠标点击的二维坐标显示到屏幕上cv::putText(showImage,temp,Point(0, 16), FONT_HERSHEY_PLAIN, 1.f, Scalar(120, 255, 125), 1);
//  imshow(WINNAME, showImage);
}//选定感兴趣区域,获得与图像大小相同的mask
void displayPicture::getMask(Mat &mask)
{display();mask=Mat::zeros(srcImage.rows,srcImage.cols,CV_8U);Mat all255(srcImage.rows,srcImage.cols,CV_8U,Scalar(255));for(int i=0;i<selectRect.size();i++){Mat roi=mask(selectRect[i]);Mat roi2=all255(selectRect[i]);roi2.copyTo(roi);}//显示maskdisplayPicture displayMask(mask);displayMask.display();}
//选定不感兴趣区域,获得mask
void displayPicture::getMaskINV(Mat &mask)
{display();mask=Mat(srcImage.rows,srcImage.cols,CV_8U,Scalar(255));Mat allZeros=Mat::zeros(srcImage.rows,srcImage.cols,CV_8U);for(int i=0;i<selectRect.size();i++){Mat roi=mask(selectRect[i]);Mat roi2=allZeros(selectRect[i]);roi2.copyTo(roi);}//显示maskdisplayPicture displayMask(mask);displayMask.display();

项目资源

opencv实现鼠标画矩形框、显示十字线、缩放图片相关推荐

  1. Unity2D 实现UGUI滚动鼠标滑轮以鼠标位置点为中心缩放图片

    先放参考文章: Unity3d UGUI以鼠标位置点为中心缩放图片(含项目源码)https://blog.csdn.net/qq_33789001/article/details/117749837 ...

  2. opencv画框显示python_python+opencv选出视频中一帧再利用鼠标回调实现图像上画矩形框...

    最近因为要实现模板匹配,需要在视频中选中一个目标,然后框出(即作为模板),对其利用模板匹配的方法进行检测.于是需要首先选出视频中的一帧,但是在利用摄像头读视频的过程中我唯一能想到的方法就是: 1.在视 ...

  3. python+opencv选出视频中一帧再利用鼠标回调实现图像上画矩形框

    最近因为要实现模板匹配,需要在视频中选中一个目标,然后框出(即作为模板),对其利用模板匹配的方法进行检测.于是需要首先选出视频中的一帧,但是在利用摄像头读视频的过程中我唯一能想到的方法就是: 1.在视 ...

  4. OpenCV中鼠标交互-绘制矩形框

    OpenCV中鼠标交互-绘制矩形框 ·具体流程: 1.绑定回调函数 2.在回调函数中检测触发的事件 3.根据不同事件做出不同动作 一.绑定回调函数 cv2.setMouseCallback('orig ...

  5. Python OpenCV:利用滚动条移动图片,利用鼠标缩放图片

    Python OpenCV:利用滚动条移动图片,利用鼠标缩放图片 一.实现目标 二.实现背景 三.实现方法 四.运行环境 五.运行代码 六.运行结果 七.不足 八.参考 一.实现目标   在OpenC ...

  6. Python OpenCV:利用鼠标移动缩放图片

    一.实现目标   在OpenCV中通过鼠标左键拖拽移动图片,通过鼠标滚轮前后旋转放大缩小图片. 二.实现背景   在前一篇博客在OpenCV中使用滚动条显示大图中发现自己画滚动条移动大图略显繁琐,且缩 ...

  7. php鼠标经过显示文本,jQuery实现鼠标单击网页文字后在文本框显示的方法

    这篇文章主要介绍了jQuery实现鼠标单击网页文字后在文本框显示的方法,可实现鼠标点击上方文字即可在下方勾选处文本框显示对应文字的效果,涉及jQuery鼠标事件及链式操作的相关技巧,需要的朋友可以参考 ...

  8. 如何点击按钮弹出弹框显示几秒_layer消息框显示在鼠标旁边

    layer因为操作简单,界面美观,是开发消息弹窗的不二选择.一般我们都会让消息框采用浮动效果显示在屏幕正中间,但是如果我们的需求是弹框显示在鼠标点击位置的左下角,而且是随滚动条移动的,就像bootst ...

  9. QT编写实现图片的幻灯片播放、自适应显示、缩放(以鼠标位置为中心进行缩放)、拖动、重置、显示鼠标位置像素坐标及RGB值、播放GIF动画、截图保存、批量保存、拖入文件夹遍历所有文件

    这个图片查看器功能很多,是我花了不少心思,不断优化,不断添加功能的成果: 1.能打开并显示所有常用图片格式文件,显示鼠标位置像素坐标及RGB值 2.能缩放,拖动图片,可以以鼠标为中心滚动滚轮进行缩放 ...

最新文章

  1. oracle里的查询转换
  2. 计算密集型分布式内存存储和运算平台架构
  3. pythonmysql查询转list_python 数据库查询结果转对象
  4. 两个datatable合并 主键一样覆盖_MySQL 建表为啥还设置个自增 id ?用流水号当主键不正好么?...
  5. “神兽”出笼谁来管?多地试水暑期托管班
  6. QT学习之解决QT中QIcon图标不显示的问题
  7. golang xorm cmd xorm工具使用 reverse 反转一个数据库结构,生成代码
  8. MySQL完全自学手册
  9. 头歌平台(EduCoder)—— 数据挖掘算法原理与实践:数据预处理
  10. 多变量微积分(4)——多重积分之三重积分
  11. 安卓手机端口号怎么查看_安卓手机里的专业模式究竟该怎么拍?
  12. 纯CSS画基本图形(矩形、圆形、三角形、多边形、爱心)
  13. 2021年抖音0粉丝无货源直播带货最新技巧
  14. Leetcode 种花问题
  15. 网页webview适应手机分辨率
  16. js给label赋值功能
  17. 如果你要读一本真正普及“人工智能”的读物 | 赠书
  18. java formula one 用法_使用Formula One生成Excel报表-
  19. 国家电网 Sg186工程中GIS平台的选型
  20. 微信小程序云开发数据库update函数更新不了数据的问题(已解决)

热门文章

  1. R语言mgcv包中的gam函数拟合广义加性模型(Generalized Additive Model)GAM(对非线性变量进行样条处理、计算RMSE、R方、调整R方、可视化模型预测值与真实值的曲线)
  2. 3-2 Verilog 4位行波进位加法器
  3. 如何把.ipynb文件转化为.py文件
  4. Linux进程通信之System V消息队列
  5. spring与mybatis整合,数据库连接异常
  6. DDD 实战 (2):看看代码结构长啥样(值得收藏)
  7. java tea加密_TEA 加密解法,统一了C语言、Java与PHP的运算结果
  8. 计算机专业出国留学邮件怎么写,计算机专业留学个人陈述范文.pdf
  9. 图像拼接 之 特征点匹配
  10. sql实现当天最晚一次数据和最早一次的数据计算