Контур многоугольника в OpenCV? например противоположность cvApproxPoly ()? - PullRequest
3 голосов
/ 24 декабря 2009

Существует ли простое и быстрое решение OpenCV, которое преобразует набор вершин CvPoint, определяющих многоугольник, в контур с большим количеством вершин?

У меня есть простые многоугольники в одном пространстве, и я хочу преобразовать многоугольники в другое пространство, где прямые линии станут изогнутыми. Поэтому важно, чтобы я добавил больше вершин в мои прямые линии. Это было бы противоположностью cvApproxPoly().

Внутренне cvPolyLine() делает именно то, что я хочу. Есть ли способ получить к нему доступ?

Я использую OpenCV 1.1.

1 Ответ

4 голосов
/ 25 декабря 2009

Итак, я написал свою собственную функцию GetLineFromEndPts (), которая должна решить эту проблему хитроумно. Учитывая две точки a и b, эта функция выводит список точек на линии, соединяющей a и b. Поэтому, чтобы найти контур с множеством точек из многоугольника, заданного несколькими вершинами, я могу запустить эту функцию для последовательных пар вершин.

 /*
 * Given two points a and b , and a sequence of CvPoints
 * this function will find the points that walk the line
 * between a and b and append those
 * the end of the sequence
 *
 * Note that the output  includes point a, but not point b.
 */
int GetLineFromEndPts(CvPoint a, CvPoint b, CvSeq* contour){
    if (contour==NULL) {
        printf("ERROR! contour in GetLineFromEndPts() is NULL!\n");
        return -1;
    }
    float d=dist(a,b);
    /** Normalized vector with components i and j pointing along the line**/
    float ihat= ( (float) (b.x -a.x) ) /d;
    float jhat= ( (float) (b.y -a.y) ) /d;

    CvPoint currPt; /* Current Point On integer grid*/
    CvPoint prevPt=a; /* Prev Point on integer grid */
    currPt=a;

    /** Prepare Writer for Appending Points to Seq **/
    CvSeqWriter writer;
    cvStartAppendToSeq( contour, &writer ); 

    int t;
    float tempPtx;
    float tempPty;
    int signx=1;
    int signy=1;

    for (t = 0; t <  (int) (d+0.5) ; ++t) {

        /** Our target point is now defined by a parametric equation **/
        tempPtx=(float) t * ihat + (float) a.x;
        tempPty=(float) t * jhat + (float) a.y;

        /** We will want to round and we need to know the number's sign to round correctly **/
        if (tempPtx<0) {
            signx=-1;
        } else {
            signx=1;
        }
        if (tempPty<0) {
            signy=-1;
        } else{
            signy=1;
        }


        /** Round to an integer value. Note that we need the sign before we add/subtract .5 **/
        currPt=cvPoint((int) ( tempPtx + (float) signx * 0.5 ) ,
                    (int) ( tempPty + (float) signy * 0.5 ));


        /** If first point, OR the current approx point is not the same as prev **/
        if ( t==0 ||  !( currPt.x == prevPt.x && currPt.y == prevPt.y   )   ){

            /** Write out the point **/
            CV_WRITE_SEQ_ELEM( currPt, writer );

        printf(" t=%d\n",t);
        printf(" currPt.x=%d\n",currPt.x);
        printf(" currPt.y=%d\n",currPt.y);


        }
        prevPt=currPt;
    }
    cvEndWriteSeq( &writer );
    return 1;
}

И связанные функции:

/*
 * Returns the squared distance between two points
 */
int sqDist(CvPoint pta, CvPoint ptb){
    return (  ((pta.x - ptb.x)*(pta.x - ptb.x) ) + ((pta.y - ptb.y)*(pta.y - ptb.y)  ) );
}

И наконец:

/*
 * Finds the distance between two points
 * and returns the value as a float
 */
float dist(CvPoint a, CvPoint b){
    return ( sqrt( (float) sqDist(a,b))  );
}

Так, например, если вызывается с:

GetLineFromEndPts(cvPoint(0,0),cvPoint(10,15),test);

функция выводит:

 t=0
 currPt.x=0
 currPt.y=0
 t=1
 currPt.x=1
 currPt.y=1
 t=2
 currPt.x=1
 currPt.y=2
 t=3
 currPt.x=2
 currPt.y=2
 t=4
 currPt.x=2
 currPt.y=3
 t=5
 currPt.x=3
 currPt.y=4
 t=6
 currPt.x=3
 currPt.y=5
 t=7
 currPt.x=4
 currPt.y=6
 t=8
 currPt.x=4
 currPt.y=7
 t=9
 currPt.x=5
 currPt.y=7
 t=10
 currPt.x=6
 currPt.y=8
 t=11
 currPt.x=6
 currPt.y=9
 t=12
 currPt.x=7
 currPt.y=10
 t=13
 currPt.x=7
 currPt.y=11
 t=14
 currPt.x=8
 currPt.y=12
 t=16
 currPt.x=9
 currPt.y=13
 t=17
 currPt.x=9
 currPt.y=14
...