0
我試圖將cv::cuda::FarnebackOpticalFlow
算法的輸出轉換爲無符號字節的3個YUV平面(用於通過FFMPEG進行後續壓縮)。OpenCV CUDA錯誤-217試圖執行我的自定義函數
我在調用stream.waitForCompletion()
(未在此處顯示)時收到錯誤代碼-217(「未指定的啓動失敗」);在我的內核中觸發錯誤的原因是嘗試爲輸出GpuMat
對象之一分配一個值(請參閱下面的行dst_y(y, x) = ...
)。
我使用的OpenCV 3.3,從源代碼編譯時,Windows 10下
我使用的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));
}
賓果!並感謝一噸。所以,傳遞一個const引用應該可以用普通的C++工作,但是在這裏我們將東西從CPU傳遞到GPU,所以這個規則在窗口外面是可以理解的。如果nvcc提醒我的話,那本來是很好的! – JPNotADragon
@JPNotADragon很高興爲您提供幫助。儘管說實話我並不完全確定爲什麼const引用不起作用。我遇到了同樣的問題,而且我無意中偶然發現了這個解決方案。如果你發現原因,請讓我知道。 – zindarod
現在我想到了,CPU-GPU接口可能不是唯一需要考慮的因素。我正在使用流式處理,這意味着輸入數據在調用封裝函數後仍然可用 - 這裏不會出現這種情況,因爲PtrStep對象是由GpuMat轉換運算符生成的臨時對象。 – JPNotADragon