H-S光流法

H-S光流法

一、实验目的

计算出图像序列的光流场,并用有向箭头在图中标出。

二、算法实现

1、构建图像金字塔

金字塔的每一层包括:图像的灰度图、x和y方向的梯度图、相邻两帧灰度图的像素灰度差( It )。

这里写图片描述

a、计算图像x、y、t方向的梯度。 IxIy 计算方法:每个像素沿x、y方向的两个相邻像素的灰度差的一半。 It 计算方法:当前帧与上一帧对应位置的像素灰度差。代码如下:

//x方向梯度
void GradImg::calculateDerivativeX()
{
  gradx = cv::Mat::zeros(im.size(),CV_64F);  
  for(int y = 0; y < im.rows; ++y)
  {
    for(int x = 0; x < im.cols; ++x)
    {
      int prev = std::max(x - 1, 0);
      int next = std::min(x + 1, im.cols - 1);
      gradx.at<double>(y, x) = (double) (im.at<double>(y, next) - im.at<double>(y, prev)) * 0.5f;
    }
  }
}

//y方向梯度
void GradImg::calculateDerivativeY()
{
  grady = cv::Mat::zeros(im.size(),CV_64F);  
  for(int y = 0; y < im.rows; ++y)
  {
    for(int x = 0; x < im.cols; ++x)
    {
      int prev = std::max(y - 1, 0);
      int next = std::min(y + 1, im.rows - 1);
      grady.at<double>(y, x) = (double) (im.at<double>(next, x) - im.at<double>(prev, x)) * 0.5f;
    }
  }
}
//t方向梯度
void GradImg::calculateDerivativeT(GradImg& ref)
{
  gradt = cv::Mat::zeros(im.size(),CV_64F);  
  for(int y = 0; y < gradt.rows; ++y)
  {
    for(int x = 0; x < gradt.cols; ++x)
    {
      gradt.at<double>(y, x) = (double) (im.at<double>(y, x) - ref.getImg().at<double>(y, x));
    }
  }
}

b、计算图像金字塔,下采样方法为均匀采样,代码如下:

//均匀采样
cv::Mat HSOpticalFlow::pyrDownMeanSmooth(const cv::Mat& in)
{
  cv::Mat out;
  out = cv::Mat::zeros(cv::Size(in.size().width / 2, in.size().height / 2),in.type()); 
  for(int y = 0; y < out.rows; ++y)
  {
    for(int x = 0; x < out.cols; ++x)
    {
      int x0 = x * 2;
      int x1 = x0 + 1;
      int y0 = y * 2;
      int y1 = y0 + 1;
      out.at<double>(y, x) = (double) ( (in.at<double>(y0, x0) + in.at<double>(y0, x1) + in.at<double>(y1, x0) + in.at<double>(y1, x1)) / 4.0f );      
    }
  }
  return out.clone();
}

//建图像金字塔
void HSOpticalFlow::buildpyr()
{
  //清空存放金字塔的容器
  curlevels.clear();
  reflevels.clear();

  reflevels.push_back(ref);
  curlevels.push_back(cur);
  cv::Mat refcopy;
  cv::Mat curcopy;
  refcopy = ref.getImg();
  curcopy = cur.getImg();
  GradImg gradref;
  GradImg gradcur;
  for (int i = 0 ; i < py_layers ; i++)
  {
    cv::Mat refdown = pyrDownMeanSmooth(refcopy);
    gradref.setImg(refdown);
    reflevels.push_back(gradref);
    refcopy = refdown.clone();
    cv::Mat curdown = pyrDownMeanSmooth(curcopy);

    gradcur.setImg(curdown);
    gradcur.calculateDerivativeX();
    gradcur.calculateDerivativeY();
    gradcur.calculateDerivativeT(gradref);
    curlevels.push_back(gradcur);
    curcopy = curdown.clone();
  }
}

2、计算光流

沿着金字塔,从上往下,依次计算光流。上一层的光流通过插值法传到下一层,作为下一层光流的初值。
这样做的好处:由于光流法基于灰度一致性假设,只能处理帧间运动较小的情况,使用金字塔,可以由粗到精计算大运动情况下的光流。
每个像素的光流计算方法如下:

u=uIxIxu+IyvIta+I2x+I2yv=vIyIxu+IyvIta+I2x+I2y

其中 a 为常数,反映了对图像数据及平滑约束的可信度,当图像数据本身含有较大噪声时,此时需要加大a的值,相反,当输入图像含有较少的噪声时,此时可减小 a <script type="math/tex" id="MathJax-Element-177">a</script>的值。
通过在每一层使用上式迭代计算每个像素的光流,再将该层光流传到下一层,作为下一层光流初值,计算下一层的光流。代码如下:

while(iter < maxiter) 
{
   iter++; 
   for(int y = 0; y < im.rows; ++y)
   {
      for(int x = 0; x < im.cols; ++x)
      {
      double mm = optow_ub.at<double>(y,x)*dx.at<double>(y,x) +optow_vb.at<double>         (y,x)*dy.at<double>(y,x) + dt.at<double>(y,x);
      double nn = thea + dx.at<double>(y,x)*dx.at<double>(y,x) + dy.at<double>(y,x)*dy.at<double>(y,x);
      optow_u.at<double>(y,x) = optow_ub.at<double>(y,x) - dx.at<double>(y,x)*(mm/nn);
      optow_v.at<double>(y,x) = optow_vb.at<double>(y,x) - dy.at<double>(y,x)*(mm/nn);    
    }}
    if ( iter < maxiter )  
    {
      optow_ub = smooth<double>(optow_u);
      optow_vb = smooth<double>(optow_v);
    }}

3、光流可视化

用箭头表示图像像素的光流,箭头方向表示光流方向,长度表示光流大小。设定一个阈值区间,只显示在该区间内的光流。代码如下:

//在图片的相应像素上画出光流箭头
for (int y = 0 ; y < u.rows ; y++)
for (int x = 0 ; x < u.cols ; x++)
  {
   if ((abs(u.at<double>(y,x))>th1 && abs(u.at<double>(y,x))<th2) && 
       (abs(v.at<double>(y,x))>th1 && abs(v.at<double>(y,x))<th2))
    {
      cv::Point pStart = Point(x, y);
      cv::Point pEnd = Point(x+u.at<double>(y,x) *1.8f, y+v.at<double>(y,x) *1.8f);   
      drawArrow(rgbcur, pStart, pEnd);
    }
  }
cv::imshow ( rgb_file, rgbcur.clone() );

三、实验结果

1、Traffic数据集

在图像中显示的光流的上下阈值分别设为:2.6、12.8。

这里写图片描述 这里写图片描述 这里写图片描述

2、outdoor数据集

这里写图片描述

这里写图片描述

这里写图片描述

参考资料

https://www.cnblogs.com/rocbomb/p/3795719.html?utm_source=tuicool&utm_medium=referral
http://blog.csdn.net/u014568921/article/details/46638557

源代码

http://download.csdn.net/download/jianwen_jiang/10211887

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Lucas-Kanade光流跟踪算法、Kalman滤波和Horn-Schunck光流跟踪算法都是常用的目标跟踪算法,但是它们的成功率受多种因素影响,例如目标的运动模式、场景的复杂程度、图像的质量等等。 一般而言,Lucas-Kanade光流跟踪算法适用于目标运动较小,场景复杂度较低的情况,其成功率较高;Kalman滤波则可以通过对目标运动模型的建立,提高跟踪的稳定性和准确性,但需要对目标运动模型进行精细的建模;Horn-Schunck光流跟踪算法可以对场景中的所有像素进行跟踪,但对于复杂场景和非刚体运动的目标,其成功率可能会降低。 总的来说,这些跟踪算法的成功率并不能一概而论,需要根据具体的应用场景和算法参数进行选择和优化。 ### 回答2: Lucas-Kanade光流跟踪算法是一种基于局部窗口的光流估计方法。它通过考虑像素间灰度的差异以及他们在时域上的关系来估计运动场景中的光流。Lucas-Kanade算法在追踪小范围运动目标方面表现出色,对于物体的局部运动能够提供相对准确的跟踪结果。然而,当目标存在较大的尺度变化、非刚性运动或者相机快速移动时,Lucas-Kanade算法的追踪效果可能会变差,成功率较低。 Kalman滤波是一种常用于追踪目标的滤波算法。它基于目标的运动模型和观测模型,通过不断更新目标状态的估计值,可以实现对目标的连续追踪。Kalman滤波算法在目标运动模型和观测模型已知且符合线性高斯分布的情况下,可以提供较高的成功率。然而,当目标存在非线性动力学模型或观测噪声的非高斯性质时,Kalman滤波算法的追踪效果可能会下降,成功率也会降低。 Horn-Schunck光流跟踪算法考虑了光流连续性约束,通过最小化运动场景的光流梯度的平方来进行光流估计。这种算法可以较好地处理光照变化以及物体表面运动的不连续性。Horn-Schunck算法在物体表面的显著变化和相机运动快速时表现较差,成功率相对较低。 综上所述,不同的追踪算法在不同的场景下具有不同的成功率。针对不同的目标运动模式和环境条件,选择合适的跟踪算法是保证成功率的关键。+ ### 回答3: Lucas-Kanade光流跟踪算法是一种基于局部邻域的光流估计方法。它将图像的像素值变化视为一个小的运动向量,并利用目标周围像素的灰度值变化对目标的运动进行估计。这种算法适用于文理丰富的目标,并具有较高的跟踪成功率。 Kalman滤波是一种递归滤波器,常用于估计目标的状态并对其运动进行预测。它通过引入过程噪声和测量噪声的模型来减少噪声的影响,从而提高目标跟踪的成功率。Kalman滤波在目标运动模型已知的情况下表现良好,但在目标运动模型未知或非线性时可能存在一定的限制。 Horn-Schunck光流跟踪算法是一种基于全局光流约束的方法。它假设图像整体上是平滑的,通过最小化目标图像区域的灰度差异和光流分量的平方差来优化光流场。相对于Lucas-Kanade算法,Horn-Schunck算法能够应对光照和噪声的变化,但对于目标存在快速运动或文理不平滑的情况,其成功率可能会降低。 总体而言,Lucas-Kanade光流跟踪算法在适应文理丰富的目标方面表现较好;Kalman滤波在已知运动模型下能够有效预测目标的运动;Horn-Schunck光流跟踪算法适用于处理光照和噪声变化,但对于快速运动或不平滑的目标可能有限。因此,根据具体的应用场景和目标特征,选择合适的算法可以提高跟踪的成功率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值