2011-11-04 103 views
6

我創建了一個共享庫,用於從Delphi/Lazarus應用程序加載的輪廓檢測。主應用程序將指針傳遞給庫中的函數處理的位圖。OpenCV指向位圖處理的指針

下面是庫中的函數。參數「img」是指向我的位圖的指針。

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

從德爾福的一面,我傳遞一個指向該結構的陣列:

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

我需要處理內存中的位圖,這就是爲什麼我不加載來自庫內的文件。

問題是:這是一個正確的方式來分配一個位圖到cv :: Mat嗎?

我問這是因爲代碼在Linux中沒有問題,但在與Mingw編譯的Windows上失敗。

注:它無法與這條線SIGSEGV:

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

編輯:只有當我編譯的OpenCV在Release模式,在調試模式下它的工作原理確定的SIGSEGV提高。

在此先感謝, 萊昂納多。

回答

1

所以要創建的圖像是這樣的:

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

src.data = img; 

第一個聲明和實例化 墊SRC(imgHeight,imgWidth,CV_8UC4)將分配內存爲新的圖像和自動跟蹤一個引用計數器對分配內存的引用數量。 然後你通過

變異實例變量src.data = img;

當實例src超出作用域時,析構函數被調用並且極有可能試圖釋放src.data中的內存,這是您分配的內存,這可能會導致分段錯誤。正確的方法來做到這一點是不會改變對象的實例變量,而是簡單地使用正確的構造函數時你實例源:

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

這樣一來,您只需創建一個矩陣頭,並沒有引用計數器或釋放將由src的析構函數執行。

祝你好運!

編輯:我不確定段錯誤實際上是由於嘗試錯誤地釋放內存導致的,但不通過直接分配實例變量來中斷數據抽象是一種很好的做法。

+0

謝謝喬納斯。我嘗試了你的建議,它可以在Linux上運行,但SIGSEGV在Windows上仍然存在。 – leonardorame