Как применить детектор сегмента линии (LSD) к видео, кадр за кадром? - PullRequest
2 голосов
/ 22 июня 2011
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;
}

Примечание: ошибки отсутствуют, но при запуске выдает внутреннюю ошибку LSD: неверный ввод изображения

Ответы [ 2 ]

2 голосов
/ 23 июня 2011

Начните с исследования , как структурирована PGM :

 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. 

Для PGM типа P2 пиксели читаются (ASCII) в файле, но для P5 они не будут, потому чтоони будут храниться в двоичном формате.

Одна важная вещь Вы должны знать, что этот формат занимает всего 1 канал на пиксель.Это означает, что PGM может хранить только СЕРЫЙ масштабированный изображения .Запомните это!

Теперь, если вы используете OpenCV для загрузки изображений из файла, вы должны загрузить их, используя 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;
}

Но если вы используетелюбой другой флаг этой функции, или если вы создаете изображение с cvCreateImage(), или если вы снимаете кадры с камеры или что-то в этом роде, вам нужно преобразовать каждый кадр в его представление в оттенках серого используя cvCvtColor().

Я скачал lsd-1.5 и заметил, что там есть пример, который показывает, как использовать библиотеку.Один из файлов исходного кода с именем lsd_cmd.c вручную читает файл PGM и собирает с ним image_double.Функция, которая делает этот трюк, - read_pgm_image_double(), и она считывает пиксели из файла PGM и сохраняет их внутри image->data.Это важно, потому что если следующее не работает, вам придется перебирать пиксели IplImage и делать это самостоятельно.

После успешной загрузки серого масштабированного изображения в IplImage* cv_img, вы можете попробоватьчтобы создать нужную структуру с помощью:

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

В случае, если это не сработает, вам нужно проверить файл, который я предложил выше, перебрать пиксели cv_img->imageData и скопировать их по одномуодин (делает правильное преобразование типов) в image->data.

В конце не забудьте освободить этот ресурс, когда вы закончите, используя его:

free_image_double(image);
0 голосов
/ 24 октября 2012

Этот вопрос помог мне некоторое время назад.Вы, наверное, уже решили эту проблему, так что извините за задержку, но сейчас я делюсь ответом.

Я использую lsd 1.6, и интерфейс lsd немного отличается от того, который вы используете (они изменили lsdинтерфейс функции от 1,5 до 1,6).

CvCapture* capture;
capture = cvCreateCameraCapture (0);
assert( capture != NULL );

//get capture properties
int width  = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
int height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

//create OpenCV image structs
IplImage *frame;
IplImage *frameBW = cvCreateImage( cvSize( width, height ), IPL_DEPTH_8U, 1 );

//create LSD image type
double *image;
image = (double *) malloc( width * height * sizeof(double) );

while (1) {
    frame = cvQueryFrame( capture );
    if( !frame ) break;

    //convert to grayscale
    cvCvtColor( frame , frameBW, CV_RGB2GRAY);

    //cast into LSD image type
    uchar *data = (uchar *)frameBW->imageData;
    for (i=0;i<width;i++){
    for(j=0;j<height;j++){
        image[ i + j * width ] = data[ i + j * width];
    }
    }

    //run LSD
    double *list;
    int n;
    list = lsd( &n, image, width, height );

    //DO PROCESSING DRAWING ETC

    //draw segments on frame
    for (int j=0; j<n ; j++){       
        //define segment end-points
        CvPoint pt1 = cvPoint(list[ 0 + j * 7 ],list[ 1 + j * 7 ]);
        CvPoint pt2 = cvPoint(list[ 2 + j * 7 ],list[ 3 + j * 7 ]);

        // draw line segment on frame
        cvLine(frame,pt1,pt2,CV_RGB(255,0,0),1.5,8,0);      
    }

    cvShowImage("FRAME WITH LSD",frame);

    //free memory
    free( (void *) list );

    char c = cvWaitKey(1);
    if( c == 27 ) break; // ESC QUITS
}
//free memory
free( (void *) image );

cvReleaseImage( &frame );
cvReleaseImage( &frameBW );
cvDestroyWindow( "FRAME WITH LSD");

Надеюсь, это поможет вам или кому-то в будущем!ЛСД действительно отлично работает.

...