一、Catmull_Rom样条曲线模型引入
Catmull_Rom样条曲线拟合是曲线插值技术的一种,该插值技术能经过所给的所有控制点。BY THE WAY,很多插值技术可以参考http://www.cnblogs.com/WhyEngine/p/4020390.html
Catmull_Rom样条曲线拟合方法需要至少四个控制点,公式如下:
其中,t属于[0,1](也就是0-1中每个t值可能对应所求曲线中的某点,其取值越多,曲线越密)。实际上,四个控制点,曲线只会经过其中两个控制点,如现在有控制点A,B,C,D,则最后的曲线拟合结果将如下:
得到的事BC之间的拟合曲线。那么若要得到ABCD的拟合曲线应该怎么办呢。实际上,引入两个新的控制点A',D'即可,A'由AB计算而得,D'由CD计算而得,例如,A'计算如下:
A'.x = A.x + (A.x - B.x)
A'.y = A.y + (A.y - B.y)
B'点计算类似。于是,由A'ABC可以得到AB曲线,由ABCD可以得到BC曲线,由BCDD'可以得到CD曲线,经过三次计算,可以得到ABCD曲线。
在一张空白图上,计算经过(50,50),(90,120),(70,200)三点的Catmull_Rom样条曲线,程序如下:
IplImage* img = cvCreateImage(cvSize(300,300), 8, 1); for (int i = 0; i < img->height; ++i) { for (int j = 0; j < img->width; ++j) { ((char *)(img->imageData + img->widthStep * (i)))[j] = 0; } } CvPoint point0,point1,point2,point3,point4;//3个控制点来做 point1.x = 50; point1.y = 50; point2.x = 90; point2.y = 120; point3.x = 70; point3.y = 200; point0.x = point1.x+(point1.x-point2.x); point0.y = point1.y+(point1.y-point2.y); point4.x = point3.x+(point3.x-point2.x); point4.y = point3.y+(point3.y-point2.y); ((char *)(img->imageData + img->widthStep * (point1.y)))[point1.x] = 255; ((char *)(img->imageData + img->widthStep * (point2.y)))[point2.x] = 255; ((char *)(img->imageData + img->widthStep * (point3.y)))[point3.x] = 255; for (int i = 1; i < 500 ; i++) { float t = (float) i * (1.0f / (float) 500); float tt = t * t; float ttt = tt * t; CvPoint pi; pi.x = 0.5 * (2*point1.x+(point2.x-point0.x)*t + (2*point0.x-5*point1.x+4*point2.x-point3.x)*tt + (3*point1.x-point0.x-3*point2.x+point3.x)*ttt); pi.y = 0.5 * (2*point1.y+(point2.y-point0.y)*t + (2*point0.y-5*point1.y+4*point2.y-point3.y)*tt + (3*point1.y-point0.y-3*point2.y+point3.y)*ttt); ((char *)(img->imageData + img->widthStep * (pi.y)))[pi.x] = 255; } for (int i = 1; i < 500 ; i++) { float t = (float) i * (1.0f / (float) 500); float tt = t * t; float ttt = tt * t; CvPoint pi; pi.x = 0.5 * (2*point2.x+(point3.x-point1.x)*t + (2*point1.x-5*point2.x+4*point3.x-point4.x)*tt + (3*point2.x-point1.x-3*point3.x+point4.x)*ttt); pi.y = 0.5 * (2*point2.y+(point3.y-point1.y)*t + (2*point1.y-5*point2.y+4*point3.y-point4.y)*tt + (3*point2.y-point1.y-3*point3.y+point4.y)*ttt); ((char *)(img->imageData + img->widthStep * (pi.y)))[pi.x] = 255; } cvShowImage("scr", img); cvWaitKey(0); return 0;
得到结果:
拟合效果较好。
二、基于Catmull_Rom样条曲线的车道线检测
2.1 基本思路
为了更好地模拟车道线情况,给出下图进行模拟实验:
模拟情形1 模拟情形2
有了Catmull_Rom样条曲线的基础,那么车道线检测实际上就是找到合适的控制点!
给出基于Catmull_Rom样条曲线的车道线检测的基本方法(除去预处理过程):
参考:《基于Catmull-Rom 样条曲线的弯曲车道线检测研究,何 鹏,高 峰,魏厚敏》
(1)Hough变换直线检测,将两条主车道线检测出来,直线记为L1,L2;
(2)判断是车道线是直线还是曲线;
(3)若车道线是曲线,找到三个控制点P1,P2,P3;
(4)通过三个控制点,拟合Catmull_Rom样条曲线,得到结果
结束
2.2 具体实现
(1)Hough变换直线检测:
首先,我们要将曲线车道线分为两个部分,一个是直线部分,一个是曲线部分,如下图,直线部分在近区域端,看作是主车道线。
对主车道线进行直线检测,为了避免角度偏差过大的误检,我们限定检测的角度范围为0°- 70°以及130°- 180°。(可以看到误检曲线角度往往在90°附近)
(可能的误检情况,绿色线代表误检线)
进行角度限制的Hough变换检测直线,得到结果:
(2)判断直线还是曲线:
若是直线,那么Hough变换检测的结果应该和实际直线吻合;而若是曲线,那么,由(1)中可知,Hough变换实际上检测的是直线部分,而曲线部分则会漏检。
直线检测吻合 曲线检测漏检
按照此特性,若从上往下检测(即从(x = 0,y = 0)开始 x++,y++到(x = w,y = h)),直线的Hough检测结果将会基本吻合实际结果,即在检测结果点的周围,都将有实际点的存在;而曲线的Hough检测结果,将会先出现检测结果周围没有实际点,直到上图P3点后,检测结果点周围才会有实际点存在。
定义:1>.检测结果点吻合:若检测点周围八领域内存在实际点,则代表检测点结果吻合
于是该问题转化为:从图顶向下搜索,能否找到P3点,使得P3点上部分一段区域(给定一个长度阈值alph1)检测结果点都不吻合(引入容错因子,防止噪声theta),P3点下部分一段区域(同样给定一个长度阈值alph2)检测结果点吻合。若能找到P3点,则该车道线是曲线,否则,该车道线是直线!
(3)找到控制点P1,P2,P3:
P3控制点:实际上,步骤(2)中已经找到了其中一个控制点P3,P3点可以作为直线部分和曲线部分的分界点,P3以上部分拟合曲线,P3一下部分保留Hough变换的直线检测结果;
P1控制点:我们注意到,可以取远端两车道的消失点作为控制点P1。
具体搜索方法:
1>找到Hough变换得到的两直线的交点O。
2>从O点所在行向下搜索,找到P1。(从左往右搜索,第一个遇到的点即为P1点)
P2控制点:得到了P1,P3两点,则取P1,P3中间的一行搜索两车道的P2点!
得到结果:
(4)经过三个控制点P1,2,3,使用Catmull_Rom样条曲线拟合得到结果:
结论:
(1)从结果上来看,能得到曲线,拟合效果并不是很好,但是提升空间很大,比如增多控制点会让曲线拟合更为精准!
(2)控制点寻找的方法仍需要斟酌,因为道路的情况及其复杂,所以需要针对可想的所有情况进行模拟!
接下来,将继续实验
相关推荐
catmull-rom样条插值算法1
Android使用Catmull_Rom插值算法画光滑曲线图源代码
Catmull-Rom 样条算法实现,支持1~N维算法。
需要有opengl,如何配置opengl请自行...利用B-Spline插值和Catmull-Rom插值实现物体的移动,物体的旋转由欧拉角或者四元数实现。 在Visual C++上实现的 效果视频请点击:https://www.youtube.com/watch?v=I2FgyMXiZvk
为了较好地保持图像的边缘信息, 提出一种基于Canny边缘检测的Catmull-Rom图像插值放大算法。首先用Canny算子检测出原图像的边缘; 然后, 根据插值目标图像未知像素点时, 目标图像与原图像的相似性, 如果未知像素点为...
该程序为沿用户编辑的 Catmull-Rom 样条线加速的球设置动画。 沿多段曲线的距离由弧长参数化。
实验内容:给出任意四个控制点,绘一条穿过所有的曲线,采用Catmull-Rom曲线。
针对图像高倍放大易出现block现象,文章构造了一类5次的Catmull-Rom样条用于图像放大,取得了较为满意的效果;与3次Catmull-Rom样条具有C1连续的性质相比,所构造的5次Catmull-Rom样条在不增加插值节点情况下达到C2...
Cardinal(Catmull-Rom) 使用统一参数化对给定的四个控制点进行样条插值。 每个控制点都可以是 N 维欧几里得空间。 ---------------------------------- 还给出了一个简单的测试程序 (main.m) 来执行给定数据的 1D、...
曲线编辑器要求C++11 和 freeglut ##Controls 通过在按住以下键之一的同时单击来绘制曲线: p:折线b:贝塞尔曲线r:Catmull-Rom 样条l:拉格朗日曲线单击要选择的曲线。 拖动曲线移动。 按住 'a' 将点添加到所选...
catmull-rom实现
Catmull Rom样条插值变得容易。 安装 $ npm install --save cat-rom-spline 用法 var catRomSpline = require ( 'cat-rom-spline' ) ; // Points are arrays in the form of [x, y] var p0 = [ 0 , 0 ] ; var p1 = ...
catmull_rom
使用B样条线和Catmull Rom样条线,因为它们允许对控制参数施加简单约束。然后将这种新的自适应函数应用于线性自适应滤波器的输出,并将其用于维纳型非线性系统的辨识。此外,我们推导了自适应算法的一种简单形式和...
Example % Generate random nodes x = rand(4,2); % Interpolate different splines a = cspl(x); b = cspl(x,[],0.25); c = cspl(x,[],0.5);...legend 'Centripetal (0)' 'Cardinal (0.25)' 'Cardinal (0.50)' 'Random...
CatmullRomSpline模块 对于您的Catmull-Rom样条曲线的所有需求。 唯一的依赖关系是t。
它使用向心Catmull-Rom样条绘制边界,分割后的边界可以很容易地进行编辑。 . 在附件中,我们使用了主动样条模型来自动分割前后肺 X 射线。 此外,我们提供了所有必要的代码来训练模型,并以眼热成像为例来做到这...
它使用向心Catmull-Rom样条绘制边界,分割后的边界可以很容易地进行编辑。 . 在附件中,我们使用了主动样条模型来自动分割前后肺 X 射线。 此外,我们提供了所有必要的代码来训练模型,并以眼热成像为例来做到这...
一个lib,用于在n维的三次基数/ Catmull-Rom样条曲线上进行插值。 安装 npm install --save curve-interpolator 基本用法 引用CurveInterpolator类: // commonjs const CurveInterpolator = require ( 'curve-...
Bezier_Bspline_Catmull_Rom曲线拟合