我一直試圖使用OpenCV和C++來跟蹤2D灰度圖像中曲面的輪廓(線條),但是我一直運行到無限循環。我嘗試了各種調試,但無法糾正我的問題。請幫忙!C++ - 停止無限循環 - 跟蹤輪廓
我的形象看起來是這樣的:http://snag.gy/fAs9a.jpg(第四圖像)
這就是我的「初步」輪廓看上去像:http://snag.gy/fAs9a.jpg(第五圖像)
這是我迄今所做的:
- 初始化包含圖像表面「初始」輪廓的圖像蒙版。
- 在掩碼中,獲取所有值大於255的點座標,並將它們存儲在向量中。
- 對於每個座標集,將行值遞增以沿圖像中的當前列下降,並找到其所有鄰居大於閾值的第一個像素。
- 找到像素後,轉到下一列並重復該過程,直到在所有列中找到所有像素。
- 如果沒有發現這樣的像素,則最後的(行,列)值設置爲0。
- 一旦所有的明亮像素被找到,這構成了「最終輪廓」
問題:我即使我的邏輯聽起來很合理,我的代碼也看起來很合理,但仍然會陷入無限循環。在當前列中可能沒有找到像素大於閾值的像素。
調試:我調試我的代碼,以確定在無限循環發生的一切,並發現它在if-else
代碼塊中main
功能while
循環下。
- 我檢查了我的代碼只爲第一列,它的工作。但是,當我推廣我的代碼時,它會陷入無限循環。
- 試圖減少鄰域模式的要求;如果只有幾個鄰居大於閾值,那麼該點就足夠用於「最終輪廓」
- 我檢查了是否所有行都正在迭代,並看到行計數保持重置。
- 爲了解決第3點,如果超過200,我設置了一個截斷無限循環的計數。但是,輸出「最終輪廓」圖像與初始蒙版圖像相同。
我已經用盡了關於如何刪除我的錯誤的想法。再次,非常感謝幫助!
這是我的代碼:
// function to get the neigbourhood pattern
bool checkLBP(unsigned char *GMOtemp, unsigned char *contour, int &row, int &col, int width, int thresh)
{
const int arrSize = 9;
const int semiArrSize = 6;
// for first column, need only 6 neighbours
// since it is at one end of the image
if(col == 0) {
int array [semiArrSize];
// start storing values in the array
array[0] = GMOtemp[(row*width) + (col)];
array[1] = GMOtemp[((row+1)*width) + (col)];
array[2] = GMOtemp[((row+2)*width) + (col)];
array[3] = GMOtemp[(row*width) + (col+1)];
array[4] = GMOtemp[((row+1)*width) + (col+1)];
array[5] = GMOtemp[((row+2)*width) + (col+1)];
int cnt = 0;
for(int i = 0; i<semiArrSize; i++) {
if(array[i] >= thresh) {
cnt++;
}
}
printf("\n cnt %d \n",cnt);
if(cnt >= 2) {
return true;
}
else {
return false;
}
}
// for last column, need only 6 neighbours
else if(col == width - 1) {
int array [semiArrSize];
// start storing values in the array
array[0] = GMOtemp[(row*width) + (col)];
array[1] = GMOtemp[((row+1)*width) + (col)];
array[2] = GMOtemp[((row+2)*width) + (col)];
array[3] = GMOtemp[(row*width) + (col-1)];
array[4] = GMOtemp[((row+1)*width) + (col-1)];
array[5] = GMOtemp[((row+2)*width) + (col-1)];
int cnt = 0;
for(int i = 0; i<semiArrSize; i++) {
if(array[i] >= thresh) {
cnt++;
}
}
printf("\n cnt %d \n",cnt);
if(cnt >= 2) {
return true;
}
else {
return false;
}
}
else {
int array [arrSize];
// start filling all the elements
array[0] = GMOtemp[((row)*width) +(col-1)];
array[1] = GMOtemp[((row)*width) +(col)];
array[2] = GMOtemp[((row)*width) +(col+1)];
array[3] = GMOtemp[((row+1)*width) +(col-1)];
array[4] = GMOtemp[((row+1)*width) +(col)];
array[5] = GMOtemp[((row+1)*width) +(col+1)];
array[6] = GMOtemp[((row+2)*width) +(col-1)];
array[7] = GMOtemp[((row+2)*width) +(col)];
array[8] = GMOtemp[((row+2)*width) +(col+1)];
int cnt = 0;
for(int i = 0; i<arrSize; i++) {
if(array[i] >= thresh) {
cnt++;
}
}
printf("\n cnt %d \n",cnt);
if(cnt >= 1) {
return true;
}
else {
return false;
}
}
}
的main()
// ... previous code to do blurring of the image.
// code to get the point-coordinates from the "initial mask" image
std::vector<int> setC;
std::vector<int> setR;
for(int xc = 0; xc < input.cols; xc++) {
for(int xr = 0; xr < input.rows; xr++) {
int val = mask[xr*input.cols + xc];
if(val == 255) {
//setC[i] = xc;
//setR[i] = xr;
//i++;
setC.push_back(xc);
setR.push_back(xr);
}
}
}
// get the LBP pattern
// LBP PATTERN IS A 3X3 NEIGHBOURHOOD
std::vector<int>::iterator mc1 = setC.begin();
std::vector<int>::iterator mr1 = setR.begin();
int rr = 0;
int cc = 0;
int width = input.cols;
//rowcount = 0;
int infiniteCount = 0;
unsigned char *GMOtemp;
unsigned char *contour;
GMOtemp = (unsigned char*) malloc(sizeof(unsigned char) * input.rows * input.cols);
contour = (unsigned char*) malloc(sizeof(unsigned char) * input.rows * input.cols);
memcpy(GMOtemp, OCVout2.data, sizeof(unsigned char) * input.rows * input.cols);
memset(contour, 0, sizeof(unsigned char) * input.rows * input.cols);
while((mc1 != setC.end()) && (mr1 != setR.end())) {
//looping:
rr = *mr1; // get row and col
cc = *mc1;
printf("\n %d %d \n", rr, cc);
rr++; // increment the row
bool result = checkLBP(GMOtemp, contour, rr, cc, width, sum);
//printf("\n %d \n", rr);
if(result == true)
{
contour[rr*width + cc] = 255; // set current point to be equal to 255
mc1++; // increment the vector iterators - so, go to next column
mr1++;
}
else {
do{
rr++;
result = checkLBP(GMOtemp, contour, rr, cc, width, sum);
infiniteCount++;
//printf("\n rr %d \n", rr);
//printf("\n %d \n", infiniteCount);
if (rr == (input.rows - 1) || infiniteCount == 200) {
contour[rr*width + cc] = 255;
mr1++;
mc1++;
infiniteCount = 0;
result = true;
break;
}
//printf("\n rr %d \n", rr);
} while(result == false);
}
我昨天晚上解決了它。在'if(result == false)'循環中,我將while循環轉換爲for循環。所以,我所做的是我強迫迭代從當前行到最後,檢查結果和命中'break'只有當'結果== TRUE'。我還包括一個'check'變量,看看所有結果是否都是錯誤的。如果檢查設置爲true(您建議的標誌),我將轉到下一個座標集。我將在今天晚些時候發佈代碼,因爲我離開了我編寫代碼的實際系統。 – Eagle
不,我想就這樣打破了我的'如果.. else'循環。請記住,在循環的「else」部分中,如果當前列中所有像素的所有像素鄰居(逐個迭代)小於閾值,則意味着沒有像素可以設置爲當前列中的255。所以,我必須移動到下一列,獲取下一個座標集,然後執行相同的操作。 – Eagle
@eagle,很高興你解決它,然後,是啊,你的'check'和我的'flag'其實是同樣的事情,就是採取這樣的檢查步驟。另外,如果你試圖擺脫'if ... else'循環,'break'不會這樣做。 'break'不上'如果... else',通常人們用'goto'工作,而不是,但我不是那種風扇。不過,很高興你解決了這個問題,我希望我能以同樣的方式幫助你。乾杯(: – rockinfresh