关于轮廓的遍历,如何解释cvDrawContours函数及相关的数据结构是如何实现轮廓遍历的
来源:互联网 发布:网络教育统考报名网址 编辑:程序博客网 时间:2024/05/13 14:24
下面代码1能够覆盖所有轮廓,但是代码2当出现多个环套接在一起(类似箭靶子的样子)时,就不能把内部的轮廓遍历到
代码1,原版opencv的cvDrawContours函数:
CV_IMPL void
cvDrawContours( void* _img, CvSeq* contour,
CvScalar _externalColor, CvScalar _holeColor,
int maxLevel, int thickness,
int line_type, CvPoint _offset )
{
CvSeq *contour0 = contour, *h_next = 0;
CvTreeNodeIterator iterator;
cv::vector<cv::PolyEdge> edges;
cv::vector<cv::Point> pts;
cv::Scalar externalColor = _externalColor, holeColor = _holeColor;
cv::Mat img = cv::cvarrToMat(_img);
cv::Point offset = _offset;
double ext_buf[4], hole_buf[4];
if( line_type == CV_AA && img.depth() != CV_8U )
line_type = 8;
if( !contour )
return;
CV_Assert( thickness <= 255 );
scalarToRawData( externalColor, ext_buf, img.type(), 0 );
scalarToRawData( holeColor, hole_buf, img.type(), 0 );
maxLevel = MAX(maxLevel, INT_MIN+2);
maxLevel = MIN(maxLevel, INT_MAX-1);
if( maxLevel < 0 )
{
h_next = contour->h_next;
contour->h_next = 0;
maxLevel = -maxLevel+1;
}
cvInitTreeNodeIterator( &iterator, contour, maxLevel );
while( (contour = (CvSeq*)cvNextTreeNode( &iterator )) != 0 )
{
CvSeqReader reader;
int i, count = contour->total;
int elem_type = CV_MAT_TYPE(contour->flags);
void* clr = (contour->flags & CV_SEQ_FLAG_HOLE) == 0 ? ext_buf : hole_buf;
cvStartReadSeq( contour, &reader, 0 );
if( thickness < 0 )
pts.resize(0);
if( CV_IS_SEQ_CHAIN_CONTOUR( contour ))
{
cv::Point pt = ((CvChain*)contour)->origin;
cv::Point prev_pt = pt;
char prev_code = reader.ptr ? reader.ptr[0] : '\0';
prev_pt += offset;
for( i = 0; i < count; i++ )
{
char code;
CV_READ_SEQ_ELEM( code, reader );
assert( (code & ~7) == 0 );
if( code != prev_code )
{
prev_code = code;
if( thickness >= 0 )
cv::ThickLine( img, prev_pt, pt, clr, thickness, line_type, 2, 0 );
else
pts.push_back(pt);
prev_pt = pt;
}
pt.x += CodeDeltas[(int)code][0];
pt.y += CodeDeltas[(int)code][1];
}
if( thickness >= 0 )
cv::ThickLine( img, prev_pt,
cv::Point(((CvChain*)contour)->origin) + offset,
clr, thickness, line_type, 2, 0 );
else
cv::CollectPolyEdges(img, &pts[0], (int)pts.size(),
edges, ext_buf, line_type, 0, offset);
}
else if( CV_IS_SEQ_POLYLINE( contour ))
{
CV_Assert( elem_type == CV_32SC2 );
cv::Point pt1, pt2;
int shift = 0;
count -= !CV_IS_SEQ_CLOSED(contour);
CV_READ_SEQ_ELEM( pt1, reader );
pt1 += offset;
if( thickness < 0 )
pts.push_back(pt1);
for( i = 0; i < count; i++ )
{
CV_READ_SEQ_ELEM( pt2, reader );
pt2 += offset;
if( thickness >= 0 )
cv::ThickLine( img, pt1, pt2, clr, thickness, line_type, 2, shift );
else
pts.push_back(pt2);
pt1 = pt2;
}
if( thickness < 0 )
cv::CollectPolyEdges( img, &pts[0], (int)pts.size(),
edges, ext_buf, line_type, 0, cv::Point() );
}
}
if( thickness < 0 )
cv::FillEdgeCollection( img, edges, ext_buf );
if( h_next && contour0 )
contour0->h_next = h_next;
}
代码2,简化的遍历代码:
////////////////////////////////////////////////////////////////////////////////////////////
CvTreeNodeIterator iterator;
int iOneTourLength=0;
CvSeq *contour = contours;
cvInitTreeNodeIterator(&iterator,contour,3);
//把所有轮廓的点收集起来
CvSeq* allpointsSeq = cvCreateSeq(CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour),
sizeof(CvPoint), storage);
while( 0 != (contour = (CvSeq*)cvNextTreeNode(&iterator)) ){
//找到一个轮廓就可以用for循环提取里面的点了
//这里遍历CvSeq里面的元素的方法很怪异
iOneTourLength = contour->total;
//给点数组分配空间,记得释放
CvPoint *points = (CvPoint *)malloc(sizeof(CvPoint) * iOneTourLength);
//printf("seqlength:%d\n",seqlength);
CvSeqReader reader;
CvPoint pt = cvPoint(0,0);
cvStartReadSeq(contour,&reader);
//开始提取
for(int i = 0 ;i < iOneTourLength; i++){
CV_READ_SEQ_ELEM(pt,reader);
points[i] = pt;
cvSeqPush(allpointsSeq,&pt);
}
//把这个轮廓点找出后,就可以用这些点画个封闭线
cvPolyLine(frmIn1, &points, &iOneTourLength, 1, 1, CV_RGB(0,255,0),2 , 8, 0);
}
////////////////////////////////////////////////////////////////////////////////////////////
代码1,原版opencv的cvDrawContours函数:
CV_IMPL void
cvDrawContours( void* _img, CvSeq* contour,
CvScalar _externalColor, CvScalar _holeColor,
int maxLevel, int thickness,
int line_type, CvPoint _offset )
{
CvSeq *contour0 = contour, *h_next = 0;
CvTreeNodeIterator iterator;
cv::vector<cv::PolyEdge> edges;
cv::vector<cv::Point> pts;
cv::Scalar externalColor = _externalColor, holeColor = _holeColor;
cv::Mat img = cv::cvarrToMat(_img);
cv::Point offset = _offset;
double ext_buf[4], hole_buf[4];
if( line_type == CV_AA && img.depth() != CV_8U )
line_type = 8;
if( !contour )
return;
CV_Assert( thickness <= 255 );
scalarToRawData( externalColor, ext_buf, img.type(), 0 );
scalarToRawData( holeColor, hole_buf, img.type(), 0 );
maxLevel = MAX(maxLevel, INT_MIN+2);
maxLevel = MIN(maxLevel, INT_MAX-1);
if( maxLevel < 0 )
{
h_next = contour->h_next;
contour->h_next = 0;
maxLevel = -maxLevel+1;
}
cvInitTreeNodeIterator( &iterator, contour, maxLevel );
while( (contour = (CvSeq*)cvNextTreeNode( &iterator )) != 0 )
{
CvSeqReader reader;
int i, count = contour->total;
int elem_type = CV_MAT_TYPE(contour->flags);
void* clr = (contour->flags & CV_SEQ_FLAG_HOLE) == 0 ? ext_buf : hole_buf;
cvStartReadSeq( contour, &reader, 0 );
if( thickness < 0 )
pts.resize(0);
if( CV_IS_SEQ_CHAIN_CONTOUR( contour ))
{
cv::Point pt = ((CvChain*)contour)->origin;
cv::Point prev_pt = pt;
char prev_code = reader.ptr ? reader.ptr[0] : '\0';
prev_pt += offset;
for( i = 0; i < count; i++ )
{
char code;
CV_READ_SEQ_ELEM( code, reader );
assert( (code & ~7) == 0 );
if( code != prev_code )
{
prev_code = code;
if( thickness >= 0 )
cv::ThickLine( img, prev_pt, pt, clr, thickness, line_type, 2, 0 );
else
pts.push_back(pt);
prev_pt = pt;
}
pt.x += CodeDeltas[(int)code][0];
pt.y += CodeDeltas[(int)code][1];
}
if( thickness >= 0 )
cv::ThickLine( img, prev_pt,
cv::Point(((CvChain*)contour)->origin) + offset,
clr, thickness, line_type, 2, 0 );
else
cv::CollectPolyEdges(img, &pts[0], (int)pts.size(),
edges, ext_buf, line_type, 0, offset);
}
else if( CV_IS_SEQ_POLYLINE( contour ))
{
CV_Assert( elem_type == CV_32SC2 );
cv::Point pt1, pt2;
int shift = 0;
count -= !CV_IS_SEQ_CLOSED(contour);
CV_READ_SEQ_ELEM( pt1, reader );
pt1 += offset;
if( thickness < 0 )
pts.push_back(pt1);
for( i = 0; i < count; i++ )
{
CV_READ_SEQ_ELEM( pt2, reader );
pt2 += offset;
if( thickness >= 0 )
cv::ThickLine( img, pt1, pt2, clr, thickness, line_type, 2, shift );
else
pts.push_back(pt2);
pt1 = pt2;
}
if( thickness < 0 )
cv::CollectPolyEdges( img, &pts[0], (int)pts.size(),
edges, ext_buf, line_type, 0, cv::Point() );
}
}
if( thickness < 0 )
cv::FillEdgeCollection( img, edges, ext_buf );
if( h_next && contour0 )
contour0->h_next = h_next;
}
代码2,简化的遍历代码:
////////////////////////////////////////////////////////////////////////////////////////////
CvTreeNodeIterator iterator;
int iOneTourLength=0;
CvSeq *contour = contours;
cvInitTreeNodeIterator(&iterator,contour,3);
//把所有轮廓的点收集起来
CvSeq* allpointsSeq = cvCreateSeq(CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour),
sizeof(CvPoint), storage);
while( 0 != (contour = (CvSeq*)cvNextTreeNode(&iterator)) ){
//找到一个轮廓就可以用for循环提取里面的点了
//这里遍历CvSeq里面的元素的方法很怪异
iOneTourLength = contour->total;
//给点数组分配空间,记得释放
CvPoint *points = (CvPoint *)malloc(sizeof(CvPoint) * iOneTourLength);
//printf("seqlength:%d\n",seqlength);
CvSeqReader reader;
CvPoint pt = cvPoint(0,0);
cvStartReadSeq(contour,&reader);
//开始提取
for(int i = 0 ;i < iOneTourLength; i++){
CV_READ_SEQ_ELEM(pt,reader);
points[i] = pt;
cvSeqPush(allpointsSeq,&pt);
}
//把这个轮廓点找出后,就可以用这些点画个封闭线
cvPolyLine(frmIn1, &points, &iOneTourLength, 1, 1, CV_RGB(0,255,0),2 , 8, 0);
}
////////////////////////////////////////////////////////////////////////////////////////////
- 关于轮廓的遍历,如何解释cvDrawContours函数及相关的数据结构是如何实现轮廓遍历的
- 轮廓提取cvDrawContours 函数和cvDrawContours函数的使用
- opencv轮廓相关的函数
- cvFindContours && cvDrawContours 的应用2-----图像内轮廓填充
- cvFindContours && cvDrawContours 的应用2-----图像内轮廓填充
- 轮廓、边缘、边界的相关函数
- OpenCV轮廓、边缘、边界的相关函数
- 如何编程读取墙的轮廓线
- 关于轮廓的各种使用
- 关于轮廓的各种使用
- 关于轮廓的各种使用
- 关于轮廓的各种使用
- 关于轮廓的各种使用
- CvDrawContours绘制轮廓
- cvDrawContours绘制轮廓
- OpenCV 与轮廓相关的一些函数
- 树的遍历及相关递归函数
- 使用OpenCV的函数findContours提取轮廓并绘制轮廓
- Android中LayoutInflater实例
- Web开发经验
- 黑马程序员-高新技术(反射)
- hdu3397 Sequence operation(线段树成段更新)
- 什么是离屏表面
- 关于轮廓的遍历,如何解释cvDrawContours函数及相关的数据结构是如何实现轮廓遍历的
- php 函数小记quotemeta
- 开发者需知的10类工具
- poj2996 Help Me with the Game
- dreamweaver配置PHP服务器
- 最常见的20种VC++编译错误信息
- sizeof(string)
- qt-everywhere-opensource-src-4.8.1移植到2440、6410
- cocos2d-x在android下添加插屏广告