Read an image from a qrc using imread() of OpenCV(使用 OpenCV 的 imread() 从 qrc 读取图像)
问题描述
我想以这种方式使用 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");
但最终的 
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 加载图像,并使用 QImage 并转换为 Matasmaloney.com/2013/11/code/converting-between-cvmat-and-qimage-or-qpixmap/" rel="noreferrer">this 代码,包括克隆和不克隆.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 读取图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使用 OpenCV 的 imread() 从 qrc 读取图像
				
        
 
            
        基础教程推荐
- 如何检查GTK+3.0中的小部件类型? 2022-11-30
 - C++结构和函数声明。为什么它不能编译? 2022-11-07
 - 如何在 C++ 中初始化静态常量成员? 2022-01-01
 - 如何通过C程序打开命令提示符Cmd 2022-12-09
 - 我有静态或动态 boost 库吗? 2021-01-01
 - 常量变量在标题中不起作用 2021-01-01
 - 静态库、静态链接动态库和动态链接动态库的 .lib 文件里面是什么? 2021-01-01
 - 这个宏可以转换成函数吗? 2022-01-01
 - 如何将 std::pair 的排序 std::list 转换为 std::map 2022-01-01
 - 在 C++ 中计算滚动/移动平均值 2021-01-01
 
    	
    	
    	
    	
    	
    	
    	
    	
						
						
						
						
						
				
				
				
				