2014-11-04 78 views
0

我工作的算法來找到和填充二值化圖像上的區域,代碼爲一些圖像按預期工作,但我不知道爲什麼,之後第四影像畫面,我總是得到這個錯誤:OpenCV雙免費或腐敗(出):中止(核心轉儲)

* Error in `./heli': double free or corruption (out): 0x0000000001ccb610 * Aborted (core dumped)

這是我的代碼:

void fillRegion(Mat src, Mat &dst, Point origin, Vec3b color) 
{ 
    int size = 0; 
    list<Point> cadena; 
    cadena.push_back(origin); 
    while(!cadena.empty()) 
    { 
     Point current = cadena.front(); 
     cadena.pop_front(); 
     Point top,bot,right,left; 
     top = bot = right = left = current; 
     top.y -= 1; 
     bot.y += 1; 
     right.x += 1; 
     left.x -= 1; 
     Vec3b cero = Vec3b(0,0,0); 

     if(top.y >= 0 && dst.at<Vec3b>(top) == cero && src.at<uchar>(top)!= 0) 
     { 
      dst.at<Vec3b>(top) = color; 
      cadena.push_back(top); 
     } 
     if(bot.y <= src.rows && dst.at<Vec3b>(bot) == cero && src.at<uchar>(bot)!= 0) 
     { 
      dst.at<Vec3b>(bot) = color; 
      cadena.push_back(bot); 
     } 
     if(right.x <= src.cols && dst.at<Vec3b>(right) == cero && src.at<uchar>(right)!= 0) 
     { 
      dst.at<Vec3b>(right) = color; 
      cadena.push_back(right); 
     } 
     if(left.y >= 0 && dst.at<Vec3b>(left) == cero && src.at<uchar>(left)!= 0) 
     { 
      dst.at<Vec3b>(left) = color; 
      cadena.push_back(left); 
     } 
    } 
} 

void segment(Mat src, Mat &dst) 
{ 
    for(int x = 0; x < src.cols; x++) 
    { 
     for(int y = 0; y < src.rows; y++) 
     { 
      Point p = Point(x,y); 
      if(src.at<uchar>(p) != 0 && dst.at<Vec3b>(p) == Vec3b(0,0,0)) 
      { 
       fillRegion(src,dst,p,getRandomColor()); 
      } 
     }  
    } 
} 
int main(int argc, char *argv[]) 
{ 
    namedWindow("Original", WINDOW_NORMAL); 
    namedWindow("Resultado", WINDOW_NORMAL); 
    vector<string> archivos = vector<string>(); 
    getdir("../images",archivos); 
    int tam = archivos.size(); 
    for(uint i = 0; i < tam; i++) 
    { 
     Mat img = imread(archivos[i],CV_LOAD_IMAGE_GRAYSCALE); 
     Mat newImg = Mat(img.rows,img.cols, CV_8UC3, Scalar(0,0,0));; 
     threshold(img,img,125,255,THRESH_BINARY); 
     imshow("Original", img); 
     segment(img,newImg); 
     imshow("Resultado", newImg); 
     waitKey(0); 
    } 
} 

我稱之爲「分段」的方法,然後調用找到的每個區域的「fillRegion」的方法。 我知道錯誤發生在「fillRegion」方法上,因爲如果我從「segment」發表評論,錯誤消失了,但我無法找到/不知道錯誤是什麼。

回答

0

如果你有GDB(你應該),做到以下幾點:

gdb 
run "your file name here" 
core /[name of core file] 
bt (stands for backtrace) 

這會告訴你,你的代碼崩潰。

+0

好吧我這樣做,它告訴我,錯誤是在這條主線上: 'Mat newImg = Mat(img.rows,img.cols,CV_8UC3 ,標量(0,0,0));' 具體來說,在對Mat :: release的調用中(我從來沒有這樣做) 但是這並沒有告訴我任何東西:/ – 2014-11-04 16:01:59

+0

Mat有一個用戶定義的副本實際上工作的構造函數?我不知道,但是如果在那一行有錯誤,可能是它使用的是編譯器生成的拷貝構造函數,這可能不夠。 – PaulMcKenzie 2014-11-04 16:05:35

+0

@edua_glz我會建議這樣做:'Mat newImg(img.rows,img.cols,CV_8UC3,Scalar(0,0,0));'不需要調用複製構造函數 - 只需創建變量。您在代碼中的其他幾個地方做了同樣的疏忽,在創建新對象時,您不必要地調用複製構造函數。像這裏 - 'Vec3b cero = Vec3b(0,0,0);'這應該是'Vec3b cero(0,0,0);' – PaulMcKenzie 2014-11-04 16:11:26

0

我不認爲它與複製構造函數不同的是它沒有分配足夠的內存。正如您所提到的,在segment中註釋fillRegion呼叫可以避免seg錯誤。這可能意味着fillRegion中存在內存泄漏,它會在程序的4次迭代中填滿分配的內存大小。

雖然這不會解決你的內存泄漏問題,但我建議將Mat src改爲const Mat& src。通過引用傳遞將避免在這種情況下不必要的副本,因爲您不在內部修改任何內容src

我的猜測,內存泄漏與這兩個檢查要做到: bot.y <= src.rows right.x <= src.cols

我認爲,他們應該把嚴格小於(<)少,以避免無效點打電話at。在當前Mat尺寸以外的點上調用at時,它是否調整大小?如果是這樣的話,那麼只要你碰到這些邊界,你就會不斷調整這些圖像的大小。有你的內存泄漏

還有一件事:可以getRandomColor()潛在返回(0, 0, 0)?如果是這樣,這個程序可能會陷入無限循環

+0

我按照您的建議進行了兩項更改,但錯誤仍然存​​在 – 2014-11-04 16:25:36

+0

根據此處的文檔:http://docs.opencv.org/doc /tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.html#mat複製構造函數使用引用計數機制,並不實際複製數據。但是,我同意OP應該通過const引用,只是爲了避免所有這些。 – PaulMcKenzie 2014-11-04 16:31:31