如何使用OpenCV Transparent API将BGRA2BGR进行转换。

huangapple go评论65阅读模式
英文:

How to convert BGRA2BGR using OpenCV Transparent API

问题

我想要使用我硬件上的可用GPU实现给定图像的颜色空间转换。为了实现这一目标,我们有OpenCV的Transparent API(UMat),它利用GPU执行处理。

我有一台IMX8MP EVK套件,支持GPU。

我有一个视频,它的格式是BGRA,我正在使用gstreamer appsrc读取该视频。我想将颜色空间转换为BGR,以便在opencv中进行进一步处理。我尝试使用opencv的Mat和cvtColor() API进行转换,但它消耗了大量的CPU资源。因此,我希望在GPU上执行颜色转换活动。

我将接收到的Gstreamer缓冲区转换为cv::Mat,使用以下代码片段。

cv::Mat image = cv::Mat(cv::Size(width, height), CV_8UC4, (char*)map.data, cv::Mat::AUTO_STEP);

然后,我进一步将cv::Mat转换为cv::UMat,使用以下代码:

cv::UMat uframe = image.getUMat(cv::ACCESS_READ);

在获得UMat类型的uframe后,我执行颜色空间转换。

cv::cvtColor(uframe, uframe, cv::COLOR_BGRA2BGR);

在这一点上,当执行我的应用程序时,我的硬件停止响应任何命令,就好像它处于死锁状态。我想了解我哪里做错了。

UMat是否支持BGRA2BGR转换?
另外,UMat会在内部使用OpenCL来在GPU上执行处理吗?

英文:

I want to achieve colorspace conversion of a given image using available GPU on my hardware. To achieve this, we have Opencv's Transparent api's (UMat) that utilize the GPU to perform processing.

I have IMX8MP EVK kit, that has GPU support enabled.

I have a video that has BGRA format and I am reading the video using gstreamer appsrc. I want to change the colorspace conversion to BGR for further processing using opencv. I have tried using opencv's Mat with cvtColor() api which consumes lot of cpu resources. Hence, I want to perform the color conversion activity on GPU.

I convert the received Gstreamer buffer to cv::Mat. Using the code snippet.

cv::Mat image = cv::Mat(cv::Size(width, height), CV_8UC4, (char*)map.data, cv::Mat::AUTO_STEP);

I further convert the cv::Mat to cv::UMat using

cv::UMat uframe = image.getUMat(cv::ACCESS_READ);

After getting the UMat type uframe, I perform colorspace conversion.

cv::cvtColor(uframe, uframe, cv::COLOR_BGRA2BGR);

At this point, my hardware stops responding to any command as if it is in deadlock when my application is executed. I want to understand where I am going wrong.

Does UMat support BGRA2BGR conversion?
Also, will OpenCL will be utilized internally by UMat to do the processing on GPU?

答案1

得分: 2

查看ocl_cvtColor的源代码(位于color.cpp中),似乎不支持“原地”处理。

我们不能像在cv::cvtColor(uframe, uframe, cv::COLOR_BGRA2BGR);中那样同时将uframe用作输入输出

选择cv::ACCESS_READ也可能导致问题,当函数尝试写入uframe时。

替换cv::cvtColor(uframe, uframe_bgr, cv::COLOR_BGRA2BGR);为以下方式:

cv::cvtColor(uframe, uframe_bgr, cv::COLOR_BGRA2BGR);

其中uframe_bgr是另一个带有cv::ACCESS_WRITE(或cv::ACCESS_RW)访问标志的cv::UMat

注意:

  • 无法在PC上重现此问题,因此我们不能确定该解决方案是否适用于IMX8MP。

示例代码(将map.data替换为map.data()):

#include <opencv2/opencv.hpp>
#include <opencv2/videoio.hpp>

int main()
{
    int width = 640;
    int height = 480;

    std::vector<uint8_t> map = std::vector<uint8_t>(width*height*4, 0); //用于存储地图缓冲区的占位符。
    std::vector<uint8_t> map_bgr = std::vector<uint8_t>(width*height*3, 0); // 为存储BGR图像分配缓冲区(我们实际上不需要它)。

    // 填充图像以进行测试:
    cv::Mat image = cv::Mat(cv::Size(width, height), CV_8UC4, (char*)map.data(), cv::Mat::AUTO_STEP);
    image = cv::Scalar(60, 60, 60, 255);
    cv::putText(image, "Text", cv::Point(width / 2 - 70 * (int)(std::string("Text").length()), height / 2 + 100), cv::FONT_HERSHEY_DUPLEX, 8, cv::Scalar(30, 255, 30), 15);

    cv::UMat uframe = image.getUMat(cv::ACCESS_READ);

    cv::Mat image_bgr = cv::Mat(cv::Size(width, height), CV_8UC3, (char*)map_bgr.data(), cv::Mat::AUTO_STEP); // 为存储BGR图像创建cv::Mat。
    cv::UMat uframe_bgr = image_bgr.getUMat(cv::ACCESS_WRITE); // 获取具有accessFlags = cv::ACCESS_WRITE的cv::UMat

    // cv::cvtColor(uframe, uframe_bgr, cv::COLOR_BGRA2BGR);
    cv::cvtColor(uframe, uframe_bgr, cv::COLOR_BGRA2BGR);  // 使用uframe_bgr作为输出。

    cv::imshow("uframe_bgr", uframe_bgr);
    cv::waitKey();
    cv::destroyAllWindows();

    return 0;
}

上述代码示例使用std::vector来分配内存缓冲区。请将std::vector替换为您用于map.data的分配方式。

英文:

Looking at the sources of ocl_cvtColor (in color.cpp), it seems like there is no support for "in-place" processing.

We can't use uframe both as input and an output as in cv::cvtColor(uframe, uframe, cv::COLOR_BGRA2BGR);.

Selecting cv::ACCESS_READ may also cause issues, when the function tries to write to uframe.


Replace cv::cvtColor(uframe, uframe_bgr, cv::COLOR_BGRA2BGR); with something like:

cv::cvtColor(uframe, uframe_bgr, cv::COLOR_BGRA2BGR);

Where uframe_bgr is another cv::UMat with cv::ACCESS_WRITE (or cv::ACCESS_RW) access flags.


Note:

  • The issue is not reproducible using a PC, so we can't be sure that the solution is going to work with IMX8MP.

Sample code (map.data is replaced with map.data()):

#include &lt;opencv2/opencv.hpp&gt;
#include &lt;opencv2/videoio.hpp&gt;

int main()
{
    int width = 640;
    int height = 480;

    std::vector&lt;uint8_t&gt; map = std::vector&lt;uint8_t&gt;(width*height*4, 0); //Place holder for map buffer from the question.
    std::vector&lt;uint8_t&gt; map_bgr = std::vector&lt;uint8_t&gt;(width*height*3, 0); // Allocate buffer for storing BGR image (we don&#39;t really need it).

    //Fill the image with some content (for testing):
    cv::Mat image = cv::Mat(cv::Size(width, height), CV_8UC4, (char*)map.data(), cv::Mat::AUTO_STEP);
    image = cv::Scalar(60, 60, 60, 255);
    cv::putText(image, &quot;Text&quot;, cv::Point(width / 2 - 70 * (int)(std::string(&quot;Text&quot;).length()), height / 2 + 100), cv::FONT_HERSHEY_DUPLEX, 8, cv::Scalar(30, 255, 30), 15);

    cv::UMat uframe = image.getUMat(cv::ACCESS_READ);
    
    cv::Mat image_bgr = cv::Mat(cv::Size(width, height), CV_8UC3, (char*)map_bgr.data(), cv::Mat::AUTO_STEP); //Create cv::Mat for storing BGR image.
    cv::UMat uframe_bgr = image_bgr.getUMat(cv::ACCESS_WRITE); //Get cv::UMat with accessFlags = cv::ACCESS_WRITE

    //cv::cvtColor(uframe, uframe_bgr, cv::COLOR_BGRA2BGR);
    cv::cvtColor(uframe, uframe_bgr, cv::COLOR_BGRA2BGR);  //Use uframe_bgr as output.

    cv::imshow(&quot;uframe_bgr&quot;, uframe_bgr);
    cv::waitKey();
    cv::destroyAllWindows();
    

    return 0;
}

The above code sample uses std::vector for allocating the memory buffers.
Replace the std::vector with the allocation you are using for map.data.

huangapple
  • 本文由 发表于 2023年6月1日 18:40:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76381046.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定