c语言opencv读取图像,c – 使用OpenCV的imread()从qrc中读取图像

正如@TheDarkKnight指出的那样,imread并不知道Qt资源.但是,您可以编写自己的加载器,使用QFile从资源中检索二进制数据,并使用imdecode(由imread内部完成)来读取图像:

Mat loadFromQrc(QString qrc, int flag = IMREAD_COLOR)

{

//double tic = double(getTickCount());

QFile file(qrc);

Mat m;

if(file.open(QIODevice::ReadOnly))

{

qint64 sz = file.size();

std::vector buf(sz);

file.read((char*)buf.data(), sz);

m = imdecode(buf, flag);

}

//double toc = (double(getTickCount()) - tic) * 1000.0 / getTickFrequency();

//qDebug() << "OpenCV loading time: " << toc;

return m;

}

你可以这样称呼它:

Mat m = loadFromQrc("qrc_path");

或指定一个标志:

Mat m = loadFromQrc("qrc_path", IMREAD_GRAYSCALE);

性能

我尝试使用loadFromQrc加载图像,并使用this代码加载QImage并转换为Mat,无论是否克隆. loadFromQrc的结果比加载QImage并将其转换为Mat快10倍.

结果以ms为单位:

Load Mat : 4.85965

QImage to Mat (no clone): 49.3999

QImage to Mat (clone) : 49.8497

测试代码:

#include

#include

#include

#include

#include

using namespace cv;

Mat loadFromQrc(QString qrc, int flag = IMREAD_COLOR)

{

QFile file(qrc);

Mat m;

if(file.open(QIODevice::ReadOnly))

{

qint64 sz = file.size();

std::vector buf(sz);

file.read((char*)buf.data(), sz);

m = imdecode(buf, flag);

}

return m;

}

cv::Mat QImageToCvMat( const QImage &inImage, bool inCloneImageData = true )

{

switch ( inImage.format() )

{

// 8-bit, 4 channel

case QImage::Format_RGB32:

{

cv::Mat mat( inImage.height(), inImage.width(), CV_8UC4, const_cast(inImage.bits()), inImage.bytesPerLine() );

return (inCloneImageData ? mat.clone() : mat);

}

// 8-bit, 3 channel

case QImage::Format_RGB888:

{

if ( !inCloneImageData )

qWarning() << "ASM::QImageToCvMat() - Conversion requires cloning since we use a temporary QImage";

QImage swapped = inImage.rgbSwapped();

return cv::Mat( swapped.height(), swapped.width(), CV_8UC3, const_cast(swapped.bits()), swapped.bytesPerLine() ).clone();

}

// 8-bit, 1 channel

case QImage::Format_Indexed8:

{

cv::Mat mat( inImage.height(), inImage.width(), CV_8UC1, const_cast(inImage.bits()), inImage.bytesPerLine() );

return (inCloneImageData ? mat.clone() : mat);

}

default:

qWarning() << "ASM::QImageToCvMat() - QImage format not handled in switch:" << inImage.format();

break;

}

return cv::Mat();

}

int main(int argc, char *argv[])

{

QString url = "...";

{

double tic = double(getTickCount());

Mat m1 = loadFromQrc(url);

double toc = (double(getTickCount()) - tic) * 1000.0 / getTickFrequency();

qDebug() << "Load Mat: " << toc;

if(m1.data != NULL)

{

imshow("m1", m1);

waitKey(1);

}

}

// {

// double tic = double(getTickCount());

// QImage img;

// img.load(url);

// Mat m2 = QImageToCvMat(img, false);

// double toc = (double(getTickCount()) - tic) * 1000.0 / getTickFrequency();

// qDebug() << "QImage to Mat (no clone): " << toc;

// if(m2.data != NULL)

// {

// imshow("m2", m2);

// waitKey(1);

// }

// }

// {

// double tic = double(getTickCount());

// QImage img;

// img.load(url);

// Mat m3 = QImageToCvMat(img, true);

// double toc = (double(getTickCount()) - tic) * 1000.0 / getTickFrequency();

// qDebug() << "QImage to Mat (clone): " << toc;

// if(m3.data != NULL)

// {

// imshow("m3", m3);

// waitKey(1);

// }

// }

waitKey();

return 0;

}

### 如何在 QML 中集成与配置 OpenCV 要在 QML 中集成和配置 OpenCV,通常需要通过 C++ 后端实现 OpenCV 的功能,并将其暴露给 QML 层面进行调用。以下是具体方法: #### 1. 安装 OpenCV 库 确保已经在 Linux 或其他操作系统上成功安装了 OpenCV 库[^3]。如果尚未完成此步骤,则需按照官方文档或相关教程(如 Ubuntu 下的编译指南[^2])完成 OpenCV 的安装。 #### 2. Qt 项目设置 为了使 OpenCV 能够正常工作于 Qt 项目中,在 `.pro` 文件中添加必要的路径和链接库: ```plaintext INCLUDEPATH += /path/to/opencv/include LIBS += -L/path/to/opencv/lib \ -lopencv_core \ -lopencv_imgproc \ -lopencv_highgui \ -lopencv_videoio ``` 上述路径应替换为实际环境中 OpenCV 的头文件目录以及动态库所在位置[^1]。 #### 3. 创建自定义 QObject 类桥接 QML 和 OpenCV 由于 QML 不支持直接访问 OpenCV 功能,因此可以创建一个继承 `QObject` 的类作为桥梁。该类封装所需的功能并将它们注册到 QML 上下文中以便使用。 ##### 示例代码 (C++) ```cpp #include <QObject> #include <QString> #include <QImage> // 导入 opencv 头文件 #include <opencv2/core.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> class ImageProcessor : public QObject { Q_OBJECT public: explicit ImageProcessor(QObject *parent = nullptr) : QObject(parent) {} // 将 cv::Mat 转换为 QImage 并返回其数据 URL 表示形式 QString processAndConvert(const QString &filePath); signals: private slots: }; QString ImageProcessor::processAndConvert(const QString &filePath){ cv::Mat img = cv::imread(filePath.toStdString()); if(img.empty()){ return ""; } // Convert from BGR to RGB since QImage uses the latter format. cv::cvtColor(img, img, cv::COLOR_BGR2RGB); QImage qImg((uchar*)img.data, img.cols,img.rows, static_cast<int>(img.step), QImage::Format_RGB888); QByteArray byteArray; QBuffer buffer(&byteArray); buffer.open(QIODevice::WriteOnly); qImg.save(&buffer,"PNG"); // writes image into byte array in PNG format return QStringLiteral("data:image/png;base64,") + QString::fromLatin1(byteArray.toBase64().constData()); } ``` #### 4. 注册类型至 QML 为了让上面定义好的 `ImageProcessor` 可用于 QML ,还需要把它注册成上下文属性或者作为一个新的可实例化对象类型提供出来。 ##### 方法 A: 设置为 Context Property ```cpp int main(int argc, char **argv){ QApplication app(argc, argv); QQmlApplicationEngine engine; ImageProcessor processor; engine.rootContext()->setContextProperty(QStringLiteral("imageProcessor"),&processor); const QStringqmlFile=QStringLiteral("qrc:/main.qml"); engine.load(qmlFile); returnapp.exec(); } ``` ##### 方法 B: 使用 plugin 方式加载 另一种更灵活的方式是把此类打包成插件供多个工程共享复用,这里不再赘述细节。 #### 5. 在 QML 中调用处理函数 一旦完成了以上准备工作之后就可以轻松地从 QML 页面上调用这些接口啦! ##### 主界面 .qml 文件片段 ```javascript import QtQuick 2.15 import QtQuick.Controls 2.15 ApplicationWindow{ visible:true width:640;height:480 Button{ text:"Load and Process" onClicked:{ var result=imageProcessor.processAndConvert("/absolute/path/image.jpg") console.log(result) myImageView.source=result } } ImageView{id:myImageView;} } ``` 这样就实现了基于 QML 对图像资源应用 OpenCV 进行预览显示等功能扩展^。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值