CV_IMPL CvSeq* cvConvexityDefects( const CvArr* array, const CvArr* hullarray, CvMemStorage* storage ) { CvSeq* defects = 0; int i, index; CvPoint* hull_cur; /* is orientation of hull different from contour one */ int rev_orientation; CvContour contour_header; union { CvContour c; CvSeq s; } hull_header; CvSeqBlock block, hullblock; CvSeq *ptseq = (CvSeq*)array, *hull = (CvSeq*)hullarray; CvSeqReader hull_reader; CvSeqReader ptseq_reader; //读序列,应该是读轮廓序列 CvSeqWriter writer; int is_index; if( CV_IS_SEQ( ptseq )) { if( !CV_IS_SEQ_POINT_SET( ptseq )) CV_Error( CV_StsUnsupportedFormat, "Input sequence is not a sequence of points" ); if( !storage ) storage = ptseq->storage; } else { ptseq = cvPointSeqFromMat( CV_SEQ_KIND_GENERIC, array, &contour_header, &block ); } if( CV_SEQ_ELTYPE( ptseq ) != CV_32SC2 ) CV_Error( CV_StsUnsupportedFormat, "Floating-point coordinates are not supported here" ); if( CV_IS_SEQ( hull )) { int hulltype = CV_SEQ_ELTYPE( hull ); if( hulltype != CV_SEQ_ELTYPE_PPOINT && hulltype != CV_SEQ_ELTYPE_INDEX ) CV_Error( CV_StsUnsupportedFormat, "Convex hull must represented as a sequence " "of indices or sequence of pointers" ); if( !storage ) storage = hull->storage; } else { CvMat* mat = (CvMat*)hull; if( !CV_IS_MAT( hull )) CV_Error(CV_StsBadArg, "Convex hull is neither sequence nor matrix"); if( (mat->cols != 1 && mat->rows != 1) || !CV_IS_MAT_CONT(mat->type) || CV_MAT_TYPE(mat->type) != CV_32SC1 ) CV_Error( CV_StsBadArg, "The matrix should be 1-dimensional and continuous array of int's" ); if( mat->cols + mat->rows - 1 > ptseq->total ) CV_Error( CV_StsBadSize, "Convex hull is larger than the point sequence" ); hull = cvMakeSeqHeaderForArray( CV_SEQ_KIND_CURVE|CV_MAT_TYPE(mat->type)|CV_SEQ_FLAG_CLOSED, sizeof(CvContour), CV_ELEM_SIZE(mat->type), mat->data.ptr, mat->cols + mat->rows - 1, &hull_header.s, &hullblock ); } is_index = CV_SEQ_ELTYPE(hull) == CV_SEQ_ELTYPE_INDEX; if( !storage ) CV_Error( CV_StsNullPtr, "NULL storage pointer" ); defects = cvCreateSeq( CV_SEQ_KIND_GENERIC, sizeof(CvSeq), sizeof(CvConvexityDefect), storage ); if( ptseq->total < 4 || hull->total < 3) { //CV_ERROR( CV_StsBadSize, // "point seq size must be >= 4, convex hull size must be >= 3" ); return defects; } /* recognize co-orientation of ptseq and its hull */ { int sign = 0; int index1, index2, index3; if( !is_index ) { CvPoint* pos = *CV_SEQ_ELEM( hull, CvPoint*, 0 ); index1 = cvSeqElemIdx( ptseq, pos ); pos = *CV_SEQ_ELEM( hull, CvPoint*, 1 ); index2 = cvSeqElemIdx( ptseq, pos ); pos = *CV_SEQ_ELEM( hull, CvPoint*, 2 ); index3 = cvSeqElemIdx( ptseq, pos ); } else { index1 = *CV_SEQ_ELEM( hull, int, 0 ); index2 = *CV_SEQ_ELEM( hull, int, 1 ); index3 = *CV_SEQ_ELEM( hull, int, 2 ); } sign += (index2 > index1) ? 1 : 0; sign += (index3 > index2) ? 1 : 0; sign += (index1 > index3) ? 1 : 0; rev_orientation = (sign == 2) ? 0 : 1; } cvStartReadSeq( ptseq, &ptseq_reader, 0 ); cvStartReadSeq( hull, &hull_reader, rev_orientation ); if( !is_index ) { hull_cur = *(CvPoint**)hull_reader.prev_elem; index = cvSeqElemIdx( ptseq, (char*)hull_cur, 0 ); //返回序列中元素的索引 } else { index = *(int*)hull_reader.prev_elem; //prev_elem为指向上一个元素的指针 hull_cur = CV_GET_SEQ_ELEM( CvPoint, ptseq, index ); //从序列中取出所给元素的地址,返回的是指针 } cvSetSeqReaderPos( &ptseq_reader, index ); cvStartAppendToSeq( defects, &writer ); /* cycle through ptseq and hull with computing defects */ //开始计算凸缺陷 for( i = 0; i < hull->total; i++ ) { CvConvexityDefect defect; int is_defect = 0; double dx0, dy0; double depth = 0, scale; CvPoint* hull_next; if( !is_index ) hull_next = *(CvPoint**)hull_reader.ptr; else { int t = *(int*)hull_reader.ptr; hull_next = CV_GET_SEQ_ELEM( CvPoint, ptseq, t ); } dx0 = (double)hull_next->x - (double)hull_cur->x; dy0 = (double)hull_next->y - (double)hull_cur->y; assert( dx0 != 0 || dy0 != 0 ); scale = 1./sqrt(dx0*dx0 + dy0*dy0); defect.start = hull_cur; //凸缺陷的开始点 defect.end = hull_next; //凸缺陷的结束点 for(;;) //这个循环就是用来计算每个凸缺陷的最远距离 { /* go through ptseq to achieve next hull point */ CV_NEXT_SEQ_ELEM( sizeof(CvPoint), ptseq_reader ); if( ptseq_reader.ptr == (schar*)hull_next ) break; else { CvPoint* cur = (CvPoint*)ptseq_reader.ptr; /* compute distance from current point to hull edge */ double dx = (double)cur->x - (double)hull_cur->x; //cur应该是轮廓上的某个点,hull_cur是什么? double dy = (double)cur->y - (double)hull_cur->y; /* compute depth */ double dist = fabs(-dy0*dx + dx0*dy) * scale; //计算距离 if( dist > depth ) //该凸缺陷下所有距离排序,得出最大距离 { depth = dist; defect.depth_point = cur; defect.depth = (float)depth; is_defect = 1; } } } if( is_defect ) { CV_WRITE_SEQ_ELEM( defect, writer ); } hull_cur = hull_next; if( rev_orientation ) { CV_PREV_SEQ_ELEM( hull->elem_size, hull_reader ); } else { CV_NEXT_SEQ_ELEM( hull->elem_size, hull_reader ); } } return cvEndWriteSeq( &writer ); //终止写序列 } 该程序中的depth求取办法就是现根据凸缺陷的初始点和终止点求得凸包线方程,然后遍历凸缺陷下的轮廓(除去凸包线),逐个按点到直线的距离公式求取距离,最后排序得到最远处的点。
opencv凸包求取源码解析
猜你喜欢
转载自blog.csdn.net/hahaha_2017/article/details/80171985
今日推荐
周排行