【问题标题】:opencv Qt how to efficiently create and pass color image to QImage?opencv Qt如何有效地创建彩色图像并将其传递给QImage?
【发布时间】:2016-02-06 00:02:45
【问题描述】:

how to convert an opencv cv::Mat to qimage 部分回答了这个问题

我使用 Qt 5.5、opencv 2.4、mac yosemite 10.10.5。

我正在寻找一种使用 QImage 显示彩色图像的有效方法,其颜色信息来自 3 个不同的 cv::Mat 对象,其中包含彩色图像的 3 个 RGB 通道。对于我自己的“教育”,我需要了解最初如何使用分离的渠道。 我不清楚从这 3 个分离的通道中获得 QImage 的最有效方法是什么。

cv::Mat 对象的声明和赋值如下:

imRed = new Mat(Size(naxis1, naxis2), CV_64F);
imGreen = new Mat(Size(naxis1, naxis2), CV_64F);
imBlue = new Mat(Size(naxis1, naxis2), CV_64F);


double* redP = imRed->ptr<double>(0);
double* greenP = imGreen->ptr<double>(0);
double* blueP = imBlue->ptr<double>(0);

for (long i = 0; i < nPixels; i++)
{

    redP[i] = (double) rawProcess.imgdata.image[i][0];;
    greenP[i] = (double) rawProcess.imgdata.image[i][1];
    blueP[i] = (double) rawProcess.imgdata.image[i][2];

}

其中rawProcess 是来自Libraw library 的对象,其中包含图像数据。 redPgreenPblueP,顾名思义,是指向红色、绿色和蓝色通道的指针,这段代码假设(如果我错了,请纠正我)cv::Mat 的地址像素值在内存中是连续的。

从这里开始,我应该如何有效地color图像的缓冲区传递给QImage,即最小化中间副本、循环等...(如果需要,我的系统可以使用openMP,我有4个线程可用)?

谢谢

【问题讨论】:

  • 虽然我需要分别在三个通道上做一些事情,但在下一步中,我可能会使用单个垫子对象并以更有效的方式做事(例如使用 CV_64FC3) .但就目前而言,对于图像通道如何在 opencv qt 交互中工作的“学术”理解,如果可能的话,了解从这三个独立通道获取内容的解决方案非常重要。
  • 有两个问题:1.如何将单独的通道合并为单个 cv::Mat 对象(例如使用 cv::merge) 2.如何有效地将 cv::Mat 对象转换为 QImage ?如果您的图像通道具有 RGB 排序(标准 openCV 排序为 BGR),则将 cv::Mat 转换为 QImage 非常有效,因为您只需传递数据数组。如果您订购了 BGR,则可以转换为 RGB afaik,这可能是完整的图像副本。如果只是关于渲染,QImage 可能不是最佳选择,但 OpenGL 可能会快得多。但是:我不确定 Qt 是否可以处理 64 位通道数据。
  • @Micka:我的问题暗示了你的两个问题。事实上,我不需要显示 64 位。这个想法是在后端使用 64 位,在三个分离的通道上以双精度进行一些图像处理,然后,使用 QImage 以最快的速度完成一些数据缓冲区,每个通道显示 8 位。我不确定通道的合并是否应该与 Qt 函数或 opencv 函数一起发生。目前我不想使用openGL。
  • 请注意,一旦我有了 QImage,我就知道如何显示内容了。 (我自己做paintevents,使用QPainters等......)。
  • 如果需要,我会给 cv::merge 一个 try int RGB ordering),然后是 .convertTo 24 位。之后,只需使用 QImage 构造函数,它使用外部数据数组来防止另一个数据复制。但我不知道这是否比在 Qt 中合并和转换效率更高或更低。

标签: c++ qt opencv colors


【解决方案1】:

下面的代码正在运行。

从上面的代码开始(以naxis1和naxis2为图片的宽高):

imRed = new Mat(Size(naxis1, naxis2), CV_64F);
imGreen = new Mat(Size(naxis1, naxis2), CV_64F);
imBlue = new Mat(Size(naxis1, naxis2), CV_64F);


double* redP = imRed->ptr<double>(0);
double* greenP = imGreen->ptr<double>(0);
double* blueP = imBlue->ptr<double>(0);

for (long i = 0; i < nPixels; i++)
{

    redP[i] = (double) rawProcess.imgdata.image[i][0];;
    greenP[i] = (double) rawProcess.imgdata.image[i][1];
    blueP[i] = (double) rawProcess.imgdata.image[i][2];

}

我补充:

std::vector<cv::Mat> matVector;
matVector.push_back(imRed);
matVector.push_back(imGreen);
matVector.push_back(imBlue);

cv::Mat colorMat32;
cv::merge(matVector, colorMat32);

cv::Mat colorMat888

double alpha = (double) (255 / 65535);
double beta = 0.0;

colorMat32.convertTo(colorMat888, CV_8UC3, alpha, beta);

newPaintImage = new QImage(colorMat888.data, naxis1, naxis2, QImage::Format_RGB888);

谢谢@Micka。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-25
    • 2021-03-19
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    相关资源
    最近更新 更多