Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何通过opencv计算提取轮廓的曲率?_C++_Opencv - Fatal编程技术网

C++ 如何通过opencv计算提取轮廓的曲率?

C++ 如何通过opencv计算提取轮廓的曲率?,c++,opencv,C++,Opencv,我确实使用了findcontours()方法从图像中提取轮廓,但我不知道如何从一组轮廓点计算曲率。有人能帮我吗?多谢各位 对于我来说,曲率是: 其中,t是轮廓内的位置,x(t)respy(t)返回相关的xrespy值。看 因此,根据我对曲率的定义,可以这样实现: std::vector< float > vecCurvature( vecContourPoints.size() ); cv::Point2f posOld, posOlder; cv::Point2f f1stDe

我确实使用了
findcontours()
方法从图像中提取轮廓,但我不知道如何从一组轮廓点计算曲率。有人能帮我吗?多谢各位

对于我来说,曲率是:

其中,
t
是轮廓内的位置,
x(t)
resp
y(t)
返回相关的
x
resp<代码>y值。看

因此,根据我对曲率的定义,可以这样实现:

std::vector< float > vecCurvature( vecContourPoints.size() );

cv::Point2f posOld, posOlder;
cv::Point2f f1stDerivative, f2ndDerivative;   
for (size_t i = 0; i < vecContourPoints.size(); i++ )
{
    const cv::Point2f& pos = vecContourPoints[i];

    if ( i == 0 ){ posOld = posOlder = pos; }

    f1stDerivative.x =   pos.x -        posOld.x;
    f1stDerivative.y =   pos.y -        posOld.y;
    f2ndDerivative.x = - pos.x + 2.0f * posOld.x - posOlder.x;
    f2ndDerivative.y = - pos.y + 2.0f * posOld.y - posOlder.y;

    float curvature2D = 0.0f;
    if ( std::abs(f2ndDerivative.x) > 10e-4 && std::abs(f2ndDerivative.y) > 10e-4 )
    {
        curvature2D = sqrt( std::abs( 
            pow( f2ndDerivative.y*f1stDerivative.x - f2ndDerivative.x*f1stDerivative.y, 2.0f ) / 
            pow( f2ndDerivative.x + f2ndDerivative.y, 3.0 ) ) );
    }
    
    vecCurvature[i] = curvature2D;
    
    posOlder = posOld;
    posOld = pos;
}
std::vectorvecCurvature(veccurtourpoints.size());
cv::Point2f posOld,posOld;
cv::点2F F1ST导数、F2ND导数;
对于(size_t i=0;i10e-4和&std::abs(f2ndDerivative.y)>10e-4)
{
曲率2d=sqrt(标准::abs(
功率(f2ndDerivative.y*f1stDerivative.x-f2ndDerivative.x*f1stDerivative.y,2.0f)/
pow(f2ndDerivative.x+f2ndDerivative.y,3.0));
}
向量曲率[i]=曲率2d;
posOld=posOld;
posOld=pos;
}
它也适用于非闭合点列表。对于闭合轮廓,您可能希望更改边界行为(对于第一次迭代)

更新:

衍生工具说明:

连续一维函数
f(t)
的导数为:

但是我们在一个离散空间中,有两个离散函数
f_x(t)
f_y(t)
,其中
t
的最小步长是一步

二阶导数是一阶导数的导数:

使用一阶导数的近似值,得出:


导数还有其他近似值,如果你搜索一下,你会发现很多。

虽然Gombat答案背后的理论是正确的,但代码和公式中都有一些错误(分母
t+n-x
应该是
t+n-t
)。我做了一些改变:

  • 使用对称导数可以获得更精确的曲率最大值位置
  • 允许使用步长进行导数计算(可用于减少噪声轮廓的噪声)
  • 使用闭合轮廓进行工作
修正: *如果分母为0(不是0),则返回无穷大作为曲率 *增加了分母平方计算 *正确检查0除数

std::vector<double> getCurvature(std::vector<cv::Point> const& vecContourPoints, int step)
{
  std::vector< double > vecCurvature( vecContourPoints.size() );

  if (vecContourPoints.size() < step)
    return vecCurvature;

  auto frontToBack = vecContourPoints.front() - vecContourPoints.back();
  std::cout << CONTENT_OF(frontToBack) << std::endl;
  bool isClosed = ((int)std::max(std::abs(frontToBack.x), std::abs(frontToBack.y))) <= 1;

  cv::Point2f pplus, pminus;
  cv::Point2f f1stDerivative, f2ndDerivative;
  for (int i = 0; i < vecContourPoints.size(); i++ )
  {
      const cv::Point2f& pos = vecContourPoints[i];

      int maxStep = step;
      if (!isClosed)
        {
          maxStep = std::min(std::min(step, i), (int)vecContourPoints.size()-1-i);
          if (maxStep == 0)
            {
              vecCurvature[i] = std::numeric_limits<double>::infinity();
              continue;
            }
        }


      int iminus = i-maxStep;
      int iplus = i+maxStep;
      pminus = vecContourPoints[iminus < 0 ? iminus + vecContourPoints.size() : iminus];
      pplus = vecContourPoints[iplus > vecContourPoints.size() ? iplus - vecContourPoints.size() : iplus];


      f1stDerivative.x =   (pplus.x -        pminus.x) / (iplus-iminus);
      f1stDerivative.y =   (pplus.y -        pminus.y) / (iplus-iminus);
      f2ndDerivative.x = (pplus.x - 2*pos.x + pminus.x) / ((iplus-iminus)/2*(iplus-iminus)/2);
      f2ndDerivative.y = (pplus.y - 2*pos.y + pminus.y) / ((iplus-iminus)/2*(iplus-iminus)/2);

      double curvature2D;
      double divisor = f1stDerivative.x*f1stDerivative.x + f1stDerivative.y*f1stDerivative.y;
      if ( std::abs(divisor) > 10e-8 )
        {
          curvature2D =  std::abs(f2ndDerivative.y*f1stDerivative.x - f2ndDerivative.x*f1stDerivative.y) /
                pow(divisor, 3.0/2.0 )  ;
        }
      else
        {
          curvature2D = std::numeric_limits<double>::infinity();
        }

      vecCurvature[i] = curvature2D;


  }
  return vecCurvature;
}
std::vector getCurvature(std::vector const&vector ContourPoints,int step)
{
std::vectorvecCurvature(veccurtourpoints.size());
if(veccourpoints.size()<步长)
返回向量曲率;
auto frontToBack=vecContourPoints.front()-vecContourPoints.back();

std::如果你向我们提供你已经尝试过的事情的列表和一个更具体的问题,这会有很大帮助吗?谢谢你的评论。但是我不明白为什么f1stDerivative.x和f2ndDerivative.x可以计算为你在代码中显示的公式?有几个选项。我对答案添加了解释。我已经e尝试了你发布的代码。但我得到了很多值,如-1.#IND000000000000?当分母中的两个导数值都为零时会发生这种情况。我更新了代码。现在,有一个额外的检查,否则曲率为零。但问题可能是,sqrt的参数为负。添加了一个
std::abs
调用。