我试图将cv::cuda::FarnebackOpticalFlow
算法的输出转换为3个无符号字节的YUV平面(以便通过FFMPEG进行后续压缩)。
我在调用stream.waitForCompletion()
时收到错误代码-217("未指定的启动失败")(此处未显示);在我的内核中触发错误的是尝试为其中一个输出GpuMat
对象赋值(请参阅dst_y(y, x) = ...
下面的行)。
我在Windows 10下使用从源代码编译的OpenCV 3.3。
我使用CMake cuda_add_executable()
命令来定义我的项目,并且我已经使用set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -arch compute_50 -code sm_50)
定义了CUDA标记,尽管我已经尝试了不再有的变体成功。我的显卡是GTX 970。
#include <opencv2/core/cuda_stream_accessor.hpp>
using namespace cv;
using namespace cuda;
namespace
{
__global__ void kernelFunc(
const PtrStepSz<float2>& src,
float scale_x, float scale_y,
PtrStepSzb dst_y, PtrStepSzb dst_u, PtrStepSzb dst_v)
{
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
if (x < src.cols && y < src.rows && y >= 0 && x >= 0)
{
// Get input: optical flow, and scale it
auto dx = scale_x * src(y, x).x, dy = scale_y * src(y, x).y;
// Luma: flow vector length, compressed using an exponential function
auto l = sqrt(dx*dx + dy*dy);
l = exp(5*l) / (exp(5*l) + 1);
dst_y(y, x) = 255 * l;
// Chroma (U and V)
dst_u(y, x) = 255 * (dx + 0.5);
dst_v(y, x) = 255 * (dy + 0.5);
}
}
} // ns
void compress_optical_flow_mat_to_yuv444(const GpuMat& src,
GpuMat& dst_y, GpuMat& dst_u, GpuMat& dst_v,
Stream& stream)
{
using namespace std::string_literals;
dst_y.create(src.size(), CV_8UC1);
dst_u.create(src.size(), CV_8UC1);
dst_v.create(src.size(), CV_8UC1);
dim3 cthreads(16, 16); //(32, 8);
dim3 cblocks(
static_cast<int>(ceil(src.size().width / static_cast<double>(cthreads.x))),
static_cast<int>(ceil(src.size().height / static_cast<double>(cthreads.y))));
// We scale optical flow so that the range [-0.5..0.5] covers half the width and half the height,
// in pixels, of the image. In other words, a given pixel may not move by more than half the
// image size per frame.
float scale_x = 0.5f / src.size().width;
float scale_y = 0.5f / src.size().height;
auto cu_str = StreamAccessor::getStream(stream);
kernelFunc<<<cblocks, cthreads, 0, cu_str>>>(src, scale_x, scale_y, dst_y, dst_u, dst_v);
auto err = cudaGetLastError();
if (err != 0)
throw std::runtime_error("compress_optical_flow_mat_to_yuv444() kernel call failed with error "s
+ std::to_string(err) + ": " + cudaGetErrorString(err));
}
答案 0 :(得分:1)
从以下行中删除&
符号:
__global__ void kernelFunc(
const PtrStepSz<float2>& src,
float scale_x, float scale_y,
PtrStepSzb dst_y, PtrStepSzb dst_u, PtrStepSzb dst_v)
到
__global__ void kernelFunc(
const PtrStepSz<float2> src,
float scale_x, float scale_y,
PtrStepSzb dst_y, PtrStepSzb dst_u, PtrStepSzb dst_v)