2011-11-04 18 views
6

He creado una biblioteca compartida para la detección de contornos que se carga desde una aplicación Delphi/Lazarus. La aplicación principal pasa un puntero a un mapa de bits para ser procesado por una función dentro de la biblioteca.Puntero OpenCV al procesamiento de mapa de bits

Aquí está la función dentro de la biblioteca. El parámetro "img" es el puntero a mi mapa de bits.

extern "C" { 

    void detect_contour(int imgWidth, int imgHeight, unsigned char * img, int &x, int &y, int &w, int &h) 
    { 
    Mat threshold_output; 
    vector<vector<Point> > contours; 
    vector<Vec4i> hierarchy; 

    Mat src_gray; 
    int thresh = 100; 
     int max_thresh = 255; 
    RNG rng(12345); 

    /// Load source image and convert it to gray 
    Mat src(imgHeight, imgWidth, CV_8UC4); 
    int idx; 

    src.data = img; 

    /// Convert image to gray and blur it 
    cvtColor(src, src_gray, CV_BGRA2GRAY); 

    blur(src_gray, src_gray, Size(10,10)); 

    /// Detect edges using Threshold 
    threshold(src_gray, threshold_output, thresh, 255, THRESH_BINARY); 
    /// Find contours 
    findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); 

    /// Approximate contours to polygons + get bounding rects and circles 
    vector<vector<Point> > contours_poly(contours.size()); 
    vector<Rect> boundRect(contours.size()); 
    vector<Point2f>center(contours.size()); 
    vector<float>radius(contours.size()); 

    int lArea = 0; 
    int lBigger = -1; 

    for(int i = 0; i < contours.size(); i++) 
     { 
     approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true); 
     boundRect[i] = boundingRect(Mat(contours_poly[i])); 
     if(lArea < boundRect[i].width * boundRect[i].height) 
     { 
      lArea = boundRect[i].width * boundRect[i].height; 
      lBigger = i; 
     } 
     } 

    if(lBigger > -1) 
    { 
     x = boundRect[lBigger].x; 
     y = boundRect[lBigger].y; 
     w = boundRect[lBigger].width; 
     h = boundRect[lBigger].height; 
    } 
    } 
} 

Desde el lado de Delphi, estoy pasando un puntero a un array de esta estructura:

TBGRAPixel = packed record 
    blue, green, red, alpha: byte; 
end; 

que necesitan para procesar el mapa de bits en memoria, por eso no estoy de cargar el archivo desde el interior de la biblioteca.

La pregunta es: ¿Es esta la manera correcta de asignar un mapa de bits a un cv :: Mat?

Lo pregunto porque el código funciona sin problemas en Linux, pero falla en Windows compilado con Mingw.

Nota: se produce un error con un SIGSEGV en esta línea:

blur(src_gray, src_gray, Size(10,10)); 

EDIT: El SIGSEGV se eleva sólo si compilo OpenCV en modo de lanzamiento, en modo de depuración funciona bien.

Gracias de antemano, Leonardo.

Respuesta

1

Así que va a crear una imagen de esta manera:

Mat src(imgHeight, imgWidth, CV_8UC4); 
int idx; 

src.data = img; 

La primera declaración y creación de instancias src Mat (imgHeight, imgWidth, CV_8UC4) va a asignar memoria para una nueva imagen y un contador de referencia que realiza un seguimiento automático del número de referencias a la memoria asignada. Luego usted muta una variable de instancia a través de

src.data = img;

Cuando el src de la instancia sale del alcance, se llama al destructor y lo más probable es que intente desasignar la memoria en src.data, que usted asignó y esto podría causar un error de segmentación. La forma correcta de hacerlo es no cambiar variable de instancia de un objeto, sino simplemente utilizar el constructor derecho cuando usted instancia src:

Mat src(imgHeight, imgWidth, CV_8UC4, img); 

De esta manera, usted acaba de crear una cabecera gráfica y no contador de referencia o cancelación de asignación será realizado por el destructor de src.

¡Buena suerte!

EDITAR: No estoy seguro de que el segfault sea en realidad causado por un intento de desasignación de memoria incorrectamente, pero es una buena práctica no romper la abstracción de datos asignando directamente a variables de instancia.

+0

Gracias Jonas. Intenté su sugerencia, y funciona en Linux, pero el SIGSEGV todavía está allí en Windows. – leonardorame

Cuestiones relacionadas