写在前面
以前写过一个OPenCV图像处理的工具,界面是这样的:
有兴趣的朋友用用:https://pan.baidu.com/s/16_DYfTnvp8cj7aqzXAlMGQ 提取码:5s9e
这个是用QWidget写的,打算用QML重写一遍,界面用QML,内部逻辑用C++。
不定时更新。
正文
首先要有一个显示图片的控件。根据 用 C++ 编写 QML 扩展 可知,这可以是一个继承QQuickPaintedItem 的自定义类,在自定义类中实现绘制图片然后将它注册到QML中。这个类尽量只显示图片和做一些交互操作,既然如此,那么需要再定义一个工具类,OpenCV图片处理的操作都在工具类中进行。
显示图片的控件如下:
#ifndef SHOWMATITEM_H
#define SHOWMATITEM_H
#include <QQuickPaintedItem>
#include <QPixmap>
#include <opencv2/core/core.hpp>
class ShowMatItem : public QQuickPaintedItem
{
Q_OBJECT
QML_ELEMENT
public:
ShowMatItem(QQuickItem *parent = 0);
void paint(QPainter *painter)override;
Q_INVOKABLE void setSrcFile(const QString & filePath);
private:
cv::Mat mat;
QString srcFilePath;
};
#endif // SHOWMATITEM_H
#include "showmatitem.h"
#include <QPainter>
#include <QPixmap>
#include <QDebug>
#include "util.h"
ShowMatItem::ShowMatItem(QQuickItem *parent)
:QQuickPaintedItem(parent)
{
}
void ShowMatItem::paint(QPainter *painter)
{
painter->setRenderHints(QPainter::Antialiasing, true);
auto rect = boundingRect().toRect();
painter->drawPixmap(rect,util::matToPixmap(rect.size(),mat));
}
void ShowMatItem::setSrcFile(const QString & filePath)
{
QString temp = filePath;
srcFilePath = temp.remove("file:///").replace("/","\\");
util::readImage(temp,mat);
update();
}
工具类如下:
#ifndef UTIL_H
#define UTIL_H
#include <QPixmap>
#include <opencv2/core/core.hpp>
class util
{
public:
static QPixmap matToPixmap(const QSize & size,const cv::Mat & mat);//Mat转QPixmap
static void readImage(const QString & filePath,cv::Mat & mat);//打开一张图片
private:
util();
};
#endif // UTIL_H
#include "util.h"
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <QTextCodec>
util::util()
{
}
QPixmap util::matToPixmap(const QSize & size, const cv::Mat & mat)
{
if(mat.empty())
return QPixmap();
auto img = QImage((const unsigned char*)(mat.data),
mat.cols,
mat.rows,
mat.cols * mat.channels(),
QImage::Format_RGB888);
return QPixmap::fromImage(img.scaled(size));
}
void util::readImage(const QString & filePath,cv::Mat & mat)
{
mat = cv::imread(QTextCodec::codecForName("gb18030")->fromUnicode(filePath).data());
cv::cvtColor(mat,mat,cv::COLOR_BGR2RGB);
}
定义完成,然后是注册,注册以后定义的控件就能在QML中使用了:
qmlRegisterType<ShowMatItem>("com.qmlcompany.cppComponents", 1, 0, "ShowMatItem");
main.qml 代码:
import QtQuick 2.14
import QtQuick.Controls
import com.qmlcompany.cppComponents 1.0
import Qt.labs.platform 1.1 as Labs //名称冲突了要用as,注意Labs要大写开头
ApplicationWindow
{
visible: true
title: qsTr("OpenCV图像处理助手")
color:"#FFFFFF"
width: 1000; height: 600
menuBar: MenuBar
{
Menu
{
title: qsTr("文件")
MenuItem
{
text: qsTr("打开文件")
onTriggered:
{
fileDialog.open()
}
Labs.FileDialog
{
id: fileDialog
title: qsTr("打开图片或者txt文件")
nameFilters: ["image files (*.png *.jpg *.jpeg *.bmp)"]
acceptLabel: qsTr("确定")
rejectLabel: qsTr("取消")
fileMode: Labs.FileDialog.OpenFile
onAccepted:
{
var filePath = fileDialog.files[0]
srcImage.setSrcFile(filePath)
}
}
}
MenuSeparator {}
MenuItem
{
text: qsTr("退出")
onTriggered: Qt.quit()
}
}
}
ShowMatItem
{
id:srcImage
anchors.fill: parent
}
}
目前代码就这些,比较简单。