我正在寻找一种算法(使用OpenCV C或C ++)来做到这一点:
给定边界图像,我想在所有点找到局部曲率并对其进行颜色映射,这是在上面显示的图像中完成的。我从Wikipedia得到了这张图片,但是却无法通过这种方式找到一种为边界着色的方法。请告诉我如何做到这一点。
如果观察边界,则红色表示边界具有高斜率,黄色表示边界几乎是线性的。
如何做到这一点?
修改
只是为了让你了解我两天后如何尝试这样做:
我使用了openCV函数convexHull
和convexityDefects
,但意识到我的方向是错误的。我只能在二进制图像的轮廓/边界上工作。
答案 0 :(得分:0)
您可以通过将三次贝塞尔曲线的路径拟合到边界,然后分析地获取曲率来解决问题。
[阐述]
边界由像素中心的x,y中的点列表组成,每个点1px或根2 px构成列表中的下一个点。您需要使用Schnider在Graphics Gems(Gems 1,pp 612,一种算法来拟合数字曲线)中使用平滑的三次Bezier路径。
沿着曲线的步骤采取始终为子像素的微小步骤,和 使用
取曲率double BezierCurve::Curvature(double t) const
{
// Nice mathematically perfect formula
//Vector2 d1 = Tangent(t);
//Vector2 d2 = Deriv2(t);
//return (d1.x * d2.y - d1.y * d2.x) / pow(d1.x * d1.x + d1.y * d1.y, 1.5);
// Get the cubic coefficients like this, I store them in the Bezier
// class
/*
a = p3 + 3.0 * p1 - 3.0 * p2 - p0;
b = 3.0 * p0 - 6.0 * p1 + 3.0 * p2;
c = 3.0 * p1 - 3.0 * p0;
d = p0;
*/
double dx, dy, ddx, ddy;
dx = 3 * this->ax * t*t + 2 * this->bx * t + this->cx;
ddx = 6 * this->ax * t + 2 * this->bx;
dy = 3 * this->ay * t*t + 2 * this->by * t + this->cy;
ddy = 6 * this->ay * t + 2 * this->by;
if (dx == 0 && dy == 0)
return 0;
return (dx*ddy - ddx*dy) / ((dx*dx + dy*dy)*sqrt(dx*dx + dy*dy));
}
答案 1 :(得分:0)
与mode = CV_RETR_EXTERNAL和method = CV_CHAIN_APPROX_NONE一起使用的OpenCV findContours
将为您提供所有有序的边界像素,例如两个后续点是邻居。
要获得圆周半径三个点,Web中有很多信息。因为您只需要半径而不是中心,this stackexchange answer很快。
在伪代码中:
vector_of_points = OpenCV::findContours(...)
p1 = vector start
p2, p3 are next points in vector
//boundary is circular, so in the first loop pass we must adjust
p2 = next point
p3 = last point
//Use p1 as our iterator
while ( p1 <= vector.end )
{
//curvature
radius = calculateRadius(p1, p2, p3)
//set color for pixel p2
setColor(p, radius)
increment p1, p2, p3
adjust for start point = end point
}