基于光流的图像分割

Posted

技术标签:

【中文标题】基于光流的图像分割【英文标题】:Image segmentation based on optical flow 【发布时间】:2016-03-08 09:37:53 【问题描述】:

我正在使用 c++、OpenCV 库,在我的软件中,我估计了视频中的光流。现在,我想对一些移动的对象进行分组,例如移动汽车。我使用了密集光流算法(Farneback)。

到目前为止,我的第一个想法是使用“k 均值”算法进行聚类。

我曾想过使用 Farneback 光流的结果来计算帧在每个方向上的位移,如下所示:

例如:

令 Dx 为 x 方向的位移(正或负),Dy 为 y 方向的位移(正或负)。

然后我将数组 [Dx,Dy] 作为输入传递给具有 k=2 个簇的 k 均值。我希望这会给一个粗略的背景/前景减法。

但是我在计算位移时遇到了问题,因为 calcOpticalFlowFarneback 的输出是 InputOutputArray 流。我应该使用类似的函数访问这个数组吗? :

findDisplacements(const Mat& flow, int step) 
const Point2f& Dx,Dy;
const Point2f& fxy = flow.at<Point2f>(y, x);
Dx=Point(cvRound(x+fxy.x))-Point(x,y);
Dy=Point(cvRound(y+fxy.y))-Point(y,x);

【问题讨论】:

到目前为止你尝试过什么? 我已经使用了 kmeans,我猜它可以工作并返回一个数组 bestLabels。但是我还没有设法将结果显示为图像。我还在使用同样有效的背景减法处理另一个代码。我应该把它们结合起来吗?或者先使用背景减法,然后 k 表示稍后? 你用的什么密集光流算法? 这里光流有什么价值?你试图通过方向/速度来区分物体?如果你知道k,那可能是的。但是,您应该知道标签对应于哪个运动矢量(我猜您是按扫描线顺序形成的)。 @mainactual 我的目标是按方向区分对象。我猜 k 的值取决于我的选择。您能否在括号中进一步解释您关于扫描线顺序的最后评论?这是什么意思? 【参考方案1】:

将运动向量用作特征进行聚类的一个小例子:

cv::Mat img0 = cv::imread("test0.png");    // Image at time t-1
cv::Mat img1 = cv::imread("test1.png");    // Image at time t
cv::Mat flow;
//estimate Optical Flow
cv::calcOpticalFlowFarneback(img0, img1, flow, 0.5, 3, 21, 20, 5, 1.1);
std::vector<cv::Point2f> samples(flow.rows * flow.cols);
// arange sample vector
int n = 0;
for( int r = 0; r < flow.rows; r++) 
  for( int c = 0; c < flow.cols; c++)
    samples[n++] = flow.at<cv::Point2f>(r,c);

cv::kmeans(samples, ...

【讨论】:

【参考方案2】:

您可以使用运动历史。

updateMotionHistory(silh, mhi, timestamp, MHI_DURATION);
calcMotionGradient(mhi, mask, orient, MAX_TIME_DELTA, MIN_TIME_DELTA, 3);
segmentMotion(mhi, segmask, regions, timestamp, MAX_TIME_DELTA);

【讨论】:

以上是关于基于光流的图像分割的主要内容,如果未能解决你的问题,请参考以下文章

图像处理代码合集:特征提取-图像分割-分类-匹配-降噪

图像分割走进基于深度学习的图像分割

基于 OpenCV C++ 光流的分割代码抛出异常

用matlab如何通过图像分割来检测边界

图像分割算法

基于深度学习的图像语义分割方法综述