VS+Qt+鼠标框选后掩膜去除背景

前言:

实际采集的图片背景比较复杂,所以我想着采用框选矩形框+掩膜的方式简单粗暴的消除背景对图片有用区域的干扰。网上搜索了一圈尝试了几种不同的方式去框选,最后发现还是Qt的鼠标事件比较容易上手。

效果图:

在这里插入图片描述

主要思路:

1.主类作用:读入图片、确认ROI、掩膜、显示图片
2.标签类作用:鼠标事件、发送矩形框的信息给主类

相关代码:

(1)标签类:
<myLabel.h>

#pragma once
#include <QLabel>
#include <QPoint>
#include <QColor>
#include <QPaintEvent>
#include <QImage>
#include <QPixmap>
#include <opencv2/opencv.hpp>
//Q_DECLARE_METATYPE(cv::Point);class myLabel : public QLabel
{Q_OBJECT
public:myLabel(QWidget *parent);void paintEvent(QPaintEvent* event);void mousePressEvent(QMouseEvent* event);void mouseReleaseEvent(QMouseEvent* event);void mouseMoveEvent(QMouseEvent* event);QPoint toRealPoint(QPoint p);void showLocalImg(cv::Mat src);
public:QPoint p_start;QPoint p_end;QPoint p_startInImg;QPoint p_endInImg;bool is_pressed;bool is_ROI;//ROI按钮是否点击判断double xScaled;//x方向图片缩放系数double yScaled;//y方向图片缩放系数QImage Img;QPixmap PixImg;
signals:void send2Points(cv::Point p_s, cv::Point p_e);
};

<mylabel.cpp>

#include"myLabel.h"
#include <QPen>
#include<QPainter>
#include<iostream>
using namespace std;myLabel::myLabel(QWidget *parent):QLabel(parent)
{p_start =QPoint(-1, -1);p_end = QPoint(-1, -1);is_pressed = false;is_ROI = true;xScaled = 1;yScaled = 1;
}
void myLabel::paintEvent(QPaintEvent *event)
{QLabel::paintEvent(event);//继承父窗口绘图事件, 显式的调用父类的paintEvent方法if (is_ROI){QPainter painter(this);painter.setPen(QPen(Qt::red, 2));int width = p_end.x() - p_start.x();int height = p_end.y() - p_start.y();painter.drawRect(QRect(p_start.x(), p_start.y(), width, height));}
}
void myLabel::mousePressEvent(QMouseEvent *event)
{if (is_ROI){QCursor cursor;cursor.setShape(Qt::ArrowCursor);is_pressed = true;p_start = event->pos();cout << "鼠标按下" << p_start.x() << " " << p_start.y() << endl;p_startInImg = toRealPoint(p_start);}
}
void myLabel::mouseReleaseEvent(QMouseEvent *event)
{if (is_ROI){p_end = event->pos(); //鼠标相对于所在控件的位置is_pressed = false;update();cout << "鼠标松开" << p_end.x() <<" "<<p_end.y()<< endl;p_endInImg = toRealPoint(p_end);emit send2Points(cv::Point(p_startInImg.x(), p_startInImg.y()), cv::Point(p_endInImg.x(), p_endInImg.y()));}
}void myLabel::mouseMoveEvent(QMouseEvent *event)
{if (is_ROI){if (event->buttons() & Qt::LeftButton) {p_end = event->pos(); //鼠标相对于所在控件的位置update();}}
}QPoint myLabel::toRealPoint(QPoint p)
{//图片左上角坐标系的坐标相对于qlabel的偏移量int xoffset;xoffset = (this->width() - PixImg.width())/2;int yoffset;yoffset = (this->height() - PixImg.height())/2;//考虑缩放比例QPoint pic_pos; pic_pos.setX((p.x()-xoffset)*xScaled);pic_pos.setY((p.y()-yoffset)*yScaled);return pic_pos;
}void myLabel::showLocalImg(cv::Mat src)
{cv::Mat Rgb;if (src.channels() == 3)//RGB Img{cv::cvtColor(src, Rgb, CV_BGR2RGB);//颜色空间转换Img = QImage((const uchar*)(Rgb.data), Rgb.cols, Rgb.rows, Rgb.cols * Rgb.channels(), QImage::Format_RGB888);}else//Gray Img{Img = QImage((const uchar*)(src.data), src.cols, src.rows, src.cols*src.channels(), QImage::Format_Indexed8);}PixImg = QPixmap::fromImage(Img);this->setScaledContents(false);//取消图片自适应qlabel大小,这种自适应不是同比例放大缩小PixImg = PixImg.scaled(this->width(), this->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);//确保qlabel显示等比例缩放最大宽度的图片//PixImg = PixImg.scaledToHeight( this->height(), Qt::SmoothTransformation);//确保qlabel显示等比例缩放最大宽度的图片this->setPixmap(PixImg);cout << this->width() << " " << this->height() << endl;xScaled =double(src.cols)/PixImg.width();yScaled =double(src.rows)/PixImg.height();
}

(2)主类

ROImain::ROImain(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);img_current_location = 0;//默认位置为第一张图connect(ui.label_Img1, &myLabel::send2Points, this, &ROImain::get2Points);
}
//确认ROI区域
void ROImain::on_pushButton_RoiConfirm_clicked()
{ui.label_Img1->is_ROI = false;//生成掩膜Mat mask = Mat::zeros(imgInputVec[img_current_location].size(), CV_8UC1);for (int i = p_start.x; i < p_end.x; ++i){for (int j = p_start.y; j < p_end.y; ++j){mask.at<uchar>(j, i) = 255;}}Mat dst;imgInputVec[img_current_location].copyTo(dst, mask);//存储掩膜后图片int a = imgMaskVec.size() - img_current_location;//判断掩膜存储位置是否与当前位置一致if (a!=0 && imgMaskVec.size()>0){for (int k = 0; k < a;++k)imgMaskVec.pop_back();}imgMaskVec.push_back(dst);ui.label_Img2->showLocalImg(imgMaskVec[img_current_location]);
}
//接收ROI的两个坐标点(矩形左上角、右下角)
void ROImain::get2Points(Point p1, Point p2)
{p_start = p1;p_end = p2;
}

代码详解

1、把qlabel控件提升为自己写的类(myLabel),这么做的目的是在QLabel的基础上可以自定义想要的功能与属性,相当于一个拓展,具体做法:
①在Qlabel右键,点击提升为

②输入自己定义的类名进行提升即可

2.鼠标框选的坐标和实际图片坐标转换问题。
1)我想要显示同比例缩放的图片,所以显示图片时候要取消图片自适应QLabel大小,这种自适应不是同比例放大缩小

this->setScaledContents(false);

2)pixmap显示图片有好几种方式,我采用scaled(),其中参数设置为同比例缩放(KeepAaspectRatio)
在这里插入图片描述
在这里插入图片描述
3)鼠标相对于控件的坐标系和图片左上角的坐标系关系

把图片在Qlabel上下左右居中显示,这样的话可以通过求得的x和y方向偏移量把坐标系从O1转换到O2

QPoint myLabel::toRealPoint(QPoint p)
{//图片左上角坐标系的坐标相对于qlabel的偏移量int xoffset;xoffset = (this->width() - PixImg.width())/2;int yoffset;yoffset = (this->height() - PixImg.height())/2;//考虑缩放比例QPoint pic_pos; pic_pos.setX((p.x()-xoffset)*xScaled);pic_pos.setY((p.y()-yoffset)*yScaled);return pic_pos;
}

缩放系数xScaled和yScaled在输入图片时候就可以计算得到

	xScaled =double(src.cols)/PixImg.width();yScaled =double(src.rows)/PixImg.height();

3.鼠标框选到输出真实图片坐标的流程
①鼠标左键按下mousePressEvent→得到相对于控件的坐标p_start
②坐标转换toRealPoint(p_start)
③鼠标左键松开mouseReleaseEvent→得到相对于控件的坐标p_end
④坐标转换toRealPoint(p_end)
⑤发送转换后的坐标给主类对象中
主类对象和标签类对象的信号与槽连接:

	connect(ui.label_Img1, &myLabel::send2Points, this, &circleCalib::get2Points);

4.掩膜
主要是A.copyTo(B,Mask)函数的理解:我个人是理解成A和Mask的相同位置像素进行与运算赋值给B,即一旦Mask有像素值为0,那么在B中同样位置的像素就赋值为0(被掩盖住了)。

注:如有错误,务必留言指正,共同学习进步!(如有帮助,不妨点赞评论。)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/52043.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT—3D绘图

OpenGL是一个跨平台的、用来渲染3D图形的标准API,Qt对OpenGL提供了强大的支持。Qt4时代的QtOpenGL模块在Qt5中已经不再建议使用,OpenGL相关的类被移到了Qt GUI模块。Qt Widgets模块中的QOpenGLWidget类提供了一个可以渲染OpenGL图形的部件&#xff0c;通过该部件可以轻松地将Op…

【Qt】Qt环境配置与入门案例

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍Qt环境配置与入门。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新不迷路&…

(三)NI采集卡应用学习:在Qt中实现多路数据的同时采集、显示、绘图及存储

1、使用NI MAX创建多路输入的测量任务 本处设置Dev1/ai0:3四路电压输入&#xff0c;采样率均为100&#xff0c;差分连接。 2、代码 // 设置地址 void Widget::on_add_pushButton_clicked() {address_txt QFileDialog::getExistingDirectory(this, tr("Open Directory&q…

linux程序框架设计,《Linux与Qt程序设计》知识框架

本文主要是通过一本书来大致了解Qt开发的框架,不对具体内容做详细分析。 1.首先弄清楚概念:定义->以自己的话理解是什么-> 实现的是什么功能->用在哪些地方 2.前面认识到的知识点的特点-> 代码实现-> 工程代码分析 第一部分 Linux基础知识 第二部分 Qt程序基础…

QT开发应用程序(11)--图形绘制和文本输出

代码演示&#xff1a; #include <QPainter> MyDraw::MyDraw(QWidget *parent) :QWidget(parent) {QLinearGradient linearGradient(0,0,400,400);linearGradient.setColorAt(0.0,Qt::white);linearGradient.setColorAt(0.2,QColor(0,0,0));linearGradient.setColorAt(1.…

chatgpt赋能python:使用Python捕获错误:为您的代码添加可靠性

使用Python捕获错误&#xff1a;为您的代码添加可靠性 在编写Python代码时&#xff0c;错误很常见。您可能会因输入无效参数而收到TypeError&#xff0c;或者因无法连接到数据库而收到ConnectionError。当这些错误发生时&#xff0c;您的代码可能会崩溃或产生不正确的结果。尽…

chatgpt赋能python:关闭Python:如何优雅地退出一个Python程序

关闭Python&#xff1a;如何优雅地退出一个Python程序 Python作为一门开发语言&#xff0c;可以广泛应用于众多领域&#xff0c;如数据科学、人工智能、Web应用开发等等。但有时候&#xff0c;我们需要关闭一个正在运行的Python程序。本文将介绍如何优雅地退出一个Python程序&…

chatgpt赋能python:Python异常捕获存在的问题

Python 异常捕获存在的问题 作为一门广受欢迎、应用广泛的编程语言&#xff0c;Python 在处理异常方面有着比较完善的设计。Python 提供了 try…except…finally 这样的异常处理机制&#xff0c;通过这些机制&#xff0c;开发者可以捕获、处理程序中产生的异常&#xff0c;从而…

yagmail——快速发送邮件

yagmail——快速发送邮件 目标&#xff1a;如何利用python中的yagmail包&#xff0c;快速发送邮件。 python写的一个简单demo脚本代码如下&#xff1a; import yagmail import pandas as pd from loguru import logger# 保存excel文件 contents pd.DataFrame() contents[&quo…

电脑和微信怎么发邮件到别人邮箱,企业邮箱如何发email给别人

邮箱已成为主流的办公软件&#xff0c;除了日常的电脑办公使用以外&#xff0c;你知道还有哪些便捷的方式使用邮箱吗&#xff1f;现在是互联网时代&#xff0c;许多邮箱都研发了手机邮箱配合使用&#xff0c;那TOM企业邮箱有哪些便捷的服务呢&#xff1f;一起看看吧&#xff01…

怎么发送电子邮件到别人邮箱?手把手教你!

在日常生活中&#xff0c;我们在工作学习的时候都离不开电子邮件&#xff0c;无论两人的距离有多远&#xff0c;都是可以通过电子邮件的方式完成信息的即时传递。这样不仅可以传输文字信息&#xff0c;还能传输图片、视频等多种格式的信息。那么&#xff0c;怎么发送电子邮件到…

chatgpt赋能Python-pythonapp自动化

Python App自动化&#xff1a;优化SEO的终极解决方案 随着互联网的发展&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;变得日益重要。对于任何网站或应用程序开发人员来说&#xff0c;SEO应该是一个非常重要的考虑因素。为了帮助开发人员和企业提高其在线可见性&#x…

chatgpt赋能python:Python自动化断言介绍

Python 自动化断言介绍 软件业的各种应用程序不可避免地需要与用户进行交互。测试团队应该确保这些应用程序快速&#xff0c;可靠地响应用户交互&#xff0c;并注重高质量测试的策略和工具。Python自动化断言是一种测试策略&#xff0c;可帮助团队实现高品质和高效率的测试。P…

chatgpt赋能python:Python自动化操作桌面的方法和应用

Python自动化操作桌面的方法和应用 Python是一种高级编程语言&#xff0c;越来越多的研究人员和程序员将其应用在自动化操作任务上。本文将向您介绍如何利用Python自动化操作桌面并且展示一些实际应用。 桌面自动化操作是什么&#xff1f; 桌面自动化操作是使用编程语言编写…

chatgpt赋能python:Python表格自动化:优化你的数据处理工作效率

Python表格自动化&#xff1a;优化你的数据处理工作效率 作为一名有10年Python编程经验的工程师&#xff0c;我深切体会到编程能够为我们带来的高效和便利。其中&#xff0c;Python在数据分析和处理方面的优势尤为突出。本文将从Python表格自动化的角度&#xff0c;为大家介绍…

chatgpt赋能python:Python如何自动化办公

Python如何自动化办公 随着信息技术的不断发展和进步&#xff0c;自动化技术已经在各行各业得到了广泛的应用。作为一种高级编程语言&#xff0c;Python在自动化办公领域发挥了重要的作用。下面&#xff0c;我们来详细了解一下Python如何自动化办公。 什么是Python自动化办公…

chatgpt赋能Python-python_gui自动化点击

简介 Python是一种功能强大的编程语言&#xff0c;它的广泛应用让许多企业都使用了这种语言来编写脚本&#xff0c;编写小型应用程序和构建自动化工作流程。其中&#xff0c;Python GUI自动化成为了越来越普遍的需求。Python可以使用多种GUI库&#xff0c;例如PyQt、Tkinter和…

chatgpt赋能python:如何用Python自动化办公提升工作效率

如何用Python自动化办公提升工作效率 随着科技的不断发展和普及&#xff0c;人们越来越重视如何利用技术手段提高生产效率。对于很多办公人员来说&#xff0c;每天大量的重复性工作可能会让人感到枯燥乏味。而Python作为一种易学易用的编程语言&#xff0c;可以帮助办公人员自…

chatgpt赋能Python-python_gui_自动化

Python GUI自动化——让你的工作更高效 Python是一种多用途、高级语言&#xff0c;使用广泛。它是一种开发强大且易于维护的程序的语言。自从出现以来&#xff0c;Python已经在许多领域得到了广泛的应用&#xff0c;包括 Web 开发、数据分析、人工智能和自动化测试等。而其中&…

chatgpt赋能python:自动化办公:Python的应用

自动化办公&#xff1a;Python的应用 随着信息量的爆炸式增长&#xff0c;人们面临越来越多的数据处理任务。办公桌上堆积如山的资料&#xff0c;以及工作日程的繁忙&#xff0c;使得人们越来越需要自动化的解决方案。Python自从诞生以来&#xff0c;就在自动化开发领域占据了…