日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Cv中文參考手冊之二------圖像輪廓處理

 昵稱13859582 2013-09-12

Cv中文參考手冊之二 - Cv結(jié)構(gòu)分析

下面的鏈接是OPENCV之CV部分用戶參考手冊的中文翻譯,在此感謝Z.M.Zhang對模式識別、照相機定標與三維重建部分所做的翻譯,Y.C.WEI對全文做了統(tǒng)一細致的更改

Cv結(jié)構(gòu)分析

 

目錄

輪廓處理函數(shù)

ApproxChains

用多邊形曲線逼近 Freeman 鏈

CvSeq* cvApproxChains( CvSeq* src_seq, CvMemStorage* storage,
                       int method=CV_CHAIN_APPROX_SIMPLE,
                       double parameter=0, int minimal_perimeter=0, int recursive=0 );
    src_seq
  • 涉及其它鏈的鏈指針

  • storage
  • 存儲多邊形線段位置的緩存

  • method
  • 逼近方法 (見函數(shù) cvFindContours 的描述).

  • parameter
  • 方法參數(shù)(現(xiàn)在不用).

  • minimal_perimeter
  • 僅逼近周長大于 minimal_perimeter 輪廓。其它的鏈從結(jié)果中除去。

  • recursive
  • 如果非 0, 函數(shù)從 src_seq 中利用 h_next 和 v_next links 連接逼近所有可訪問的鏈。如果為 0, 則僅逼近單鏈。

這是一個單獨的逼近程序。 對同樣的逼近標識,函數(shù) cvApproxChains 與 cvFindContours 的工作方式一模一樣。它返回發(fā)現(xiàn)的第一個輪廓的指針。其它的逼近模塊,可以用返回結(jié)構(gòu)中的 v_next 和 v_next 域來訪問

StartReadChainPoints

初始化鏈讀取

void cvStartReadChainPoints( CvChain* chain, CvChainPtReader* reader );
    chain
  • 鏈的指針

    reader
  • 鏈的讀取狀態(tài)

函數(shù) cvStartReadChainPoints 初始化一個特殊的讀取器 (參考 Dynamic Data Structures 以獲得關(guān)于集合與序列的更多內(nèi)容).

ReadChainPoint

得到下一個鏈的點

CvPoint cvReadChainPoint( CvChainPtReader* reader );
    reader
  • 鏈的讀取狀態(tài)

函數(shù) cvReadChainPoint 返回當前鏈的點,并且更新讀取位置。

ApproxPoly

用指定精度逼近多邊形曲線

CvSeq* cvApproxPoly( const void* src_seq, int header_size, CvMemStorage* storage,
                     int method, double parameter, int parameter2=0 );
    src_seq
  • 點集數(shù)組序列

  • header_size
  • 逼近曲線的頭尺寸

  • storage
  • 逼近輪廓的容器。如果為 NULL, 則使用輸入的序列

  • method
  • 逼近方法。目前僅支持 CV_POLY_APPROX_DP , 對應(yīng) Douglas-Peucker 算法.

  • parameter
  • 方法相關(guān)參數(shù)。對 CV_POLY_APPROX_DP 它是指定的逼近精度

  • parameter2
  • 如果 src_seq 是序列,它表示要么逼近單個序列,要么在 src_seq 的同一個或低級層次上逼近所有序列 (參考 cvFindContours 中對輪廓繼承結(jié)構(gòu)的描述). 如果 src_seq 是點集的數(shù)組 (CvMat*) , 參數(shù)指定曲線是閉合 (parameter2!=0) 還是非閉合 (parameter2=0).

函數(shù) cvApproxPoly 逼近一個或多個曲線,并返回逼近結(jié)果。對多個曲線的逼近,生成的樹將與輸入的具有同樣的結(jié)構(gòu)。(1:1 的對應(yīng)關(guān)系).

BoundingRect

計算點集的最外面(up-right)矩形邊界

CvRect cvBoundingRect( CvArr* points, int update=0 );
    points
  • 二維點集,點的序列或向量 (CvMat)

  • update
  • 更新標識。下面是輪廓類型和標識的一些可能組合:

    • update=0, contour ~ CvContour*: 不計算矩形邊界,但直接由輪廓頭的 rect 域得到。

    • update=1, contour ~ CvContour*: 計算矩形邊界,而且將結(jié)果寫入到輪廓頭的 rect 域中 header.

    • update=0, contour ~ CvSeq* or CvMat*: 計算并返回邊界矩形

    • update=1, contour ~ CvSeq* or CvMat*: 產(chǎn)生運行錯誤 (runtime error is raised)

函數(shù) cvBoundingRect 返回二維點集的最外面 (up-right)矩形邊界。

ContourArea

計算整個輪廓或部分輪廓的面積

double cvContourArea( const CvArr* contour, CvSlice slice=CV_WHOLE_SEQ );
    contour
  • 輪廓 (邊界點的序列或數(shù)組).

  • slice
  • 感興趣輪廓部分的起始點,缺省是計算整個輪廓的面積。

函數(shù) cvContourArea 計算整個輪廓或部分輪廓的面積。 對后面的情況,面積表示輪廓部分和起始點連線構(gòu)成的封閉部分的面積。如下圖所示:

Image:Contoursecarea.png

備注: 輪廓的方向影響面積的符號。因此函數(shù)也許會返回負的結(jié)果。應(yīng)用函數(shù) fabs() 得到面積的絕對值。

ArcLength

計算輪廓周長或曲線長度

double cvArcLength( const void* curve, CvSlice slice=CV_WHOLE_SEQ, int is_closed=-1 );
    curve
  • 曲線點集序列或數(shù)組

  • slice
  • 曲線的起始點,缺省是計算整個曲線的長度

  • is_closed
  • 表示曲線是否閉合,有三種情況:

    • is_closed=0 - 假設(shè)曲線不閉合

    • is_closed>0 - 假設(shè)曲線閉合

    • is_closed<0 - 若曲線是序列,檢查 ((CvSeq*)curve)->flags 中的標識 CV_SEQ_FLAG_CLOSED 來確定曲線是否閉合。否則 (曲線由點集的數(shù)組 (CvMat*) 表示) 假設(shè)曲線不閉合。

函數(shù) cvArcLength 通過依次計算序列點之間的線段長度,并求和來得到曲線的長度。

CreateContourTree

創(chuàng)建輪廓的繼承表示形式

CvContourTree* cvCreateContourTree( const CvSeq* contour, CvMemStorage* storage, double threshold );
    contour
  • 輸入的輪廓

  • storage
  • 輸出樹的容器

  • threshold
  • 逼近精度

函數(shù) cvCreateContourTree 為輸入輪廓 contour 創(chuàng)建一個二叉樹,并返回樹根的指針。如果參數(shù) threshold 小于或等于 0 ,則函數(shù)創(chuàng)建一個完整的二叉樹。如果 threshold 大于 0 , 函數(shù)用 threshold 指定的精度創(chuàng)建二叉樹:如果基線的截斷區(qū)域頂點小于threshold,該數(shù)就停止生長并作為函數(shù)的最終結(jié)果返回。

ContourFromContourTree

由樹恢復(fù)輪廓

CvSeq* cvContourFromContourTree( const CvContourTree* tree, CvMemStorage* storage,
                                 CvTermCriteria criteria );
    tree
  • 輪廓樹

  • storage
  • 重構(gòu)的輪廓容器

  • criteria
  • 停止重構(gòu)的準則

函數(shù) cvContourFromContourTree 從二叉樹恢復(fù)輪廓。參數(shù) criteria 決定了重構(gòu)的精度和使用樹的數(shù)目及層次。所以它可建立逼近的輪廓。 函數(shù)返回重構(gòu)的輪廓。

MatchContourTrees

用樹的形式比較兩個輪廓

double cvMatchContourTrees( const CvContourTree* tree1, const CvContourTree* tree2,
                            int method, double threshold );
    tree1
  • 第一個輪廓樹

  • tree2
  • 第二個輪廓樹

  • method
  • 相似度。僅支持 CV_CONTOUR_TREES_MATCH_I1 。

  • threshold
  • 相似度閾值

函數(shù) cvMatchContourTrees 計算兩個輪廓樹的匹配值。從樹根開始通過逐層比較來計算相似度。如果某層的相似度小于 threshold, 則中斷比較過程,且返回當前的差值。

計算幾何

MaxRect

對兩個給定矩形,尋找矩形邊界

CvRect cvMaxRect( const CvRect* rect1, const CvRect* rect2 );
    rect1
  • 第一個矩形

  • rect2
  • 第二個矩形

函數(shù) cvMaxRect 尋找包含兩個輸入矩形的具有最小面積的矩形邊界。

Image:Maxrect.png

CvBox2D

旋轉(zhuǎn)的二維盒子

typedef struct CvBox2D
{
    CvPoint2D32f center;  /* 盒子的中心 */
    CvSize2D32f  size;    /* 盒子的長和寬 */
    float angle;          /* 水平軸與第一個邊的夾角,用角度度表示*/
}
CvBox2D;

PointSeqFromMat

從點向量中初始化點序列頭部

CvSeq* cvPointSeqFromMat( int seq_kind, const CvArr* mat,
                          CvContour* contour_header,
                          CvSeqBlock* block );
    seq_kind

點序列的類型:一系列點(0),曲線(CV_SEQ_KIND_CURVE),封閉曲線(CV_SEQ_KIND_CURVE+CV_SEQ_FLAG_CLOSED) 等等。

    mat
  • 輸入矩陣。輸入應(yīng)該是連續(xù)的一維點向量,類型也應(yīng)該是CV_32SC2或者CV_32FC2.

  • contour_header
  • 輪廓頭部,被函數(shù)初始化。

  • block
  • 序列塊頭部,被函數(shù)初始化。

函數(shù)cvPointSeqFromMat 初始化序列頭部,用來創(chuàng)建一個將給定矩陣中的元素形成的"虛擬"序列。沒有數(shù)據(jù)被拷貝。被初始化的頭部可以傳遞給其他任何包含輸入點序列的函數(shù)。沒有額外的元素加入序列,但是一些可能被移除。函數(shù)是cvMakeSeqHeaderForArray 的一個特別的變量,然后在內(nèi)部使用。它返回初始化頭部的指針。需要注意的是,包含的邊界矩形(CvContour 的rect字段)沒有被初始化,如果你需要使用,需要自己調(diào)用cvBoundingRect。

以下是使用例子。

CvContour header;
CvSeqBlock block;
CvMat* vector = cvCreateMat( 1, 3, CV_32SC2 );

CV_MAT_ELEM( *vector, CvPoint, 0, 0 ) = cvPoint(100,100);
CV_MAT_ELEM( *vector, CvPoint, 0, 1 ) = cvPoint(100,200);
CV_MAT_ELEM( *vector, CvPoint, 0, 2 ) = cvPoint(200,100);

IplImage* img = cvCreateImage( cvSize(300,300), 8, 3 );
cvZero(img);

cvDrawContours( img, cvPointSeqFromMat(CV_SEQ_KIND_CURVE+CV_SEQ_FLAG_CLOSED,
   vector, &header, &block), CV_RGB(255,0,0), CV_RGB(255,0,0), 0, 3, 8, cvPoint(0,0));

BoxPoints

尋找盒子的頂點

void cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] );
    box
  • 盒子

  • pt
  • 頂點數(shù)組

函數(shù) cvBoxPoints 計算輸入的二維盒子的頂點。下面是函數(shù)代碼:

void cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] )
{
    double angle = box.angle*CV_PI/180.
    float a = (float)cos(angle)*0.5f;
    float b = (float)sin(angle)*0.5f;

    pt[0].x = box.center.x - a*box.size.height - b*box.size.width;
    pt[0].y = box.center.y + b*box.size.height - a*box.size.width;
    pt[1].x = box.center.x + a*box.size.height - b*box.size.width;
    pt[1].y = box.center.y - b*box.size.height - a*box.size.width;
    pt[2].x = 2*box.center.x - pt[0].x;
    pt[2].y = 2*box.center.y - pt[0].y;
    pt[3].x = 2*box.center.x - pt[1].x;
    pt[3].y = 2*box.center.y - pt[1].y;
}

FitEllipse

二維點集的橢圓擬合

CvBox2D cvFitEllipse2( const CvArr* points );
    points
  • 點集的序列或數(shù)組

函數(shù) cvFitEllipse 對給定的一組二維點集作橢圓的最佳擬合(最小二乘意義上的)。返回的結(jié)構(gòu)與 cvEllipse 中的意義類似,除了 size 表示橢圓軸的整個長度,而不是一半長度。

FitLine

2D 或 3D 點集的直線擬合

void  cvFitLine( const CvArr* points, int dist_type, double param,
                 double reps, double aeps, float* line );
    points
  • 2D 或 3D 點集,32-比特整數(shù)或浮點數(shù)坐標

  • dist_type
  • 擬合的距離類型 (見討論).

  • param
  • 對某些距離的數(shù)字參數(shù),如果是 0, 則選擇某些最優(yōu)值

  • reps, aeps
  • 半徑 (坐標原點到直線的距離) 和角度的精度,一般設(shè)為0.01。

  • line
  • 輸出的直線參數(shù)。2D 擬合情況下,它是包含 4 個浮點數(shù)的數(shù)組 (vx, vy, x0, y0),其中 (vx, vy) 是線的單位向量而 (x0, y0) 是線上的某個點. 對 3D 擬合,它是包含 6 個浮點數(shù)的數(shù)組 (vx, vy, vz, x0, y0, z0), 其中 (vx, vy, vz) 是線的單位向量,而 (x0, y0, z0) 是線上某點。

函數(shù) cvFitLine 通過求 sumi:ρ(ri) 的最小值方法,用 2D 或 3D 點集擬合直線,其中 ri 是第 i 個點到直線的距離, ρ(r) 是下面的距離函數(shù)之一:

dist_type=CV_DIST_L2 (L2): ρ(r)=r2/2 (最簡單和最快的最小二乘法)

dist_type=CV_DIST_L1 (L1): ρ(r)=r

dist_type=CV_DIST_L12 (L1-L2): ρ(r)=2?[sqrt(1+r2/2) - 1]

dist_type=CV_DIST_FAIR (Fair): ρ(r)=C2?[r/C - log(1 + r/C)], C=1.3998

dist_type=CV_DIST_WELSCH (Welsch): ρ(r)=C2/2?[1 - exp(-(r/C)2)], C=2.9846

dist_type=CV_DIST_HUBER (Huber): ρ(r)= r2/2, if r < C; C?(r-C/2), otherwise; C=1.345

ConvexHull2

發(fā)現(xiàn)點集的凸外形

CvSeq* cvConvexHull2( const CvArr* input, void* hull_storage=NULL,
                      int orientation=CV_CLOCKWISE, int return_points=0 );
    points
  • 2D 點集的序列或數(shù)組,32-比特整數(shù)或浮點數(shù)坐標

  • hull_storage
  • 輸出的數(shù)組(CvMat*) 或內(nèi)存緩存 (CvMemStorage*),用以存儲凸外形。 如果是數(shù)組,則它應(yīng)該是一維的,而且與輸入的數(shù)組/序列具有同樣數(shù)目的元素。輸出時,通過修改頭結(jié)構(gòu)將數(shù)組裁減到凸外形的尺寸。

  • orientation
  • 凸外形的旋轉(zhuǎn)方向: 逆時針或順時針 (CV_CLOCKWISE or CV_COUNTER_CLOCKWISE)

  • return_points
  • 如果非零,hull_storage 為數(shù)組情況下,點集將以外形 (hull) 存儲,而不是頂點形式 (indices)。如果 hull_storag 為內(nèi)存存儲模式下則存儲為點集形式(points)。

函數(shù) cvConvexHull2 使用 Sklansky 算法計算 2D 點集的凸外形。如果 hull_storage 是內(nèi)存存儲倉, 函數(shù)根據(jù) return_points 的值,創(chuàng)建一個包含外形的點集或指向這些點的指針的序列。

例子. 由點集序列或數(shù)組創(chuàng)建凸外形

#include "cv.h"
#include "highgui.h"
#include <stdlib.h>

#define ARRAY  0 /* switch between array/sequence method by replacing 0<=>1 */

void main( int argc, char** argv )
{
    IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );
    cvNamedWindow( "hull", 1 );

#if !ARRAY
        CvMemStorage* storage = cvCreateMemStorage();
#endif

    for(;;)
    {
        int i, count = rand()%100 + 1, hullcount;
        CvPoint pt0;
#if !ARRAY
        CvSeq* ptseq = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour),
                                     sizeof(CvPoint), storage );
        CvSeq* hull;

        for( i = 0; i < count; i++ )
        {
            pt0.x = rand() % (img->width/2) + img->width/4;
            pt0.y = rand() % (img->height/2) + img->height/4;
            cvSeqPush( ptseq, &pt0 );
        }
        hull = cvConvexHull2( ptseq, 0, CV_CLOCKWISE, 0 );
        hullcount = hull->total;
#else
        CvPoint* points = (CvPoint*)malloc( count * sizeof(points[0]));
        int* hull = (int*)malloc( count * sizeof(hull[0]));
        CvMat point_mat = cvMat( 1, count, CV_32SC2, points );
        CvMat hull_mat = cvMat( 1, count, CV_32SC1, hull );

        for( i = 0; i < count; i++ )
        {
            pt0.x = rand() % (img->width/2) + img->width/4;
            pt0.y = rand() % (img->height/2) + img->height/4;
            points[i] = pt0;
        }
        cvConvexHull2( &point_mat, &hull_mat, CV_CLOCKWISE, 0 );
        hullcount = hull_mat.cols;
#endif
        cvZero( img );
        for( i = 0; i < count; i++ )
        {
#if !ARRAY
            pt0 = *CV_GET_SEQ_ELEM( CvPoint, ptseq, i );
#else
            pt0 = points[i];
#endif
            cvCircle( img, pt0, 2, CV_RGB( 255, 0, 0 ), CV_FILLED );
        }

#if !ARRAY
        pt0 = **CV_GET_SEQ_ELEM( CvPoint*, hull, hullcount - 1 );
#else
        pt0 = points[hull[hullcount-1]];
#endif

        for( i = 0; i < hullcount; i++ )
        {
#if !ARRAY
            CvPoint pt = **CV_GET_SEQ_ELEM( CvPoint*, hull, i );
#else
            CvPoint pt = points[hull[i]];
#endif
            cvLine( img, pt0, pt, CV_RGB( 0, 255, 0 ));
            pt0 = pt;
        }

        cvShowImage( "hull", img );

        int key = cvWaitKey(0);
        if( key == 27 ) // 'ESC'
            break;

#if !ARRAY
        cvClearMemStorage( storage );
#else
        free( points );
        free( hull );
#endif
    }
}

CheckContourConvexity

測試輪廓的凸性

int cvCheckContourConvexity( const CvArr* contour );
    contour
  • 被測試輪廓 (點序列或數(shù)組).

函數(shù) cvCheckContourConvexity 輸入的輪廓是否為凸的。必須是簡單輪廓,比如沒有自交叉。

CvConvexityDefect

用來描述一個簡單輪廓凸性缺陷的結(jié)構(gòu)體

typedef struct CvConvexityDefect
{
    CvPoint* start; /* 缺陷開始的輪廓點 */
    CvPoint* end; /* 缺陷結(jié)束的輪廓點 */
    CvPoint* depth_point; /* 缺陷中距離凸形最遠的輪廓點(谷底) */
    float depth; /* 谷底距離凸形的深度*/
} CvConvexityDefect;

Picture. 手部輪廓的凸形缺陷.

Image:Defects.png

ConvexityDefects

發(fā)現(xiàn)輪廓凸形缺陷

CvSeq* cvConvexityDefects( const CvArr* contour, const CvArr* convexhull,
                           CvMemStorage* storage=NULL );
    contour
  • 輸入輪廓

  • convexhull
  • 用 cvConvexHull2 得到的凸外形,它應(yīng)該包含輪廓的定點的指針或下標,而不是外形點的本身,即cvConvexHull2 中的參數(shù) return_points 應(yīng)該設(shè)置為 0.

  • storage
  • 凸性缺陷的輸出序列容器。如果為 NULL, 使用輪廓或外形的存儲倉。

函數(shù) cvConvexityDefects 發(fā)現(xiàn)輸入輪廓的所有凸性缺陷,并且返回 CvConvexityDefect 結(jié)構(gòu)序列。

PointPolygonTest

測試點是否在多邊形中

double cvPointPolygonTest( const CvArr* contour,
                           CvPoint2D32f pt, int measure_dist );
    contour
  • 輸入輪廓.

  • pt
  • 針對輪廓需要測試的點。

  • measure_dist
  • 如果非0,函數(shù)將估算點到輪廓最近邊的距離。

函數(shù)cvPointPolygonTest 決定測試點是否在輪廓內(nèi),輪廓外,還是輪廓的邊上(或者共邊的交點上),它的返回值是正負零,相對應(yīng)的,當measure_dist=0時,返回值是1, -1,0, 同樣當 measure_dist≠0 ,它是返回一個從點到最近的邊的帶符號距離。

下面是函數(shù)輸出的結(jié)果,用圖片的每一個象素去測試輪廓的結(jié)果。

Image:Pointpolygon.png

MinAreaRect2

對給定的 2D 點集,尋找最小面積的包圍矩形

CvBox2D  cvMinAreaRect2( const CvArr* points, CvMemStorage* storage=NULL );
    points
  • 點序列或點集數(shù)組

  • storage
  • 可選的臨時存儲倉

函數(shù) cvMinAreaRect2 通過建立凸外形并且旋轉(zhuǎn)外形以尋找給定 2D 點集的最小面積的包圍矩形.

Picture. Minimal-area bounding rectangle for contour

Image:Minareabox.png

MinEnclosingCircle

對給定的 2D 點集,尋找最小面積的包圍圓形

int cvMinEnclosingCircle( const CvArr* points, CvPoint2D32f* center, float* radius );
    points
  • 點序列或點集數(shù)組

  • center
  • 輸出參數(shù):圓心

  • radius
  • 輸出參數(shù):半徑

函數(shù) cvMinEnclosingCircle 對給定的 2D 點集迭代尋找最小面積的包圍圓形。如果產(chǎn)生的圓包含所有點,返回非零。否則返回零(算法失?。?。

CalcPGH

計算輪廓的 pair-wise 幾何直方圖

void cvCalcPGH( const CvSeq* contour, CvHistogram* hist );
    contour
  • 輸入輪廓,當前僅僅支持具有整數(shù)坐標的點集

  • hist
  • 計算出的直方圖,必須是兩維的。

函數(shù) cvCalcPGH 計算輪廓的 2D pair-wise 幾何直方圖 (2D pair-wise geometrical histogram :PGH), 算法描述見 [Iivarinen97]. 算法考慮的每一對輪廓邊緣。計算每一對邊緣之間的夾角以及最大最小距離。具體做法是,輪流考慮每一個邊緣做為基準,函數(shù)循環(huán)遍歷所有其他的邊緣。在考慮基準邊緣和其它邊緣的時候, 選擇非基準線上的點到基準線上的最大和最小距離。邊緣之間的角度定義了直方圖的行,而在其中增加對應(yīng)計算出來的最大和最小距離的所有直方塊, (即直方圖是 [Iivarninen97] 定義中的轉(zhuǎn)置). 該直方圖用來做輪廓匹配。

平面劃分

CvSubdiv2D

平面劃分

#define CV_SUBDIV2D_FIELDS()        CV_GRAPH_FIELDS()               int  quad_edges;                int  is_geometry_valid;         CvSubdiv2DEdge recent_edge;     CvPoint2D32f  topleft;          CvPoint2D32f  bottomright;

typedef struct CvSubdiv2D
{
    CV_SUBDIV2D_FIELDS()
}
CvSubdiv2D;

平面劃分是將一個平面分割為一組互不重疊的能夠復(fù)蓋整個平面的區(qū)域P(facets)。上面結(jié)構(gòu)描述了建立在 2D 點集上的劃分結(jié)構(gòu),其中點集互相連接并且構(gòu)成平面圖形,該圖形通過結(jié)合一些無限連接外部劃分點(稱為凸形點)的邊緣,將一個平面用邊按照其邊緣劃分成很多小區(qū)域(facets)。

對于每一個劃分操作,都有一個對偶劃分與之對應(yīng),對偶的意思是小區(qū)域和點(劃分的頂點)變換角色,即在對偶劃分中,小區(qū)域被當做一個頂點(以下稱之為虛擬點),而原始的劃分頂點被當做小區(qū)域。在如下所示的圖例中,原始的劃分用實線來表示,而對偶劃分用點線來表示。

OpenCV 使用Delaunay's 算法將平面分割成小的三角形區(qū)域。分割的實現(xiàn)通過從一個假定的三角形(該三角形確保包括所有的分割點)開始不斷迭代來完成。在這種情況下,對偶劃分就是輸入的2d點集的 Voronoi圖表。這種劃分可以用于對一個平面的3d分段變換、形態(tài)變換、平面點的快速定位以及建立特定的圖結(jié)構(gòu) (比如 NNG,RNG等等)。

Image:Subdiv.png

CvQuadEdge2D

平面劃分中的Quad-edge(四方邊緣結(jié)構(gòu))

/* quad-edge中的一條邊緣,低兩位表示該邊緣的索引號,其它高位表示邊緣指針。 */
typedef long CvSubdiv2DEdge;

/* 四方邊緣的結(jié)構(gòu)場 */
#define CV_QUADEDGE2D_FIELDS()         int flags;                         struct CvSubdiv2DPoint* pt[4];     CvSubdiv2DEdge  next[4];

typedef struct CvQuadEdge2D
{
    CV_QUADEDGE2D_FIELDS()
}
CvQuadEdge2D;

Quad-edge(譯者注:以下稱之為四方邊緣結(jié)構(gòu))是平面劃分的基元,其中包括四個邊緣 (e, eRot(紅色) 以及它們的逆(綠色))。

Image:Quadedge.png

CvSubdiv2DPoint

原始和對偶劃分點

#define CV_SUBDIV2D_POINT_FIELDS()    int            flags;          CvSubdiv2DEdge first;          CvPoint2D32f   pt;

#define CV_SUBDIV2D_VIRTUAL_POINT_FLAG (1 << 30)

typedef struct CvSubdiv2DPoint
{
    CV_SUBDIV2D_POINT_FIELDS()
}
CvSubdiv2DPoint;

Subdiv2DGetEdge

返回給定的邊緣之一

CvSubdiv2DEdge  cvSubdiv2DGetEdge( CvSubdiv2DEdge edge, CvNextEdgeType type );
#define cvSubdiv2DNextEdge( edge ) cvSubdiv2DGetEdge( edge, CV_NEXT_AROUND_ORG )
    edge
  • 劃分的邊緣 (并不是四方邊緣結(jié)構(gòu))

  • type
  • 確定函數(shù)返回哪條相關(guān)邊緣,是下面幾種之一:

    • CV_NEXT_AROUND_ORG - 邊緣原點的下一條 (eOnext on the picture above if e is the input edge)

    • CV_NEXT_AROUND_DST - 邊緣頂點的下一條 (eDnext)

    • CV_PREV_AROUND_ORG - 邊緣原點的前一條 (reversed eRnext)

    • CV_PREV_AROUND_DST - 邊緣終點的前一條 (reversed eLnext)

    • CV_NEXT_AROUND_LEFT - 左區(qū)域的下一條 (eLnext)

    • CV_NEXT_AROUND_RIGHT - 右區(qū)域的下一條(eRnext)

    • CV_PREV_AROUND_LEFT - 左區(qū)域的前一條 (reversed eOnext)

    • CV_PREV_AROUND_RIGHT - 右區(qū)域的前一條 (reversed eDnext)

函數(shù) cvSubdiv2DGetEdge 返回與輸入邊緣相關(guān)的邊緣

Subdiv2DRotateEdge

返回同一個四方邊緣結(jié)構(gòu)中的另一條邊緣

CvSubdiv2DEdge  cvSubdiv2DRotateEdge( CvSubdiv2DEdge edge, int rotate );
    edge
  • 劃分的邊緣 (并不是四方邊緣結(jié)構(gòu))

  • type
  • 確定函數(shù)根據(jù)輸入的邊緣返回同一四方邊緣結(jié)構(gòu)中的哪條邊緣,是下面幾種之一:

    • 0 - 輸入邊緣 (上圖中的e,如果e是輸入邊緣)

    • 1 - 旋轉(zhuǎn)邊緣 (eRot)

    • 2 -逆邊緣 ( e的反向邊緣)

    • 3 - 旋轉(zhuǎn)邊緣的反向邊緣(eRot的反向邊緣, 圖中綠色)

函數(shù) cvSubdiv2DRotateEdge 根據(jù)輸入的邊緣返回四方邊緣結(jié)構(gòu)中的一條邊緣

Subdiv2DEdgeOrg

返回邊緣的原點

CvSubdiv2DPoint* cvSubdiv2DEdgeOrg( CvSubdiv2DEdge edge );
    edge
  • 劃分的邊緣 (并不是四方邊緣結(jié)構(gòu))

函數(shù) cvSubdiv2DEdgeOrg 返回邊緣的原點。如果該邊緣是從對偶劃分得到并且虛點坐標還沒有計算出來,可能返回空指針。虛點可以用函數(shù)來cvCalcSubdivVoronoi2D計算。

Subdiv2DEdgeDst

Returns edge destination

CvSubdiv2DPoint* cvSubdiv2DEdgeDst( CvSubdiv2DEdge edge );
    edge
  • 劃分的邊緣 (并不是四方邊緣結(jié)構(gòu))

函數(shù) cvSubdiv2DEdgeDst 返回邊緣的終點。如果該邊緣是從對偶劃分得到并且虛點坐標還沒有計算出來,可能返回空指針。虛點可以用函數(shù)來cvCalcSubdivVoronoi2D計算。

CreateSubdivDelaunay2D

生成的空Delaunay 三角測量

CvSubdiv2D* cvCreateSubdivDelaunay2D( CvRect rect, CvMemStorage* storage );
    rect
  • Rectangle包括所有待加入劃分操作的2d點的四方形。

  • storage
  • 劃分操作的存儲器

函數(shù) cvCreateSubdivDelaunay2D 生成一個空的Delaunay 劃分, 其中2d points可以進一步使用函數(shù) cvSubdivDelaunay2DInsert來添加。所有的點一定要在指定的四方形中添加,否則就會報運行錯誤。

SubdivDelaunay2DInsert

向 Delaunay三角測量中插入一個點

CvSubdiv2DPoint*  cvSubdivDelaunay2DInsert( CvSubdiv2D* subdiv, CvPoint2D32f pt);
    subdiv
  • 通過函數(shù) cvCreateSubdivDelaunay2D.生成的Delaunay劃分

  • pt
  • 待插入的點

函數(shù) cvSubdivDelaunay2DInsert 向劃分的結(jié)構(gòu)中插入一個點并且正確地改變劃分的拓樸結(jié)構(gòu)。如果劃分結(jié)構(gòu)中已經(jīng)存在一個相同的坐標點,則不會有新點插入。該函數(shù)返回指向已插入點的指針。在這個截斷,不計算任何虛點坐標。

Subdiv2DLocate

在 Delaunay三角測量中定位輸入點

CvSubdiv2DPointLocation  cvSubdiv2DLocate( CvSubdiv2D* subdiv, CvPoint2D32f pt,
                                           CvSubdiv2DEdge* edge,
                                           CvSubdiv2DPoint** vertex=NULL );
    subdiv
  • Delaunay 或者是其它分割結(jié)構(gòu).

  • pt
  • 待定位的輸入點

  • edge
  • 與輸入點對應(yīng)的輸入邊緣(點在其上或者其右)

  • vertex
  • 與輸入點對應(yīng)的輸出頂點坐標(指向double類型),可選。

函數(shù) cvSubdiv2DLocate 在劃分中定位輸入點,共有5種類型:

  • 輸入點落入某小區(qū)域內(nèi)。 函數(shù)返回參數(shù) CV_PTLOC_INSIDE 且*edge 中包含小區(qū)域的邊緣之一。

  • 輸入點落p在邊緣之上。 函數(shù)返回參數(shù) CV_PTLOC_ON_EDGE 且 *edge 包含此邊緣。

  • 輸入點與劃分的頂點之一相對應(yīng)。 函數(shù)返回參數(shù) CV_PTLOC_VERTEX 且 *vertex 中包括指向該頂點的指針;

  • 輸入點落在劃分的參考區(qū)域之外。 函數(shù)返回參數(shù) CV_PTLOC_OUTSIDE_RECT且不填寫任何指針。

  • 輸入?yún)?shù)之一有誤。函數(shù)報運行錯誤(如果已經(jīng)選則了沉默或者父母出錯模式,則函數(shù)返回CV_PTLOC_ERROR) 。

FindNearestPoint2D

根據(jù)輸入點,找到其最近的劃分頂點

CvSubdiv2DPoint* cvFindNearestPoint2D( CvSubdiv2D* subdiv, CvPoint2D32f pt );
    subdiv
  • Delaunay或者其它劃分方式

  • pt
  • 輸入點

函數(shù) cvFindNearestPoint2D 是另一個定位輸入點的函數(shù)。該函數(shù)找到輸入點的最近劃分頂點。盡管劃分出的小區(qū)域(facet)被用來作為起始點,但是輸入點不一定非得在最終找到的頂點所在的小區(qū)域之內(nèi)。該函數(shù)返回指向找到的劃分頂點的指針。

CalcSubdivVoronoi2D

計算Voronoi圖表的細胞結(jié)構(gòu)

void cvCalcSubdivVoronoi2D( CvSubdiv2D* subdiv );
    subdiv
  • Delaunay 劃分,其中所有的點已經(jīng)添加 。

函數(shù) cvCalcSubdivVoronoi2D 計算虛點的坐標,所有與原劃分中的某頂點相對應(yīng)的虛點形成了(當他們相互連接時)該頂點的Voronoi 細胞的邊界。

ClearSubdivVoronoi2D

移除所有的虛點

void cvClearSubdivVoronoi2D( CvSubdiv2D* subdiv );
    subdiv
  • Delaunay 劃分

函數(shù) cvClearSubdivVoronoi2D 移除所有的虛點。當劃分的結(jié)果被函數(shù)cvCalcSubdivVoronoi2D的前一次調(diào)用更改時,該函數(shù)被cvCalcSubdivVoronoi2D內(nèi)部調(diào)用 。


還有一些其它的底層處理函數(shù)與平面劃分操作協(xié)同工作,參見 cv.h 及源碼。生成 delaunay.c 三角測量以及2d隨機點集的Voronoi 圖表的演示代碼可以在 opencv

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多