英文:
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 <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); //Place holder for map buffer from the question.
std::vector<uint8_t> map_bgr = std::vector<uint8_t>(width*height*3, 0); // Allocate buffer for storing BGR image (we don'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, "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); //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("uframe_bgr", 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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论