道格拉斯-普克抽稀算法 曲線平滑

  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;
}

//==============================

發佈了138 篇原創文章 · 獲贊 9 · 訪問量 102萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章