一个显示 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控件介绍 控 ...
随机推荐
- Adding property to a json object in C#
Adding property to a json object in C# you can do it with a dynamic object dynamic obj = JsonConve ...
- linux sig Segmentation fault error
当你发现自己的程序挂了,发现这样的一个报错, 不要慌张,它还是带有一点有用信息的.ps: 如果程序挂了,没有捕抓到这个提示,看一下/var/log/messages对应时间段有没有如下消息.memca ...
- 全面解读php-面向对象
一.类的自动载入 //类的自动载入我们使用 spl_autoload_register($autoload_function ).我们需要在不同的地方包含更多不同的类文件,只需要多写几个 $autol ...
- 分期花呗 账户交易通知:尾号6932客户,您的申请已通过,账户余额38139元,无手续费,点t.cn/Aijsx9vq取款,回T退订。
10692285499 分期花呗 账户变动通知:尾号6932客户,您的申请已通过,账户余额5000元,请及时点击t.cn/AiOMsNAm取款,回T退订. 106935276259002分期花呗 账户 ...
- python爬虫常用的库
1,请求:requests requests.get(url, headers) requests.post(url, data=data, files=files) urllib模块: Py ...
- Day06:方法 / 猜字母游戏
JAVA方法 方法就是处理一个业务所需要编写的代码的代码段 方法特性 一个方法处理一个业务 方法代码编写,不和其他方法冲突 方法定义后可以随意调用 将main方法中的所有代码分散到各个普通方法中 减少 ...
- SpringCloud常用注解有哪些?
@Mapper: 注解写在你的Mapper映射接口上面 @SpringBootApplication: 写在主程序上面 @Configuration: 写在配置类上面 @Bean: 写在配置类中的返回 ...
- Lombok的用法
Lombok是一款Java开发插件,使得Java开发者可以通过其定义的一些注解来消除业务工程中冗长和繁琐的代码,尤其对于简单的Java模型对象(POJO).在开发环境中使用Lombok插件后,Java ...
- 线性模型-线性回归、Logistic分类
线性模型是机器学习中最简单的,最基础的模型结果,常常被应用于分类.回归等学习任务中. 回归和分类区别: 回归:预测值是一个连续的实数: 分类:预测值是离散的类别数据. 1. 线性模型做回归任务 ...
- Linux解决Python调用Matlab函数无法导入matlab.engine问题及其他注意事项
问题描述 Linux系统,根据matlab官方文档说明,利用Matlab中的API来实现Python调用Matlab函数.具体方法见文档: https://ww2.mathworks.cn/help/ ...