2011-11-04 56 views
6

Tôi đã tạo một thư viện được chia sẻ để phát hiện đường viền được tải từ ứng dụng Delphi/Lazarus. Ứng dụng chính, chuyển một con trỏ tới một bitmap để được xử lý bởi một hàm bên trong thư viện.Con trỏ OpenCV để xử lý bitmap

Đây là hàm bên trong thư viện. Tham số "img" là con trỏ tới bitmap của tôi.

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

Từ phía Delphi, tôi đi qua một con trỏ đến một mảng của cấu trúc này:

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

tôi cần phải xử lý bitmap trong-bộ nhớ, đó là lý do tại sao tôi không tải tập tin từ bên trong thư viện.

Câu hỏi đặt ra là: Đây có phải là cách đúng để chỉ định bitmap cho cv :: Mat không?

Tôi hỏi điều này vì mã hoạt động mà không có sự cố trong Linux, nhưng không thành công trên Windows được biên dịch với Mingw.

Lưu ý: nó không thành công với một SIGSEGV trên dòng này:

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

EDIT: Các SIGSEGV được nâng lên chỉ khi tôi biên dịch OpenCV trong chế độ Release, trong chế độ Debug nó hoạt động ok.

Xin cảm ơn trước, Leonardo.

Trả lời

1

Vì vậy, bạn đang tạo ra một hình ảnh theo cách này:

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

src.data = img; 

Việc kê khai đầu tiên và instantiation Mat src (imgHeight, imgWidth, CV_8UC4) sẽ phân bổ bộ nhớ cho một hình ảnh mới và một bộ đếm tham chiếu tự động theo dõi số lượng tham chiếu đến bộ nhớ được cấp phát. Sau đó, bạn thay đổi biến mẫu thông qua

src.data = img;

Khi thể hiện src nằm ngoài phạm vi, hàm hủy được gọi và rất có thể sẽ cố gắng xử lý bộ nhớ tại src.data, mà bạn đã gán và điều này có thể gây ra lỗi phân đoạn. Đúng cách để làm điều đó là không thay đổi biến số thể hiện của một đối tượng, nhưng chỉ cần sử dụng các nhà xây dựng ngay khi bạn nhanh chóng src:

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

Bằng cách này, bạn chỉ cần tạo một tiêu đề ma trận và không có tài liệu tham khảo truy cập hoặc deallocation sẽ được thực hiện bởi destructor của src.

Chúc may mắn!

EDIT: Tôi không chắc chắn rằng segfault là thực sự gây ra bởi một nỗ lực để deallocate bộ nhớ không chính xác, nhưng nó là một thực hành tốt không để phá vỡ dữ liệu trừu tượng bằng cách gán trực tiếp cho các biến dụ.

+0

Cảm ơn Jonas. Tôi đã thử đề xuất của bạn và nó hoạt động trên Linux, nhưng SIGSEGV vẫn còn trên Windows. – leonardorame

Các vấn đề liên quan