【发布时间】:2016-07-23 19:34:50
【问题描述】:
我目前正在从事一个对象跟踪项目,并使用过 c++ 、 opencv 。我已经成功使用 Farneback 密集光流来实现分割方法,例如 k 均值(使用每帧中的位移)。现在我想用 Lucas Kanade 稀疏方法做同样的事情。但是这个函数的输出是:
nextPts – 2D 点的输出向量(具有单精度浮点坐标),包含第二张图像中输入特征的计算新位置;当传递 OPTFLOW_USE_INITIAL_FLOW 标志时,向量必须与输入中的大小相同。
(如官网所述)
例如,我的问题是 如何将结果转换为 Mat 流。到目前为止我已经尝试过:
//实现Lucas Kanade算法
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);
这是光流演示。任何想法我应该如何获得类似于 Farneback 光流结果的 Mat 流?
更新:非常好的答案。但是现在我在显示 kmeans 图像时遇到了问题。我使用了farneback:
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);
有什么想法吗? ?
【问题讨论】:
-
不确定密集光学流使用的类型,但可能。某事像这样:对于 f1features 中的每个点和 f2features 中对应的 pt:map.at<:vec2f>(point) = cv::Vec2f(f2feature.x-f1feature.x, f2feature.y-f1feature.y)。将所有其他点设置为表示“未知 - 无法提取该像素的流”的值
-
你说的最后一句话是什么意思?你能再解释一下吗?谢谢,我正在考虑类似的想法!
-
lucas kanade 计算了一个非常稀疏的流。因此,您的地图密集流中将有很多点您没有流信息。您必须决定为这些像素设置什么样的值。
-
@george_t 我为你的问题添加了一个可能的答案,以 cv 开头的函数名称通常是 opencv c 版本。在文档中你可以看到他们有
C++: void calcOpticalFlowPyrLK和C: void cvCalcOpticalFlowPyrLK。另外,我已经将 KMeans 直接用于 2D 新点,但我不确定您是要对新图像中的相似点(接近的点)进行聚类,还是对两个图像之间具有相似差异的点进行聚类,如果是稍后,只有一个带有差异的 cv::Point2f 向量将起作用 -
@george_t 好吧,你可以随时使用
std::vector<cv::Vec2f>,在这里你可以放置每个点的位移。如果您希望 kmeans 考虑对象的初始位置或最终位置,也可以使用cv::Vec4f。甚至cv::Vec5f,如果您想在计算中包含强度。我会更新我的答案
标签: c++ opencv opticalflow