Replace cv::calcOpticalFlowPyrLK with cv::cuda::SparsePyrLKOpticalFlow api

Hi , for performance, I’d like to use cv::cuda::SparsePyrLKOpticalFlow. Setting the same parameters, It seems outputs of the two API not exactly the same, so is there any way to get the same outputs from the two APIs? Or no way to do it?

You may find this useful. In response to a question a user had I converted a CPU example using calcOpticalFlowPyrLK to a CUDA one using SparsePyrLKOpticalFlow in python.

Note the implementation is not optimized in any way it is simply to show how to get the “same” result using the two different api’s.

Yes, I alse wrote a similar cpp version, here the code. If we fix other parameters, It seems maxCorners I have set it a big value, which will lead to difference. so the question is how to adjust these params?


#include <opencv2/opencv.hpp>
static void download(const cv::cuda::GpuMat& d_mat,
std::vectorcv::Point2f& vec) {
cv::Mat mat(1, d_mat.cols, CV_32FC2, reinterpret_cast<void*>(&vec[0]));;

int main(void) {
constexpr int maxCorners = 100;
constexpr double qualityLevel = 0.01;
constexpr double minDist = 20.0;
// constexpr double blockSize = 3;
cv::Ptrcv::cuda::CornersDetector detector =
CV_8UC1, maxCorners, qualityLevel, minDist);
// for optflow
constexpr int winSize = 21;
constexpr int maxLevel = 3;
constexpr int iters = 30;
cv::Ptrcv::cuda::SparsePyrLKOpticalFlow d_pyrLK_sparse =
cv::cuda::SparsePyrLKOpticalFlow::create(cv::Size(winSize, winSize),
maxLevel, iters);

cv::Mat prevImgGray = cv::imread(“./srcimg/prev.jpg”, cv::IMREAD_GRAYSCALE);
cv::Mat nextImgGray = cv::imread(“./srcimg/next.jpg”, cv::IMREAD_GRAYSCALE);
if (prevImgGray.empty() || nextImgGray.empty()) {
std::cout << “open file failed” << std::endl;
cv::cuda::GpuMat d_prevImgGray(prevImgGray);
cv::cuda::GpuMat d_nextImgGray(nextImgGray);

cv::cuda::GpuMat d_prevPts;
detector->detect(d_prevImgGray, d_prevPts);
std::vectorcv::Point2f prevPts;
download(d_prevPts, prevPts);

std::vectorcv::Point2f cvGpuRet;
cv::cuda::GpuMat d_nextPts;
cv::cuda::GpuMat d_status;
d_pyrLK_sparse->calc(d_prevImgGray, d_nextImgGray, d_prevPts, d_nextPts,
download(d_nextPts, cvGpuRet);

std::vectorcv::Point2f cvCpuRet;
std::vector cvCpuErr;
std::vector status;
// cv::TermCriteria criteria = cv::TermCriteria(
// (cv::TermCriteria::COUNT) + (cv::TermCriteria::EPS), 10, 0.03);
cv::calcOpticalFlowPyrLK(prevImgGray, nextImgGray, prevPts, cvCpuRet,
status, cvCpuErr, cv::Size(winSize, winSize),
for (size_t i = 0; i < prevPts.size(); ++i) {
std::cout << “prevPts:” << prevPts[i] << " cvCpuRet:" << cvCpuRet[i]
<< " cvGpuRet:" << cvGpuRet[i] << std::endl;
return 0;