C++ GPU加速LK金字塔中的窗口大小限制

C++ GPU加速LK金字塔中的窗口大小限制,c++,opencv,cuda,gpu,image-stabilization,C++,Opencv,Cuda,Gpu,Image Stabilization,我在实时提要上执行图像稳定,以便在稳定图像上运行一些视觉算法(强调“实时”)。目前,这一使用CPU实现的LK金字塔版本的处理速度还不够快,即使在事先构建金字塔时(参考图像和“先前”特征只计算一次),但需要缩放以处理分辨率约为四倍的图像,这使得当前的实现速度太慢。我想我可能会尝试通过合并GPU来加快速度,因为OpenCV已经为支持CUDA的设备实现了相同的LK方法,cv::GPU::PyrLKOpticalFlow类。我正在使用::sparse调用和一组以前的特性 我的主要问题是窗户的大小似乎有限

我在实时提要上执行图像稳定,以便在稳定图像上运行一些视觉算法(强调“实时”)。目前,这一使用CPU实现的LK金字塔版本的处理速度还不够快,即使在事先构建金字塔时(参考图像和“先前”特征只计算一次),但需要缩放以处理分辨率约为四倍的图像,这使得当前的实现速度太慢。我想我可能会尝试通过合并GPU来加快速度,因为OpenCV已经为支持CUDA的设备实现了相同的LK方法,cv::GPU::PyrLKOpticalFlow类。我正在使用::sparse调用和一组以前的特性

我的主要问题是窗户的大小似乎有限制,而我的窗户太大了。该限制作为断言出现在pyrlk.cpp文件中:

CV_Assert(patch.x > 0 && patch.x < 6 && patch.y > 0 && patch.y < 6);
我的问题是我需要一个大约80x80像素的窗口大小,这是a。为什么我想使用GPU加速,B。为什么这在OpenCV中似乎不起作用。:)此外,对于分辨率更高的图像,此窗口大小需要增大

我不熟悉GPU加速的实际实现,所以我想知道是否有人能解释为什么OpenCV中存在这种限制,它是否是硬件或OpenCV实现施加的真正限制,以及是否有办法解决它。这似乎很奇怪,这将是一个硬件限制,因为这些情况下,你会想使用一个GPU。我可以用较小的搜索窗口获得合理的速度,但对于应用程序来说,稳定性不够好

我需要这么大的搜索窗口,因为我正在计算第一帧(参考)的运动。运动是周期性的,再加上一些小的随机漂移,因此这种方法工作得很好,但当匹配特征可能在30-40像素(原始分辨率)左右时,需要更多的空间来搜索周期的峰值

这是在Linux上使用OpenCV版本2.4.10,它是从CUDA支持的源代码构建的


(这是一个(经过修改的)重新发布,但似乎没有太多活动,因此希望提供更好的讨论环境!)

补丁大小作为模板参数传递给CUDA内核

请参阅调用代码:


对补丁大小的限制是为了减少模板实例化的数量。通过修改此代码并添加更多实例,您可以根据需要增加此限制。

补丁大小作为模板参数传递给CUDA内核

请参阅调用代码:


对补丁大小的限制是为了减少模板实例化的数量。通过修改此代码并添加更多实例,您可以根据需要增加此限制。

补丁大小作为模板参数传递给CUDA内核

请参阅调用代码:


对补丁大小的限制是为了减少模板实例化的数量。通过修改此代码并添加更多实例,您可以根据需要增加此限制。

补丁大小作为模板参数传递给CUDA内核

请参阅调用代码:


对补丁大小的限制是为了减少模板实例化的数量。您可以根据需要修改此代码并添加更多实例来增加此限制。

如果您为适当的设备进行编译,并且您的窗口是方形的,在我看来,您应该能够获得80x80的
winSize
。但是没有更大的。该算法的实现方式似乎取决于GPU线程块大小,因此是的,似乎确实存在硬件/算法限制。您是否已对其进行调试,以发现实际请求的
winSize
是什么,以及在断言点计算的结果
patch
?最终可能会有像Jet47这样的人来给你一个明确的答案。如果你为合适的设备编译,并且你的窗口是方形的,在我看来,你应该能够获得80x80的
winSize
。但是没有更大的。该算法的实现方式似乎取决于GPU线程块大小,因此是的,似乎确实存在硬件/算法限制。您是否已对其进行调试,以发现实际请求的
winSize
是什么,以及在断言点计算的结果
patch
?最终可能会有像Jet47这样的人来给你一个明确的答案。如果你为合适的设备编译,并且你的窗口是方形的,在我看来,你应该能够获得80x80的
winSize
。但是没有更大的。该算法的实现方式似乎取决于GPU线程块大小,因此是的,似乎确实存在硬件/算法限制。您是否已对其进行调试,以发现实际请求的
winSize
是什么,以及在断言点计算的结果
patch
?最终可能会有像Jet47这样的人来给你一个明确的答案。如果你为合适的设备编译,并且你的窗口是方形的,在我看来,你应该能够获得80x80的
winSize
。但是没有更大的。该算法的实现方式似乎取决于GPU线程块大小,因此是的,似乎确实存在硬件/算法限制。您是否已对其进行调试,以发现实际请求的
winSize
是什么,以及在断言点计算的结果
patch
?最终可能会有像Jet47这样的人来给你一个明确的答案。
void calcPatchSize(cv::Size winSize, dim3& block, dim3& patch)
{
    if (winSize.width > 32 && winSize.width > 2 * winSize.height)
    {
        block.x = deviceSupports(FEATURE_SET_COMPUTE_12) ? 32 : 16;
        block.y = 8;
    }
    else
    {
        block.x = 16;
        block.y = deviceSupports(FEATURE_SET_COMPUTE_12) ? 16 : 8;
    }

    patch.x = (winSize.width  + block.x - 1) / block.x;
    patch.y = (winSize.height + block.y - 1) / block.y;

    block.z = patch.z = 1;
}
static const func_t funcs[5][5] =
{
    {sparse_caller<1, 1, 1>, sparse_caller<1, 2, 1>, sparse_caller<1, 3, 1>, sparse_caller<1, 4, 1>, sparse_caller<1, 5, 1>},
    {sparse_caller<1, 1, 2>, sparse_caller<1, 2, 2>, sparse_caller<1, 3, 2>, sparse_caller<1, 4, 2>, sparse_caller<1, 5, 2>},
    {sparse_caller<1, 1, 3>, sparse_caller<1, 2, 3>, sparse_caller<1, 3, 3>, sparse_caller<1, 4, 3>, sparse_caller<1, 5, 3>},
    {sparse_caller<1, 1, 4>, sparse_caller<1, 2, 4>, sparse_caller<1, 3, 4>, sparse_caller<1, 4, 4>, sparse_caller<1, 5, 4>},
    {sparse_caller<1, 1, 5>, sparse_caller<1, 2, 5>, sparse_caller<1, 3, 5>, sparse_caller<1, 4, 5>, sparse_caller<1, 5, 5>}
};
template <int cn, int PATCH_X, int PATCH_Y>
void sparse_caller(int rows, int cols, const float2* prevPts, float2* nextPts, 
                   uchar* status, float* err, int ptcount,
                   int level, dim3 block, cudaStream_t stream)