- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
简介:
意向是使用 OpenCV 捕获视频,并将其用作 OpenCL 程序的输入 .两者的转移需要为高效 尽可能(如果这不是问题,为什么要使用 OpenCL,对吗?)。
我读到 OpenCV 在内部使用 OpenCL( UMat
),并且我可以访问 GPU
通过访问 UMat::handle
来缓冲.但是,到目前为止,我为此所做的尝试都没有成功。
意图是重用UMat
缓冲区作为 OpenCL 的输入 kernels
,并最终将结果作为图像返回另一个 UMat
用于显示它。
OpenCV 框架仅用于为程序生成输入,因此,我对使用 OpenCV CL 包装器 ( cv::ocl
) 不感兴趣,而是使用普通 OpenCL ( cl::...
)。这避免在完整软件中包含/链接 OpenCV 框架。
问题:
如何通过 OpenCL 访问 OpenCV UMat 缓冲区?
DISCLAIM: please, be kind, as this is just supposed to be a very minimal example for this question.
#include <iostream>
#include <vector>
#include <cassert>
#define __CL_ENABLE_EXCEPTIONS // enable exceptions instead of error-codes
#define CL_TARGET_OPENCL_VERSION 120
#include <CL/cl.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/core/ocl.hpp>
using namespace cv;
using namespace std;
int main()
{
// OPENCL STUFF
// Very simplified/basic/stupid/naive OpenCL context creation
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
assert(platforms.size()>0);
std::vector<cl::Device> devices;
platforms[0].getDevices( CL_DEVICE_TYPE_ALL, &devices);
assert(devices.size()>0);
cl_context_properties prop[3] =
{
CL_CONTEXT_PLATFORM,
(cl_context_properties)(platforms[0])(),
0
};
cl::Context context( devices[0], prop, nullptr, nullptr);
std::string kernelStr = R"DELIMITER(
kernel void replaceRB( global uchar3* content)
{
const size_t globalId = get_global_id(0);
private uchar3 byte = content[globalId];
char aux = byte.z;
byte.z = byte.x;
byte.x = aux;
content[globalId] = byte;
}
)DELIMITER";
cl::Program::Sources sources;
sources.push_back(std::make_pair<const char*, size_t>(kernelStr.data(), kernelStr.size()));
cl::Program program(context, sources);
try
{
program.build({devices[0]}, "");
}
catch (...)
{
std::cout << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0]) << std::endl;
}
std::vector<cl::Kernel> kernels;
program.createKernels(&kernels);
assert(kernels.size()>0);
cl::CommandQueue queue(context, devices[0]);
// OPENCV STUFF
ocl::setUseOpenCL(true);
cv::ocl::attachContext(platforms[0].getInfo<CL_PLATFORM_NAME>(), platforms[0](), context(), devices[0]());
assert(ocl::haveOpenCL());
cout << cv::ocl::Context::getDefault().ndevices() << " GPU devices are detected." << endl;
VideoCapture cap(0); //Camera
//VideoCapture cap("SampleVideo_1280x720_1mb.mp4"); //Video example
assert(cap.isOpened());
UMat frame;
assert(cap.read(frame));
//MIX OF BOTH opencl and opencv
//cl::Buffer buf(context,CL_MEM_READ_WRITE, 256); // This works
cl::Buffer buf(*((cl_mem*)frame.handle(CL_MEM_READ_WRITE)));
int result = kernels[0].setArg(0, buf);
std::cout << result << " == " << CL_INVALID_MEM_OBJECT << std::endl;
queue.enqueueNDRangeKernel(kernels[0], cl::NullRange, cl::NDRange(16), cl::NDRange(4));
queue.flush();
//DISPLAY RESULT?
string window_name = "Test OpenCV and OpenCL";
namedWindow(window_name);
imshow(window_name, frame);
waitKey(5000);
return 0;
}
最佳答案
cv::UMat 和 opencv 的“透明 API”使用起来非常不直观,主要是因为它们向客户端隐藏了实际内存管理的非常重要的任务。
具体来说,在您的代码中,您向 cap::read 提供了一个空的 cv::UMat。 opencv 将不得不 分配 实际帧的内存。但不能保证此内存实际上会分配在正确的设备(clbuffer)内存上。如果您调试 opencv 源代码,我不会感到惊讶,您将看到在 RAM 上分配的实际内存。因此没有有效的 cl_mem 句柄。
你基本上有两个选择:
选项 1:在设备上显式地预分配 cv::UMat:
UMat frame = cv::UMat(cv::Size(width, height), format, cv::USAGE_ALLOCATE_DEVICE_MEMORY);
assert(cap.read(frame));
cv::UMat frame;
cv::ocl::convertFromBuffer(
my_cl_mem,
pitch,
rows,
cols,
format,
frame
);
关于c++ - 如何从 OpenCL 访问 OpenCV UMat (gpu) 缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58440529/
我是一名优秀的程序员,十分优秀!