cvseqpush cvgetseqelem 压入一个结构体指针时的陷阱

 一张图片经过二值化处理后,用cvfindcontours找出所有的轮廓,根据先验条件来筛选这些轮廓,
将合格的压入CvSeq, 然后将合格的取出,再得到这些轮廓上的点,做下一步分析,为了方便,我把下一步分析的工作 设置 为输出点,并将点一一画出。 

int main(int argc, char* argv[])
     {
   IplImage *src=cvLoadImage("d:/1.bmp",0);
   
   IplImage *dst=cvCreateImage(cvSize(src->width,src->height),8,3);
   
   CvMemStorage *stor=cvCreateMemStorage(0);
   
   CvSeq *seq_cont=cvCreateSeq(CV_SEQ_ELTYPE_POINT,sizeof(CvSeq),sizeof(CvPoint),stor);   //储存合格的轮廓
   
   CvSeq *cont=NULL;
   
   int i=0,j=0;
   int num=cvFindContours(src,stor,&cont,sizeof(CvContour),CV_RETR_LIST);      //记录总轮廓数
   

   int *length=new int[num];   //每个轮廓都有不同的点数,所以length[i]的值就是第i个轮廓上的点数。这里不太好理解,只能想出这样的办法了。
   
   for (i=0;i<num;i++)length[i]=0;      //
   
   for (i=0;cont;cont=cont->h_next)   //开始遍历全部的轮廓
   {   
      /*为了简单,假设全部都符合条件*/
      cvSeqPush(seq_cont,cont);         //将轮廓压入
      
      length[i++]=cont->total;         //记录每个轮廓上的点个数,为下面的分配数组做准备。
   }
   
   for (i=0;i<num;i++)
   {
      CvPoint *point=new CvPoint[length[i]];      //分配不同长度的数组,为了存储每个轮廓的点坐标。
      
      CvSeq* c=(CvSeq*)cvGetSeqElem(seq_cont,i);   //将每个轮廓取出
      
      CvSeqReader reader;

      CvPoint pt=cvPoint(0,0);

      cvStartReadSeq(c,&reader);/*程序在此出现错误,令我感到奇怪的是,当我直接执行(ctrl+F5),没有异常提示,当然也没结果。
                 但是当我单步调试的时候,却出现了错误。进入cvStartReadSeq()会发现,异常出现在这一步
                 reader->ptr = first_block->data;  cxdatastructs.cpp  第1114行,
                 这一行的作用我觉得是把轮廓的数据块的地址赋给reader。觉得问题出在cvseqpush () 或者是cvSeqgetElem()中。
                  能是在获得元素的时候执行的是浅复制。但是自己看代码的时候在却没有找到证据。 */

      for (j=0;j<c->total;j++)
      {
         CV_READ_SEQ_ELEM(pt,reader);
         point[j]=pt;
         cout<<pt.x<<"  "<<pt.y<<endl;         //运行的时候这一步没有执行,
      }
      for (j=0;j<c->total;j++)            //画出每个轮廓上的点
      {
         int k=(j+1)%c->total;
         cvLine(dst,point[j],point[k],cvScalar(0,0,255),1,4,0);
      }
      
      delete point;
   }
   
   cvNamedWindow("dst",1);
   cvShowImage("dst",dst);
   cvWaitKey(0);
   
   cvReleaseMemStorage(&stor);
   cvDestroyWindow("dst");
   cvReleaseImage(&dst);
   return 0;
 }

问题出在cvSeqPush(seq_cont,cont);
自己压进去的是一个轮廓的指针(占4个字节),但是在这个序列里每个元素却是占56个字节的CvSeq结构体变量。
所以在压入的时候必须是一个完整的结构体变量的地址(因为CvSeqPush()的第二个参数是一个指针变量,而且在这个函数内部会进行深度复制,就是把这个结构体的内容完全copy并在加入到栈底.)

只需要在压栈前 加入一行,就可搞定,当然压入栈的不再是cont,而是&seq.
CvSeq seq=*cont;
cvSeqPush(seq_cont,&seq);

另外还需要注意的是
CvSeq *seq_cont=cvCreateSeq(CV_SEQ_ELTYPE_GENERIC,sizeof(CvSeq),sizeof(CvSeq),stor);

就是第一个参数设置为CV_SEQ_ELTYPE_GENRIC。

 

详情可查看:http://www.opencv.org.cn/forum/viewtopic.php?f=1&t=8652

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值