Search code examples
copencvvideo-processing

How to apply line segment detector (LSD) on a video , frame by frame?


int main()
{
  image_double image;
  ntuple_list out;
  unsigned int xsize,ysize,depth;
  int x,y,i,j,width,height,step;
  uchar *p;
  IplImage* img = 0; 
  IplImage* dst = 0;
  img = cvLoadImage("D:\\Ahram.jpg",CV_LOAD_IMAGE_COLOR);
  width = img->width;
  height = img->height;
  dst=cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,1);
  cvCvtColor(img,dst,CV_RGB2GRAY);

  width=dst->width;
  height=dst->height;
  step=dst->widthstep;
  p=(uchar*)dst->imageData;
  image=new_image_double(dst->width,dst->height);
  xsize=dst->width;
  for(i=0;i<height;i++)
  {
      for(j=0;j<width;j++)
      {
         image->data[i+j*xsize]=p[i*step+j];

      }

  }


/* call LSD */

out = lsd(dst);

  /* print output */
  printf("%u line segments found:\n",out->size);
  for(i=0;i<out->size;i++)
    {
      for(j=0;j<out->dim;j++)
        printf("%f ",out->values[ i * out->dim + j ]);
      printf("\n");
    }


  /* free memory */
  free_image_double(image);
  free_ntuple_list(out);

  return 0;
}

N.B:it has no errors but when i run it gives out an LSD internal error:invalid image input


Solution

  • Start by researching how PGM is structured:

     Each PGM image consists of the following:
       1. A "magic number" for identifying the file type. 
          A pgm image's magic number is the two characters "P5".
       2. Whitespace (blanks, TABs, CRs, LFs).
       3. A width, formatted as ASCII characters in decimal.
       4. Whitespace.
       5. A height, again in ASCII decimal.
       6. Whitespace.
       7. The maximum gray value (Maxval), again in ASCII decimal. 
          Must be less than 65536, and more than zero.
       8. A single whitespace character (usually a newline).
       9. A raster of Height rows, in order from top to bottom. 
          Each row consists of Width gray values, in order from left to right. 
          Each gray value is a number from 0 through Maxval, with 0 being black 
           and Maxval being white. Each gray value is represented in pure binary 
           by either 1 or 2 bytes. If the Maxval is less than 256, it is 1 byte. 
          Otherwise, it is 2 bytes. The most significant byte is first. 
    

    For PGM type P2, pixels are readable (ASCII) on the file, but for P5 they won't be because they will be stored in binary format.

    One important thing you should know, is that this format takes only 1 channel per pixel. This means PGM can only store GREY scaled images. Remember this!

    Now, if you're using OpenCV to load images from a file, you should load them using CV_LOAD_IMAGE_GRAYSCALE:

    IplImage* cv_img = cvLoadImage("chairs.png", CV_LOAD_IMAGE_GRAYSCALE);
    if(!cv_img)
    {
        std::cout << "ERROR: cvLoadImage failed" << std::endl;
        return -1;
    }
    

    But if you use any other flag on this function or if you create an image with cvCreateImage(), or if you're capturing frames from a camera or something like that, you'll need to convert each frame to its grayscale representation using cvCvtColor().

    I downloaded lsd-1.5 and noticed that there is an example there that shows how to use the library. One of the source code files, named lsd_cmd.c, manually reads a PGM file and assembles an image_double with it. The function that does this trick is read_pgm_image_double(), and it reads the pixels from a PGM file and stores them inside image->data. This is important because if the following does not work, you'll have to iterate on the pixels of IplImage and do this yourself.

    After successfully loading a gray scaled image into IplImage* cv_img, you can try to create the structure you need with:

    image_double image = new_image_double(cv_img->width, cv_img->height); 
    image->data = (double) cv_img->imageData;
    

    In case this doesn't work, you'll need to check the file I suggested above and iterate through the pixels of cv_img->imageData and copy them one by one (doing the proper type conversion) to image->data.

    At the end, don't forget to free this resource when you're done using it:

    free_image_double(image);