首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何计算Lucas Kanade流

如何计算Lucas Kanade流
EN

Stack Overflow用户
提问于 2016-04-04 10:01:01
回答 1查看 2K关注 0票数 3

我目前正在从事一个目标跟踪项目,并使用了c++,opencv。我成功地利用了Farneback密集光流来实现像k均值这样的分割方法(利用每个帧中的位移)。现在,我想用Lucas Kanade稀疏方法做同样的事情。但是这个函数的输出是:

二维点的nextPts输出矢量(具有单精度浮点坐标),其中包含计算出的第二幅图像中输入特征的新位置;当传递OPTFLOW_USE_INITIAL_FLOW标志时,该向量必须具有与输入中相同的大小。

(如官方网站所述)

我的问题是,例如,我将如何获得Mat flow的结果。到目前为止,我已经尝试过:

//实现Lucas Kanade算法

代码语言:javascript
复制
cvCalcOpticalFlowPyrLK(frame1_1C, frame2_1C, pyramid1, pyramid2,
frame1_features, frame2_features, number_of_features,
optical_flow_window, 5, optical_flow_found_feature,
optical_flow_feature_error, optical_flow_termination_criteria,
0);
 // Calculate each feature point's coordinates in every frame 
 CvPoint p,q;
 p.x = (int) frame1_features[i].x;
 p.y = (int) frame1_features[i].y;

 q.x = (int) frame2_features[i].x;
 q.y = (int) frame2_features[i].y;
// Creating the arrows for imshow

angle = atan2((double) p.y - q.y, (double) p.x - q.x);
hypotenuse = sqrt(square(p.y - q.y) + square(p.x - q.x));

/* Here we lengthen the arrow by a factor of three. */

q.x = (int) (p.x - 3 * hypotenuse * cos(angle));
q.y = (int) (p.y - 3 * hypotenuse * sin(angle));

cvLine(frame1, p, q, line_color, line_thickness, CV_AA, 0);

p.x = (int) (q.x + 9 * cos(angle + pi / 4));
p.y = (int) (q.y + 9 * sin(angle + pi / 4));
cvLine(frame1, p, q, line_color, line_thickness, CV_AA, 0);
p.x = (int) (q.x + 9 * cos(angle - pi / 4));
p.y = (int) (q.y + 9 * sin(angle - pi / 4));
cvLine(frame1, p, q, line_color, line_thickness, CV_AA, 0);

allocateOnDemand(&framenew, frame_size, IPL_DEPTH_8U, 3);
cvConvertImage(frame1, framenew, CV_CVTIMG_FLIP);

cvShowImage("Optical Flow", framenew);

这是光流表示。有什么想法,我应该如何得到类似于远背光流结果的Mat流?

(tracking.html#calcopticalflowfarneback )

更新:非常好的答案。但现在我在展示kmeans形象上遇到了问题。我用的是“远避”:

代码语言:javascript
复制
cv::kmeans(m, K, bestLabels,
                TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0),
                3, KMEANS_PP_CENTERS, centers);
        int colors[K];
        for (int i = 0; i < K; i++) {
            colors[i] = 255 / (i + 1);
        }

        namedWindow("Kmeans", WINDOW_NORMAL);

        Mat clustered = Mat(flow.rows, flow.cols, CV_32F);

        for (int i = 0; i < flow.cols * flow.rows; i++) {
            clustered.at<float>(i / flow.cols, i % flow.cols) =
                    (float) (colors[bestLabels.at<int>(0, i)]);
        }
        clustered.convertTo(clustered, CV_8U);
        imshow("Kmeans", clustered);

有什么主意吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-04-04 13:00:37

要获得像Farneback算法这样的图像,您必须首先了解输出是什么。

在OpenCV文档中有:

prev(y,x) ~ next(y + flow(y,x)[1], x +flow(y,x)[0])

因此,它是一个矩阵,在图像1和2之间有位移。假设你不计算的点没有运动,0,0;你可以模拟这一点,你只需要把每个点(x,y)有新的位置(x', y')

代码语言:javascript
复制
cv::Mat LKFlowMatrix(img.rows, img.cols, CV_32FC2, cv::Scalar(0,0));
LKFlowMatrix.at<cv::Vec2f>(y,x) = cv::Vec2f(x-x', y-y') ;

另外,不要忘记使用status =0过滤“”。

顺便说一下,您的函数不是opencv c++版本的:

cvCalcOpticalFlowPyrLK应该是cv::calcOpticalFlowFarneback in c++,cvShowImage在c++中应该是cv::imshow等等。

**更新**

由于您需要的是kmeans的输入(我想这是OpenCV版本),而且您只想使用稀疏点,那么您可以这样做:

代码语言:javascript
复制
cv::Mat prevImg, nextImg;
// load your images

std::vector<cv:Point2f> initial_points, new_points;
// fill the initial points vector 

std::vector<uchar> status;
std::vector<float> error;

cv::calcOpticalFlowPyrLK(prevImage, nextImage, initial_points, new_points, status, errors);

std::vector<cv::Vec2f> vectorForKMeans;
for(size_t t = 0; t < status.size(); t++){
  if(status[t] != 0)
    vectorForKmeans.push_back(cv::Vec2f(initial_points[i] - new_points[i]));
}

// Do kmeans to vectorForKMeans
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36399624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档