[Jderobot-dev] problemas con algoritmo de Solis

Julio Guillén julio.guillen en gmail.com
Mar Mar 27 12:05:59 CEST 2012


Hola amigos, os escribo porque estoy teniendo un fallo raro al tratar de
usar Solis. Me he creado un sencillo programa para poder utilizar imágenes
con solis y poder comparar resultados tras optimizarlo para mi caso
concreto. Quiero adelantar que estoy usando la versión 2.0.0 de OpenCv y
que ya he sido capaz de utilizar este algoritmo en un componente propio.

El caso es que me he creado un pequeño proyecto en C++ y me he traído todo
lo necesario para poder usarlo de manera independiente. El programa me
compila perfectamente, pero a la hora de ejecutar me da fallo de violación
de segmento. Empleando GDB me dice que el fallo está en detectorsolis

Program received signal SIGSEGV, Segmentation fault.
0x0804ae63 in detectorsolis(_IplImage&, std::vector<Segment2D,
std::allocator<Segment2D> >*) ()

más concretamente cuando hago cvCreateImage de IplTmp1. El algoritmo de
solis está exactamente igual que el de la librería visionlib, y he sido
capaz de utilizarlo sin problemas en mi componente. Pero ahora me da fallo
y creo que es por tipos deprecados. No entiendo por qué antes me funcionaba
perfecto y ahora me da los fallos.

A ver si me podeis ayudar, y mis disculpas si es un fallo evidente. La
verdad llevo tanto con esto que no se por donde continuar.

El código es el siguiente:

=====================

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

#define G_SQUARE(a) ((a)*(a))

typedef struct {
  float x;
  float y;
  float h;
} HPoint2D;

typedef struct {
    HPoint2D start;
    HPoint2D end;
    int type;
    int isValid;
} Segment2D;

void detectorsolis(IplImage &image, std::vector<Segment2D> *segments);
double distanceBetweenPoints2D(int x1, int y1, int x2, int y2);
double distanceBetweenPoints2D(double x1, double y1, double x2, double y2);

int main() {
    IplImage *image;
    image = cvLoadImage("puerta.jpg",CV_LOAD_IMAGE_UNCHANGED);
    cvNamedWindow("Line Detection Algorithm");
    std::vector<Segment2D> segments;

    detectorsolis(*image, &segments);

    cvShowImage("Line Detection Algorithm", image);
    cvWaitKey();

    cvReleaseImage(&image);
    cvDestroyWindow("Line Detection Algorithm");
}

const int CASES_OFFSET = 5;

const int solis_cases[][11] =
        { { 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8 },
                { 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8 }, { 6, 6, 6, 6, 7, 7, 7,
8,
                        8, 8, 8 }, { 5, 5, 6, 6, 7, 7, 7, 8, 8, 1, 1 }, {
5, 5,
                        5, 5, 0, 0, 0, 1, 1, 1, 1 }, { 5, 5, 5, 5, 0, 0, 0,
1,
                        1, 1, 1 }, { 5, 5, 5, 5, 0, 0, 0, 1, 1, 1, 1 }, {
5, 5,
                        4, 4, 3, 3, 3, 2, 2, 1, 1 }, { 4, 4, 4, 4, 3, 3, 3,
2,
                        2, 2, 2 }, { 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2 }, {
4, 4,
                        4, 3, 3, 3, 3, 3, 2, 2, 2 } };

void detectorsolis(IplImage &image, std::vector<Segment2D> *segments) {
    IplImage *IplTmp1, *IplTmp2, *IplBlack, *IplLaplace;
    CvPoint pstart, pend;
    CvMemStorage *storage;
    CvSeq* contour = NULL;
    int i, i_jump = 6;
    int ThressValue = 30;
    int diff_x, diff_y;
    CvPoint *WholePointArray;
    const int min_size_contour = 30;
    CvScalar color;
    Segment2D mySegment;
    int type, current_type;
    int num_frag, min_frags = 3, counter = 0;
    double max_distance;
    bool first, debug = false;

    IplTmp1 = cvCreateImage(cvSize(image.width, image.height),
IPL_DEPTH_8U, 1);
    IplTmp2 = cvCreateImage(cvSize(image.width, image.height),
IPL_DEPTH_8U, 1);
    IplLaplace = cvCreateImage(cvSize(image.width, image.height),
IPL_DEPTH_16S, 1);
    storage = cvCreateMemStorage(0);

    /*Convert to Gray Image*/
    cvCvtColor(&image, IplTmp1, CV_RGB2GRAY);

    /*Normalize image*/
    cvNormalize(IplTmp1, IplTmp1, 0, 255, CV_MINMAX);

    // Make a average filtering
    cvSmooth(IplTmp1, IplTmp2, CV_BLUR, 3, 3); //-> OK
    //cvSmooth(IplTmp1,IplTmp2,CV_BLUR,1,1);

    //Laplace
    cvLaplace(IplTmp2, IplLaplace, 3);
    cvConvertScale(IplLaplace, IplTmp1);

    /*Perform a binary threshold*/
    cvThreshold(IplTmp1, IplTmp2, ThressValue, 255, CV_THRESH_BINARY);

    /*Find contours*/
    cvFindContours(IplTmp2, storage, &contour, sizeof(CvContour),
CV_RETR_LIST,
            CV_LINK_RUNS); //->OK
    //cvFindContours(IplTmp2, storage, &contour, sizeof(CvContour),
CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

    /*Run through found coutours*/
    while (contour != NULL) {
        /*Check length*/
        if (contour->total >= min_size_contour) {
            /*Convert to array*/
            WholePointArray = (CvPoint *) malloc(
                    contour->total * sizeof(CvPoint));
            cvCvtSeqToArray(contour, WholePointArray, CV_WHOLE_SEQ);

            i = 0;
            first = true;

            while ((i < (contour->total - (i_jump - 1)))) {

                counter++;

                /*Get current segment*/
                pstart.x = WholePointArray[(int) i].x;
                pstart.y = WholePointArray[(int) i].y;
                pend.x = WholePointArray[(int) (i + i_jump - 1)].x;
                pend.y = WholePointArray[(int) (i + i_jump - 1)].y;

                /*Calculate type*/
                diff_x = pstart.x - pend.x;
                diff_y = pstart.y - pend.y;
                type =
                        solis_cases[diff_x + CASES_OFFSET][diff_y +
CASES_OFFSET];

                if (debug) {
                    /*Visual portions*/
                    if (type == 0)
                        color = CV_RGB(255,255,255);
                    else if (type == 1)
                        color = CV_RGB(255,255,0);
                    else if (type == 2)
                        color = CV_RGB(0,255,255);
                    else if (type == 3)
                        color = CV_RGB(255,0,0);
                    else if (type == 4)
                        color = CV_RGB(0,255,0);
                    else if (type == 5)
                        color = CV_RGB(0,0,255);
                    else if (type == 6)
                        color = CV_RGB(255,0,255);
                    else if (type == 7)
                        color = CV_RGB(0,128,128);
                    else if (type == 8)
                        color = CV_RGB(128,128,0);

                    /*Draw line with orientation*/
                    cvLine(IplBlack, pstart, pend, color, 2, CV_AA, 0);
                } else {
                    if (first) {
                        if (type != 0) {
                            mySegment.start.x = pstart.x;
                            mySegment.start.y = pstart.y;
                            mySegment.start.h = (float) counter;
                            mySegment.end.x = pend.x;
                            mySegment.end.y = pend.y;
                            mySegment.end.h = (float) counter;
                            mySegment.type = type;
                            first = false;
                            current_type = type;
                            num_frag = 1;
                        }
                    } else {
                        /*Check type threshold*/
                        if (current_type == type /*|| type == 0*/) {
                            /*Save current end*/
                            mySegment.end.x = pend.x;
                            mySegment.end.y = pend.y;
                            mySegment.end.h = (float) counter;
                            num_frag++;
                        } else {
                            /*Save current segment if length is enough*/
                            if (num_frag >= min_frags)
                                segments->push_back(mySegment);
                            first = true;
                        }
                    }
                }

                i += i_jump;
            }

            /*Save the last one*/
            if (!first && num_frag >= min_frags)
                segments->push_back(mySegment);

            free(WholePointArray);
        }

        contour = contour->h_next;
    }

    max_distance = (double) (i_jump * min_frags);

    /*Merge consecutive fragments*/
    std::vector<Segment2D>::iterator it1 = segments->begin();
    while (it1 != segments->end()) {
        /*Compare with next one*/
        std::vector<Segment2D>::iterator it2 = it1;
        it2++;
        if (it2 != segments->end()) {
            if ((*it1).type == (*it2).type
                    && (*it2).start.h - (*it1).end.h <= min_frags) {
                if (distanceBetweenPoints2D((*it2).start.x,
                        (*it2).start.y, (*it1).end.x, (*it1).end.y)
                        <= max_distance) {
                    (*it1).end.x = (*it2).end.x;
                    (*it1).end.y = (*it2).end.y;
                    (*it1).end.h = (*it2).end.h;
                    segments->erase(it2);
                    continue;
                }
            }
        }

        it1++;
    }

    /*Reset .h values*/
    for (std::vector<Segment2D>::iterator it_s = segments->begin();
            it_s != segments->end(); it_s++) {
        (*it_s).start.h = 1.0;
        (*it_s).end.h = 1.0;
    }

    /*Clean up*/
    cvReleaseImage(&IplTmp1);
    cvReleaseImage(&IplTmp2);
    cvClearMemStorage(storage); //Free contour
    cvReleaseMemStorage(&storage);

    if (debug)
        cvReleaseImage(&IplBlack);
}

double distanceBetweenPoints2D(int x1, int y1, int x2, int y2)
{
    return sqrt(G_SQUARE(x2-x1) + G_SQUARE(y2-y1));
}

double distanceBetweenPoints2D(double x1, double y1, double x2, double y2)
{
    return sqrt(G_SQUARE(x2-x1) + G_SQUARE(y2-y1));
}
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: http://gsyc.escet.urjc.es/pipermail/jde-developers/attachments/20120327/66777b7b/attachment.htm 


More information about the Jde-developers mailing list