如何逐帧应用线段探测器(LSD)?

时间:2011-06-22 14:36:21

标签: c opencv video-processing

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:它没有错误但是当我运行它时会发出一个LSD内部错误:无效的图像输入

2 个答案:

答案 0 :(得分:2)

首先研究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. 

对于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的像素并将它们逐个复制(进行正确的类型转换)到{{1 }}

最后,当您使用完资源后,请不要忘记释放此资源:

image->data

答案 1 :(得分:0)

这个问题前段时间对我有所帮助。你可能已经解决了它已经很抱歉延迟但我现在正在分享答案。

我正在使用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");

希望这有助于您或将来的某个人! LSD非常棒。