道格拉斯-普克抽稀算法 曲线平滑
2015-06-27 14:26
465 查看
switch(m_SmoothMode)
{
case 0: //三点线性
for(i=2+offsetpos;i<datanum-2;i++)
{
m_pfDataArray[i] = (m_pfDataArray[i-1]+m_pfDataArray[i]+m_pfDataArray[i+1])/3;
}
break;
case 1://五点二次滤波
for(i=2+offsetpos;i<datanum-2;i++)
{
m_pfDataArray[i] = (12*(m_pfDataArray[i-1]+m_pfDataArray[i+1])
-3*(m_pfDataArray[i-2]+m_pfDataArray[i+2])
+17*m_pfDataArray[i])/35;
}
break;
case 2://三点钟形滤波
for(i=2+offsetpos;i<datanum-2;i++)
{
m_pfDataArray[i] = (short)(0.212f*m_pfDataArray[i-1]+0.576f*m_pfDataArray[i]
+0.212f*m_pfDataArray[i+1]);
}
break;
case 3://五点钟形滤波
for(i=2+offsetpos;i<datanum-2;i++)
{
m_pfDataArray[i] = (short)(0.11f*(m_pfDataArray[i-2]+m_pfDataArray[i+2])
+0.24f*(m_pfDataArray[i-1]+m_pfDataArray[i+1])
+0.3f*m_pfDataArray[i]);
}
break;
case 4://三点汉明滤波
for(i=2+offsetpos;i<datanum-2;i++)
{
m_pfDataArray[i] = (short)(0.07f*m_pfDataArray[i-1]+0.86f*m_pfDataArray[i]
+0.07f*m_pfDataArray[i+1]);
}
break;
default://五点汉明滤波
for(i=2+offsetpos;i<datanum-2;i++)
{
m_pfDataArray[i] = (short)(0.04f*(m_pfDataArray[i-2]+m_pfDataArray[i+2])
+0.24f*(m_pfDataArray[i-1]+m_pfDataArray[i+1])
+0.44f*m_pfDataArray[i]);
}
break;
}
道格拉斯-普克抽稀算法
道格拉斯-普克抽稀算法,是用来对大量冗余的图形数据点进行压缩以提取必要的数据点。该算法实现抽稀的过程是:先将一条曲线首尾点虚连一条直线,求其余各点到该直线的距离,取其最大者与规定的临界值相比较,若小于临界值,则将直线两端间各点全部舍去,否则将离该直线距离最大的点保留,并将原线条分成两部分,对每部分线条再实施该抽稀过程,直到结束。抽稀结果点数随选取限差临界值的增大而减少,应用时应根据精度来选取限差临界值,以获得最好的效果。
--------------------------------------------------------------------------
以下转载自:垂距法与道格拉斯-普克法删除冗余顶点效率的比较
彭认灿 ,董 箭 ,郑义东 ,李改肖
(大连舰艇学院 海洋测绘工程系 ,辽宁 大连 116018)
道格拉斯- 普克法可描述为:将一条曲线首末顶点虚连一条直线 ,求出其余各顶点到该直线的距离 ,选其最大者与规定的限差相比较 ,若小于等于限差 ,则将直线两端间各点全部删去;若大于限差 ,则离该直线距离最大的顶点保留 ,并以此为界 ,把曲线分为两部分
,对这两部分重复使用上述方法 ,直至最终无法作进一步的压缩为止 (见图 3)。
道格拉斯 2 普克法有一个十分突出的优点 ,即它是一个整体算法 ,在一般情况下可保留较大弯曲形态上的特征点。经道格拉斯-普克法压缩后得到的图形如图 4所示。由于该算法可准确删除小弯曲上的定点 ,故能从体上有效地保持线要素的形态特征。正是因为道格拉斯-普克法具有这样突出的优点 ,所以已经在线要素地自动制图中得到了较广泛的应用。但道格拉斯- 普克法较垂距法复杂 ,且通常编程实现时需要采用递归方 ,有一定的难度。
----------------------------------------------------------转载end
此算法可以在获取手写笔顺的特征点时应用。
C++代码
//=================================================================================================================
double PerpendicularDistance(CPoint Point1, CPoint Point2, CPoint Point)
{
//Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)| *Area of triangle
//Base = v((x1-x2)2+(x1-x2)2) *Base of Triangle*
//Area = .5*Base*H *Solve for height
//Height = Area/.5/Base
double area = abs(0.5 * (Point1.x * Point2.y + Point2.x * Point.y + Point.x * Point1.y - Point2.x * Point1.y - Point.x * Point2.y - Point1.x * Point.y));
double bottom = sqrt(pow(Point1.x - Point2.x, 2) + pow(Point1.y - Point2.y, 2));
double height = area / bottom * 2;
return height;
}
void DouglasPeuckerReduction(vector<CPoint>points, int firstPoint, int lastPoint, double tolerance, list<int> &pointIndexsToKeep)
{
double maxDistance = 0;
int indexFarthest = 0;
for (int index = firstPoint; index < lastPoint; index++)
{
double distance = PerpendicularDistance
(points[firstPoint], points[lastPoint], points[index]);
if (distance > maxDistance)
{
maxDistance = distance;
indexFarthest = index;
}
}
if (maxDistance > tolerance && indexFarthest != 0)
{
//Add the largest point that exceeds the tolerance
pointIndexsToKeep.push_back(indexFarthest);
DouglasPeuckerReduction(points, firstPoint,
indexFarthest, tolerance, pointIndexsToKeep);
DouglasPeuckerReduction(points, indexFarthest,
lastPoint, tolerance, pointIndexsToKeep);
}
}
vector<CPoint> DouglasPeucker(vector<CPoint> &Points, double Tolerance)
{
if (Points.empty() || (Points.size() < 3))
return Points;
int firstPoint = 0;
int lastPoint = Points.size() - 1;
list<int> pointIndexsToKeep ;
//Add the first and last index to the keepers
pointIndexsToKeep.push_back(firstPoint);
pointIndexsToKeep.push_back(lastPoint);
//The first and the last point cannot be the same
while (Points[firstPoint]==(Points[lastPoint]))
{
lastPoint--;
}
DouglasPeuckerReduction(Points, firstPoint, lastPoint,
Tolerance, pointIndexsToKeep);
vector<CPoint> returnPoints ;
pointIndexsToKeep.sort();
list<int>::iterator theIterator;
for( theIterator = pointIndexsToKeep.begin(); theIterator != pointIndexsToKeep.end(); theIterator++ )
{
returnPoints.push_back(Points[*theIterator]);
}
return returnPoints;
}
//==============================
matlab算法:
function curve = dp(pnts)
%dp点抽稀算法
clc;
close all;
clear all;
x = 1:0.01: 2;
num = size(x,2);
pnts = 2*sin(8*pi*x) ; % + rand(1,num)*0.8;
pnts = x .* sin(8*pi*x) + rand(1,num)*0.5;
figure; plot( x, pnts,'-.'); title('pnts');
head = [x(1), pnts(1)] ;
tail = [x(end), pnts(end)] ;
%距离阈值
dist_th = 0.1;
hold on;
max_dist = 0;
max_dist_i = 0;
%把起始点和终止点加进去
curve = [head; tail];
pnt_index = [1, num];
while(1)
%目前抽稀后的曲线上的点数
curve_num = size(curve,1);
%标记是否添加了新点,若有,表明还要继续处理
add_new_pnt = 0;
% 对区间头尾连线,然后计算各点到这条直线的距离
for nx = 1:curve_num-1
cur_pnt = curve(nx,:);
%下一个抽稀了的曲线上的点
next_pnt = curve(nx+1,:);
pnt_d = next_pnt - cur_pnt ;
th = atan2(pnt_d(2), pnt_d(1));
angle = th*180/pi;
%直线方程
% y = kx + b
k = tan(th);
b = cur_pnt(2) - k*cur_pnt(1);
k2 = k*k;
deno = sqrt(1 + k *k) ;
max_dist = 0;
pnt_index(nx);
pnt_index(nx+1);
%对这一区间的点计算到直线的距离
for i= pnt_index(nx) : pnt_index(nx+1)
dist = abs(pnts(i) - k*x(i) - b)/deno ;
if(dist> max_dist)
max_dist = dist;
max_dist_i = i;
end
end
max_dist;
max_dist_i;
far_pnt = [x(max_dist_i), pnts(max_dist_i)];
%最远的点加进去
if(max_dist > dist_th)
curve = [curve(1:nx,:); far_pnt; curve(nx+1:end,:)];
pnt_index = [pnt_index(1:nx), max_dist_i, pnt_index(nx+1:end)];
%标记添加了新点,可能还要继续处理
add_new_pnt = 1;
end
end
close all ;
figure; plot( x, pnts,'-.'); title('pnts');
hold on;
plot(curve(:,1), curve(:,2), '-g*');
drawnow;
%如果各点到直线距离都没有超过阈值则退出
%处理完毕了,ok了,退出
if(0 == add_new_pnt)
break;
end
end
{
case 0: //三点线性
for(i=2+offsetpos;i<datanum-2;i++)
{
m_pfDataArray[i] = (m_pfDataArray[i-1]+m_pfDataArray[i]+m_pfDataArray[i+1])/3;
}
break;
case 1://五点二次滤波
for(i=2+offsetpos;i<datanum-2;i++)
{
m_pfDataArray[i] = (12*(m_pfDataArray[i-1]+m_pfDataArray[i+1])
-3*(m_pfDataArray[i-2]+m_pfDataArray[i+2])
+17*m_pfDataArray[i])/35;
}
break;
case 2://三点钟形滤波
for(i=2+offsetpos;i<datanum-2;i++)
{
m_pfDataArray[i] = (short)(0.212f*m_pfDataArray[i-1]+0.576f*m_pfDataArray[i]
+0.212f*m_pfDataArray[i+1]);
}
break;
case 3://五点钟形滤波
for(i=2+offsetpos;i<datanum-2;i++)
{
m_pfDataArray[i] = (short)(0.11f*(m_pfDataArray[i-2]+m_pfDataArray[i+2])
+0.24f*(m_pfDataArray[i-1]+m_pfDataArray[i+1])
+0.3f*m_pfDataArray[i]);
}
break;
case 4://三点汉明滤波
for(i=2+offsetpos;i<datanum-2;i++)
{
m_pfDataArray[i] = (short)(0.07f*m_pfDataArray[i-1]+0.86f*m_pfDataArray[i]
+0.07f*m_pfDataArray[i+1]);
}
break;
default://五点汉明滤波
for(i=2+offsetpos;i<datanum-2;i++)
{
m_pfDataArray[i] = (short)(0.04f*(m_pfDataArray[i-2]+m_pfDataArray[i+2])
+0.24f*(m_pfDataArray[i-1]+m_pfDataArray[i+1])
+0.44f*m_pfDataArray[i]);
}
break;
}
道格拉斯-普克抽稀算法
道格拉斯-普克抽稀算法,是用来对大量冗余的图形数据点进行压缩以提取必要的数据点。该算法实现抽稀的过程是:先将一条曲线首尾点虚连一条直线,求其余各点到该直线的距离,取其最大者与规定的临界值相比较,若小于临界值,则将直线两端间各点全部舍去,否则将离该直线距离最大的点保留,并将原线条分成两部分,对每部分线条再实施该抽稀过程,直到结束。抽稀结果点数随选取限差临界值的增大而减少,应用时应根据精度来选取限差临界值,以获得最好的效果。
--------------------------------------------------------------------------
以下转载自:垂距法与道格拉斯-普克法删除冗余顶点效率的比较
彭认灿 ,董 箭 ,郑义东 ,李改肖
(大连舰艇学院 海洋测绘工程系 ,辽宁 大连 116018)
道格拉斯- 普克法可描述为:将一条曲线首末顶点虚连一条直线 ,求出其余各顶点到该直线的距离 ,选其最大者与规定的限差相比较 ,若小于等于限差 ,则将直线两端间各点全部删去;若大于限差 ,则离该直线距离最大的顶点保留 ,并以此为界 ,把曲线分为两部分
,对这两部分重复使用上述方法 ,直至最终无法作进一步的压缩为止 (见图 3)。
道格拉斯 2 普克法有一个十分突出的优点 ,即它是一个整体算法 ,在一般情况下可保留较大弯曲形态上的特征点。经道格拉斯-普克法压缩后得到的图形如图 4所示。由于该算法可准确删除小弯曲上的定点 ,故能从体上有效地保持线要素的形态特征。正是因为道格拉斯-普克法具有这样突出的优点 ,所以已经在线要素地自动制图中得到了较广泛的应用。但道格拉斯- 普克法较垂距法复杂 ,且通常编程实现时需要采用递归方 ,有一定的难度。
----------------------------------------------------------转载end
此算法可以在获取手写笔顺的特征点时应用。
C++代码
//=================================================================================================================
double PerpendicularDistance(CPoint Point1, CPoint Point2, CPoint Point)
{
//Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)| *Area of triangle
//Base = v((x1-x2)2+(x1-x2)2) *Base of Triangle*
//Area = .5*Base*H *Solve for height
//Height = Area/.5/Base
double area = abs(0.5 * (Point1.x * Point2.y + Point2.x * Point.y + Point.x * Point1.y - Point2.x * Point1.y - Point.x * Point2.y - Point1.x * Point.y));
double bottom = sqrt(pow(Point1.x - Point2.x, 2) + pow(Point1.y - Point2.y, 2));
double height = area / bottom * 2;
return height;
}
void DouglasPeuckerReduction(vector<CPoint>points, int firstPoint, int lastPoint, double tolerance, list<int> &pointIndexsToKeep)
{
double maxDistance = 0;
int indexFarthest = 0;
for (int index = firstPoint; index < lastPoint; index++)
{
double distance = PerpendicularDistance
(points[firstPoint], points[lastPoint], points[index]);
if (distance > maxDistance)
{
maxDistance = distance;
indexFarthest = index;
}
}
if (maxDistance > tolerance && indexFarthest != 0)
{
//Add the largest point that exceeds the tolerance
pointIndexsToKeep.push_back(indexFarthest);
DouglasPeuckerReduction(points, firstPoint,
indexFarthest, tolerance, pointIndexsToKeep);
DouglasPeuckerReduction(points, indexFarthest,
lastPoint, tolerance, pointIndexsToKeep);
}
}
vector<CPoint> DouglasPeucker(vector<CPoint> &Points, double Tolerance)
{
if (Points.empty() || (Points.size() < 3))
return Points;
int firstPoint = 0;
int lastPoint = Points.size() - 1;
list<int> pointIndexsToKeep ;
//Add the first and last index to the keepers
pointIndexsToKeep.push_back(firstPoint);
pointIndexsToKeep.push_back(lastPoint);
//The first and the last point cannot be the same
while (Points[firstPoint]==(Points[lastPoint]))
{
lastPoint--;
}
DouglasPeuckerReduction(Points, firstPoint, lastPoint,
Tolerance, pointIndexsToKeep);
vector<CPoint> returnPoints ;
pointIndexsToKeep.sort();
list<int>::iterator theIterator;
for( theIterator = pointIndexsToKeep.begin(); theIterator != pointIndexsToKeep.end(); theIterator++ )
{
returnPoints.push_back(Points[*theIterator]);
}
return returnPoints;
}
//==============================
matlab算法:
function curve = dp(pnts)
%dp点抽稀算法
clc;
close all;
clear all;
x = 1:0.01: 2;
num = size(x,2);
pnts = 2*sin(8*pi*x) ; % + rand(1,num)*0.8;
pnts = x .* sin(8*pi*x) + rand(1,num)*0.5;
figure; plot( x, pnts,'-.'); title('pnts');
head = [x(1), pnts(1)] ;
tail = [x(end), pnts(end)] ;
%距离阈值
dist_th = 0.1;
hold on;
max_dist = 0;
max_dist_i = 0;
%把起始点和终止点加进去
curve = [head; tail];
pnt_index = [1, num];
while(1)
%目前抽稀后的曲线上的点数
curve_num = size(curve,1);
%标记是否添加了新点,若有,表明还要继续处理
add_new_pnt = 0;
% 对区间头尾连线,然后计算各点到这条直线的距离
for nx = 1:curve_num-1
cur_pnt = curve(nx,:);
%下一个抽稀了的曲线上的点
next_pnt = curve(nx+1,:);
pnt_d = next_pnt - cur_pnt ;
th = atan2(pnt_d(2), pnt_d(1));
angle = th*180/pi;
%直线方程
% y = kx + b
k = tan(th);
b = cur_pnt(2) - k*cur_pnt(1);
k2 = k*k;
deno = sqrt(1 + k *k) ;
max_dist = 0;
pnt_index(nx);
pnt_index(nx+1);
%对这一区间的点计算到直线的距离
for i= pnt_index(nx) : pnt_index(nx+1)
dist = abs(pnts(i) - k*x(i) - b)/deno ;
if(dist> max_dist)
max_dist = dist;
max_dist_i = i;
end
end
max_dist;
max_dist_i;
far_pnt = [x(max_dist_i), pnts(max_dist_i)];
%最远的点加进去
if(max_dist > dist_th)
curve = [curve(1:nx,:); far_pnt; curve(nx+1:end,:)];
pnt_index = [pnt_index(1:nx), max_dist_i, pnt_index(nx+1:end)];
%标记添加了新点,可能还要继续处理
add_new_pnt = 1;
end
end
close all ;
figure; plot( x, pnts,'-.'); title('pnts');
hold on;
plot(curve(:,1), curve(:,2), '-g*');
drawnow;
%如果各点到直线距离都没有超过阈值则退出
%处理完毕了,ok了,退出
if(0 == add_new_pnt)
break;
end
end
相关文章推荐
- Json数据解析详解
- IT软件人员的技术学习内容(写给技术迷茫中的你) - 项目管理系列文章
- 冒泡排序
- 选择排序
- 《Windows服务器配置与管理》------磁盘管理
- 统计机器学习笔记——感知机(1)
- 日语学习之沪江N3基础 20150627 -7
- cocos2dx-3.3 网络编程(CURL+PHP) NO.1 写好PHP代码
- 项目笔记:5.利用nginx七层分发器实现基于内容的分发
- ruby-Hash
- Java数据结构 Collections的一些方法介绍
- 建立名称服务器
- 微信支付趟过的坑
- head&&tail
- K-means算法Java实现
- TextView 多文字字体颜色及多事件监听
- 6.27 洗刷刷 oj 运算符重载 矩阵之和
- HDFS学习笔记(1)初探HDFS
- 闲聊
- Windows服务器配置与管理------远程桌面管理