一个显示 OpenCV Mat 图像的自定义 Qt 控件
今天学习 Qt 的时候顺手写了一个,包含一个头文件 qcvdisplay.h 和一个源文件 qcvdisplay.cpp,因为这是 qt 默认的文件命名方式,在 Qt Designer 中提升控件时会省去输入文件名的步骤,所以最好不要改名。
qcvdisplay.h :
#ifndef QCVDISPLAY_H
#define QCVDISPLAY_H #include <QWidget>
#include <QException>
#include <opencv2/core/core.hpp> // 当图片不是灰度图或者 BGR 图像时抛出此异常
class UnsupportedFormatError : public QException
{
public:
void raise() const { throw *this; }
UnsupportedFormatError *clone() const { return new UnsupportedFormatError(*this); }
}; // 显示 opencv 图片的自定义控件
class QCVDisplay : public QWidget
{
Q_OBJECT
public:
explicit QCVDisplay(QWidget *parent = );
cv::Mat getBuffer(); public slots:
void displayImage(const cv::Mat& img); protected:
void matToQImage(const cv::Mat3b &src, QImage &dest);
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event);
QImage data;
cv::Mat buffer;
}; #endif // QCVDISPLAY_H
qcvdisplay.cpp
#include "qcvdisplay.h" #include <QResizeEvent>
#include <QPaintEvent>
#include <QPainter> #include <opencv2/imgproc/imgproc.hpp> QCVDisplay::QCVDisplay(QWidget *parent) :
QWidget(parent)
{
} cv::Mat QCVDisplay::getBuffer()
{
return buffer;
} // 将 Mat 转换为 QImage,由于 QImage 的每一行有多余对齐字节
// 故采用 RBG32 来消除多余字节
void QCVDisplay::matToQImage(const cv::Mat3b &src, QImage& dest)
{
for (int y = ; y < src.rows; ++y) {
const cv::Vec3b *srcrow = src[y];
QRgb *destrow = (QRgb*)dest.scanLine(y);
for (int x = ; x < src.cols; ++x) {
destrow[x] = qRgba(srcrow[x][], srcrow[x][], srcrow[x][], );
}
}
} // 在控件上显示图片,使用 opencv 自带的 resize 使其缩放到和控件大小一致
void QCVDisplay::displayImage(const cv::Mat &img)
{
QSize sz = data.size();
if (img.channels() == ) {
buffer = img.clone();
} else if (img.channels() == ) {
cv::cvtColor(img, buffer, CV_GRAY2RGB);
} else {
throw UnsupportedFormatError();
}
cv::Mat resized;
if (!sz.isEmpty()) {
cv::resize(buffer, resized, cv::Size(sz.width(), sz.height()));
matToQImage(resized, data);
update();
}
} // 绘图事件处理函数
void QCVDisplay::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawImage(event->rect(), data, event->rect());
} // 缩放事件也采用 opencv 自带的 resize
void QCVDisplay::resizeEvent(QResizeEvent *event)
{
if (data.size() != event->size()) {
cv::Mat resized;
data = QImage(event->size(), QImage::Format_RGB32);
if (!buffer.empty() && !event->size().isEmpty()) {
cv::resize(buffer, resized, cv::Size(event->size().width(),
event->size().height()));
matToQImage(resized, data);
}
}
QWidget::resizeEvent(event);
}
实现的思路很直接,重写 paintEvent 和 resizeEvent 两个事件处理函数来进行控件的自定义显示,用一个 Mat 作为原始图片的缓存(buffer),将其调整到与空间大小一致后再显示。QImage 的格式选择 RGB32 (第一个字节为 0xFF),使得图像每一行的像素个数全部都是 4 的倍数,消除多余的对齐像素,避免图片在显示时变形。(OpenCV 2.0 以后的图片已经不存在对齐像素了,即图像数据在内存中是连续的)
使用时将两个文件加入当前项目,在 Qt Designer 中拖入一个 widget 基类,在 widget 上点右键,选择 “提升为...”,在弹出的对话框中按照下图输入。
输入完提升的类名称,点击添加,提升即可。
一个显示 OpenCV Mat 图像的自定义 Qt 控件的更多相关文章
- 【Android开发日记】之入门篇(十四)——Button控件+自定义Button控件
好久不见,又是一个新的学期开始了,为什么我感觉好惆怅啊!这一周也发生了不少事情,节假日放了三天的假(好久没有这么悠闲过了),实习公司那边被组长半强制性的要求去解决一个后台登陆的问题,结果就是把 ...
- 自定义SWT控件一之自定义单选下拉框
一.自定义下拉控件 自定义的下拉框,是自定义样式的,其中的下拉框使用的是独立的window,非复选框的下拉框双击单机其它区域或选择完之后,独立window构成的下拉框会自动消失. package co ...
- Android自定义控件之自定义组合控件
前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...
- C# DataGridView自定义分页控件
好些日子不仔细写C#代码了,现在主要是Java项目,C#.Net相关项目不多了,有点手生了,以下代码不足之处望各位提出建议和批评. 近日闲来无事想研究一下自定义控件,虽然之前也看过,那也仅限于皮毛,粗 ...
- C# 自定义FileUpload控件
摘要:ASP.NET自带的FileUpload控件会随着浏览器的不同,显示的样式也会发生改变,很不美观,为了提高用户体验度,所以我们会去自定义FileUpload控件 实现思路:用两个Button和T ...
- (九)ASP.NET自定义用户控件(2)
http://www.cnblogs.com/SkySoot/archive/2012/09/04/2670678.html 用户控件 在 .NET 里,可以通过两种方式把自己的控件插入到 Web 窗 ...
- (八)ASP.NET自定义用户控件(1)
http://blog.csdn.net/laodao1/article/details/5897366 ASP.NET自定义控件组件开发 第一章:从一个简单的控件谈起 起始开发ASP.NET自定义控 ...
- 【转】带checkbox的ListView实现(二)——自定义Checkable控件的实现方法
原文网址:http://blog.csdn.net/harvic880925/article/details/40475367 前言:前一篇文章给大家展示了传统的Listview的写法,但有的时候我们 ...
- Qt控件精讲一:按钮
原地址:http://blog.csdn.net/yuxikuo_1/article/details/17397109 Qt Creater提供6种Button控件.如图1. Button控件介绍 控 ...
随机推荐
- MQ常问的问题
目录 1:什么场景使用了mq?直接掉接口不行吗? 2:用消息队列都有什么优点和缺点? 3:Kafka.ActiveMQ.RabbitMQ.RocketMQ 都有什么区别? 4:那你们是如何保证消息队列 ...
- Linux环境快速搭建elasticsearch6.5.4集群和Head插件
https://blog.csdn.net/boling_cavalry/article/details/86358716
- EBS 显示主页面的工作列表和主菜单
EBS环境: R12.1.3 问题描述:如果系统的“个性化页”做了设置,可能出现登录系统后,如果下图红框中的 主菜单和工作列表没有显示的情况,如果需要重新显示“主菜单”和“工作列表”,可参考以下操作 ...
- [MVC HtmlHelper简单了解]
HtmlHelper用来在视图中显示Html控件,简化代码,使用方便!,降低了View视图中的代码复杂度!可以更快速的完成工作! 以下是一些常用 的html标签 辅助方法 使用HTML辅助方法输出 ...
- DateTimePicker 日期时间选择器
在同一个选择器里选择日期和时间 DateTimePicker 由 DatePicker 和 TimePicker 派生,Picker Options 或者其他选项可以参照 DatePicker 和 T ...
- OpenStack 启动虚拟机 Booting from Hard Disk
问题 OpenStack 启动虚拟机 Booting from Hard Disk-GRUB 环境 OpenStack RUNNING IN vSphere 6.0.0 VM 开启了 CPU 虚拟化支 ...
- Linux 串口调试工具汇总
minicomminicom 是一款启动速度快,功能强大的串口终端调试工具,当然缺点就是纯字符界面,没有图形界面的调试工具看起来直观方便,但是它功能十分强大,并且在一些没有屏幕的嵌入式主板上运行颇有用 ...
- FileChannel原理
官方对Channel的解释 (一个用于输入/输出操作的连接.通道表示对实体的开放连接,如硬件设备.文件.网络套接字或能够执行一个或多个不同的输入/输出操作的程序组件,例如读取或写入.) Thankin ...
- beego框架学习(二) -路由设置
路由设置 什么是路由设置呢?前面介绍的 MVC 结构执行时,介绍过 beego 存在三种方式的路由:固定路由.正则路由.自动路由,接下来详细的讲解如何使用这三种路由. 基础路由 从beego1.2版本 ...
- 【HANA系列】SAP HANA跟我学HANA系列之创建分析视图一
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA跟我学HANA系 ...