问题描述
我想以这种方式使用 OpenCV 的 imread()
从 qrc 读取图像:
I want to read an image from a qrc using imread()
of OpenCV in this way:
Mat img = imread(":/TempIcons/logo.png");
但最终的 img 大小是 [0x0].我也试过:
but the final img
size is [0x0]. I have also tried:
Mat img = imread("qrc://TempIcons/logo.png");
但我得到的大小是一样的.我不想在 QImage
中加载图像,然后在 cv::Mat
中转换它.有没有办法以简单的方式做到这一点?如果是,我该怎么做?.
but the size I get is the same. I don't want to load the image in a QImage
to then transform it in a cv::Mat
. Is there a way to do this in a easy way?. If it is, how can I do it?.
谢谢
推荐答案
正如@TheDarkKnight 所指出的,imread
不知道 Qt 资源.但是,您可以编写自己的 loader,它使用 QFile
从资源中检索二进制数据,并使用 imdecode
(由 imdecode
在内部完成)code>imread) 读取图像:
As @TheDarkKnight pointed out, imread
is not aware of Qt resources. You can however write your own loader, that uses QFile
to retrieve the binary data from the resource, and uses imdecode
(as done internally by imread
) to read the image:
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<uchar> 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
加载图像,并使用 代码,包括克隆和不克隆.loadFromQrc
结果比加载 QImage
并将其转换为 Mat
快 10 倍.
I tried loading the image with loadFromQrc
, and loading the QImage
and converting to Mat
using this code, both with and without cloning. loadFromQrc
results to be 10 time faster then loading a QImage
and convert it to Mat
.
结果以毫秒为单位:
Load Mat : 4.85965
QImage to Mat (no clone): 49.3999
QImage to Mat (clone) : 49.8497
测试代码:
#include <vector>
#include <iostream>
#include <QDebug>
#include <QtWidgets>
#include <opencv2/opencv.hpp>
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<uchar> 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<uchar*>(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<uchar*>(swapped.bits()), swapped.bytesPerLine() ).clone();
}
// 8-bit, 1 channel
case QImage::Format_Indexed8:
{
cv::Mat mat( inImage.height(), inImage.width(), CV_8UC1, const_cast<uchar*>(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;
}
这篇关于使用 OpenCV 的 imread() 从 qrc 读取图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!