1

(NB : Sorry for my bad english...)

Hi everyone, I need help woth my code (C++) : I need to label regions from a greyscale image using OpenCV.

To do that, I'm initializing a new matrix to zeros.

I search for the first 0 (non labeled pixel), get the coordinates and begin the recursivity : I look at its 8 neighbors. For each : If the pixel exists (if the pixel i'm currently using is not on the edges), then if the "distance" between the current pixel and his neighbor is inferior to a threshold, than I put it in the same region (same label) and had it to a list.

As long as the list isn't empty, I pick another pixel from the same region and start again (pixels in the list).

When a region doesn't have anymore pixel to work with, and if all the pixels aren't labeled, I start a new region and so on.

So probleme is, after several pixels, I get a segmentation fault, which is, according to gdb, a problem coming from std::list.back() with a "Cannot access memory adresse ...".

I started using a std:list of pair. I'm now just using a std::list with 2 push_front to add coordinates in the list, and 2 back (followed by pop_back) to get them back.

I tried with vectors without any good result.

When I use little pictures (64x64), it works without problem. But when it comes to bigger pictures / non-square pictures, I always get a segmentation fault (which, using gdb, seems to be at "int b = listePix.back()").

Thank you.

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/contrib/contrib.hpp>
#include <iostream>
#include <stdio.h>
#include <utility>
#include <list>

using namespace cv;
using namespace std;

void agregation(Mat src, Mat dst);
void expendReg(Mat src, Mat dst, int compteur);
pair<int,int> premiereOcc(Mat dst);

std::list <int> listePix;

int seuil = 20;

int main( int argc, char** argv )
{
    Mat image;
    image = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);

    Mat reg = Mat::zeros(image.rows, image.cols, 0);

    agregation(image,reg);

    cout << "WORKED" << endl;

    waitKey(0);
    return 0;
}

void agregation(Mat src, Mat dst){
    bool flag = 0;
    int compteur = 0;

    do{
      compteur++;

      pair<int,int> coord = premiereOcc(dst);

      if(coord.first == -1 || coord.second == -1){
        flag = 1;
      }
      else{
        int pm = coord.first;
        int pn = coord.second;

        dst.at<uchar>(pm,pn) = compteur;
        listePix.push_front(pn);
        listePix.push_front(pm);

        expendReg(src,dst,compteur);
        listePix.clear();
      }
    }while(!flag);
}

void expendReg(Mat src, Mat dst, int compteur){
    if(listePix.size()>=2){

      int b = listePix.back();
      listePix.pop_back();
      int a = listePix.back();
      listePix.pop_back();

      int dist;

      if((a+1)<dst.rows){
          dist = abs(src.at<uchar>(a,b) - src.at<uchar>(a+1,b));
          int temp = dst.at<uchar>(a+1,b);
          if((dist<=seuil) && (temp == 0)){
            dst.at<uchar>(a+1,b) = compteur;
            listePix.push_front(b);
            listePix.push_front(a+1);
          }
      }
      if((b+1)<dst.cols){
          dist = abs(src.at<uchar>(a,b) - src.at<uchar>(a,b+1));
          int temp = dst.at<uchar>(a,b+1);
          if((dist<=seuil) && (temp == 0)){
            dst.at<uchar>(a,b+1) = compteur;
            listePix.push_front(b+1);
            listePix.push_front(a);
          }
      }
      expendReg(src,dst,compteur);
    }
}

pair<int,int> premiereOcc(Mat dst){
  //Return the coord of the first pixel without region
  for(int i = 0; i<dst.rows; i++){
    for(int j = 0; j<dst.cols; j++){
      int tmp = dst.at<uchar>(i,j);
      if(tmp == 0){
        pair<int,int> coord = make_pair(i,j);
        return coord;
      }
    }
  }
  pair<int,int> coord = make_pair(-1,-1);
  return coord;
}

EDIT2 : Image i'm using : https://www.bogotobogo.com/Matlab/images/MATLAB_DEMO_IMAGES/blobs.png

  • 4
    You do 2 calls to pop back but you only make sure the size is not zero. What happens if it is only 1? – NathanOliver Apr 02 '19 at 14:57
  • What happens if `listePix.size()` is odd? You inevitably get `size()` at some point and thus the 2 `back()` calls won't work. – Hatted Rooster Apr 02 '19 at 14:58
  • Better to check size or for empty each time before popping.or calling back(). – PrimeOfKnights Apr 02 '19 at 14:59
  • I only put things 2 by 2 in the list. And the "segmentation fault" happened even if the list has more the 200 int in it (tested this using cout << listePix.size() << endl;) – Loïc Chambrion Apr 02 '19 at 15:00
  • Perhaps listePix is a member contained in another object that gets destroyed? I mean the problem may be not in the list itself, but in a wider context (that you do not show). – Igor R. Apr 02 '19 at 15:01
  • 3
    Odd this sounds. [mcve] can we please have? – user4581301 Apr 02 '19 at 15:02
  • 2
    We need a [mcve] then. Undefined behavior can manifest itself in all sorts of ways so it might not even be a problem with the list. – NathanOliver Apr 02 '19 at 15:02
  • I added a pastebin with the full code in it. listePix is not a member of anything. I'm not able to make a "Minimal, Complete and Verifiable example" right now. I can't manage to make openCv work on my computer. I need to be at the university. – Loïc Chambrion Apr 02 '19 at 15:07
  • @LoïcChambrion A [mcve] belongs *in* the question, not behind an external link. And note the "minimal" - it means, strip your code down to the bare minimum that *still compiles* and shows the problem. Remove everything else (*read* the link and see also [SSCCE](http://www.sscce.org)). – Jesper Juhl Apr 02 '19 at 15:12
  • 1
    @LoïcChambrion You'll need to post less code, not more, to get help. That's the reason you see a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) being requested. http://stackoverflow.com is here to help you solve problems you've identified, not to identify problems for you. Here your issue is that `expendReg` is getting called with `listePix` containing only 1 element. We can't help you identify why though from the code you've put here, cause it's not an MCVE. – Jonathan Mee Apr 02 '19 at 15:16
  • I managed to shrink some code to make the "MCVE". With only one "if" in the expendReg function, it works, but with 2 or more, it gives the "Segmentation fault" error. – Loïc Chambrion Apr 02 '19 at 15:41

1 Answers1

0

I suspect a stack overflow may be happening here, because:

Possible fixes

  • Avoid recursion and use an iterative approach
  • Limit recursion depth
CiscoIPPhone
  • 9,457
  • 3
  • 38
  • 42
  • Used a while in the 'agregation' function, and removed the recursion. It worked great after that. Now I face another problem, but this issue is solved now. Thank You ! – Loïc Chambrion Apr 04 '19 at 22:32