CvLCMEdge* _cvConstructLCMEdge(CvLCM* pLCM, CvLCMData* pLCMInputData) { CvVoronoiEdge2D* pEdge = pLCMInputData->pedge; CvVoronoiSite2D* pSite = pLCMInputData->psite; float width = 0; CvLCMData LCMData; CvVoronoiNode2D* pNode0,*pNode1; CvLCMEdge* pLCMEdge = _cvCreateLCMEdge(pLCM); CvSeqWriter writer; cvStartAppendToSeq(pLCMEdge->chain,&writer ); pNode0 = pNode1 = pLCMInputData->pnode; CV_WRITE_SEQ_ELEM(pNode0->pt, writer); width += pNode0->radius; for(int counter = 0; counter < pLCM->VoronoiDiagram->edges->total; counter++) { pNode1 = CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite); if(pNode1->radius >= pLCM->maxWidth) goto CREATECOMPLEXNODE; CV_WRITE_SEQ_ELEM(pNode1->pt,writer); width += pNode1->radius; _CV_INITIALIZE_CVLCMDATA(&LCMData,pSite,pEdge,pNode1); if(_cvConstructLCMSimpleNode(pLCM,pLCMEdge,&LCMData)) goto LCMEDGEEXIT; pEdge = LCMData.pedge; pSite = LCMData.psite; pNode0 = pNode1; } return NULL; CREATECOMPLEXNODE: _CV_INITIALIZE_CVLCMDATA(&LCMData,pSite,pEdge,pNode0); CV_WRITE_SEQ_ELEM(LCMData.pnode->pt,writer); width += LCMData.pnode->radius; _cvConstructLCMComplexNode(pLCM,pLCMEdge,&LCMData); LCMEDGEEXIT: cvEndWriteSeq(&writer); pLCMEdge->width = width/pLCMEdge->chain->total; return pLCMEdge; }//end of _cvConstructLCMEdge
static void icvCalcAndWritePtIndices( CvPoint** pointer, int* stack, int start, int end, CvSeq* ptseq, CvSeqWriter* writer ) { CV_FUNCNAME( "icvCalcAndWritePtIndices" ); __BEGIN__; int i, incr = start < end ? 1 : -1; int idx, first_idx = ptseq->first->start_index; for( i = start; i != end; i += incr ) { CvPoint* ptr = (CvPoint*)pointer[stack[i]]; CvSeqBlock* block = ptseq->first; while( (unsigned)(idx = (int)(ptr - (CvPoint*)block->data)) >= (unsigned)block->count ) { block = block->next; if( block == ptseq->first ) CV_ERROR( CV_StsError, "Internal error" ); } idx += block->start_index - first_idx; CV_WRITE_SEQ_ELEM( idx, *writer ); } __END__; }
void Blob::copy_edges(const CvSeq* _edges) { CV_FUNCNAME( "Blob::copy_edges" ); __BEGIN__; cvClearSeq(this->edges_); //- copy the given sequence CvSeqReader seq_reader; CvSeqWriter seq_writer; CvPoint current_edge; int i; CV_CALL( cvStartReadSeq( _edges, &seq_reader) ); CV_CALL( cvStartAppendToSeq( this->edges_, &seq_writer ) ); for( i = 0; i < _edges->total; i++) { CV_READ_SEQ_ELEM ( current_edge , seq_reader); CV_WRITE_SEQ_ELEM( current_edge , seq_writer ); } CV_CALL( cvEndWriteSeq( &seq_writer ) ); __END__; __ISL_CHECK_ERROR__; }
//! Calculate contour points from crack codes t_PointList CBlobContour::GetContourPoints() { // it is calculated? if( m_contourPoints != NULL ) return m_contourPoints; if ( m_contour == NULL || m_contour->total <= 0 ) { return NULL; } CvSeq *tmpPoints; CvSeqReader reader; CvSeqWriter writer; CvPoint actualPoint; CvRect boundingBox; // if aproximation is different than simple extern perimeter will not work tmpPoints = cvApproxChains( m_contour, m_parentStorage, CV_CHAIN_APPROX_NONE); // apply an offset to contour points to recover real coordinates cvStartReadSeq( tmpPoints, &reader); m_contourPoints = cvCreateSeq( tmpPoints->flags, tmpPoints->header_size, tmpPoints->elem_size, m_parentStorage ); cvStartAppendToSeq(m_contourPoints, &writer ); // also calculate bounding box of the contour to allow cvPointPolygonTest // work correctly on the generated polygon boundingBox.x = boundingBox.y = 10000; boundingBox.width = boundingBox.height = 0; for( int i=0; i< tmpPoints->total; i++) { CV_READ_SEQ_ELEM( actualPoint, reader); actualPoint.x += m_startPoint.x; actualPoint.y += m_startPoint.y; boundingBox.x = MIN( boundingBox.x, actualPoint.x ); boundingBox.y = MIN( boundingBox.y, actualPoint.y ); boundingBox.width = MAX( boundingBox.width, actualPoint.x ); boundingBox.height = MAX( boundingBox.height, actualPoint.y ); CV_WRITE_SEQ_ELEM( actualPoint, writer ); } cvEndWriteSeq( &writer ); cvClearSeq( tmpPoints ); // assign calculated bounding box ((CvContour*)m_contourPoints)->rect = boundingBox; return m_contourPoints; }
/** - FUNCTION: Assigment operator - FUNCTIONALITY: Assigns a blob to the current - PARAMETERS: - src: blob to assign - RESULT: - the current blob is replaced by the src blob - RESTRICTIONS: - AUTHOR: Ricard Borr� - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ CBlob& CBlob::operator=(const CBlob &src ) { // si ja s� el mateix, no cal fer res if (this != &src) { // Eliminar v�texs del blob cvClearSeq(edges); // i la zona de mem�ia on s� cvReleaseMemStorage( &m_storage ); // creem una sequencia buida per als edges m_storage = cvCreateMemStorage(0); edges = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour), sizeof(CvPoint),m_storage); // copiem les propietats del blob origen a l'actual etiqueta = src.etiqueta; exterior = src.exterior; area = src.Area(); perimeter = src.Perimeter(); parent = src.parent; minx = src.minx; maxx = src.maxx; miny = src.miny; maxy = src.maxy; sumx = src.sumx; sumy = src.sumy; sumxx = src.sumxx; sumyy = src.sumyy; sumxy = src.sumxy; mean = src.mean; stddev = src.stddev; externPerimeter = src.externPerimeter; // copiem els edges del blob origen a l'actual CvSeqReader reader; CvSeqWriter writer; CvPoint edgeactual; cvStartReadSeq( src.Edges(), &reader); cvStartAppendToSeq( edges, &writer ); for( int i=0; i< src.Edges()->total; i++) { CV_READ_SEQ_ELEM( edgeactual ,reader); CV_WRITE_SEQ_ELEM( edgeactual , writer ); } cvEndWriteSeq( &writer ); } return *this; }
/** - FUNCTION: JoinBlob - FUNCTIONALITY: Add's external contour to current external contour - PARAMETERS: - blob: blob from which extract the added external contour - RESULT: - true if no error ocurred - RESTRICTIONS: Only external contours are added - AUTHOR: Ricard Borràs - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ void CBlob::JoinBlob( CBlob *blob ) { CvSeqWriter writer; CvSeqReader reader; t_chainCode chainCode; cvStartAppendToSeq( m_externalContour.GetChainCode(), &writer ); cvStartReadSeq( blob->GetExternalContour()->GetChainCode(), &reader ); for (int i = 0; i < blob->GetExternalContour()->GetChainCode()->total; i++ ) { CV_READ_SEQ_ELEM( chainCode, reader ); CV_WRITE_SEQ_ELEM( chainCode, writer ); } cvEndWriteSeq( &writer ); }
/** - FUNCTION: CopyEdges - FUNCTIONALITY: Adds the blob edges to destination - PARAMETERS: - destination: where to add the edges - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borr� - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ void CBlob::CopyEdges( CBlob &destination ) const { CvSeqReader reader; CvSeqWriter writer; CvPoint edgeactual; cvStartReadSeq( edges, &reader); cvStartAppendToSeq( destination.Edges(), &writer ); for( int i=0; i<edges->total; i++) { CV_READ_SEQ_ELEM( edgeactual ,reader); CV_WRITE_SEQ_ELEM( edgeactual , writer ); } cvEndWriteSeq( &writer ); }
/** - FUNCTION: CBlob - FUNCTIONALITY: Copy constructor - PARAMETERS: - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borr� - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ CBlob::CBlob( const CBlob &src ) { // copiem les propietats del blob origen a l'actual etiqueta = src.etiqueta; exterior = src.exterior; area = src.Area(); perimeter = src.Perimeter(); parent = src.parent; minx = src.minx; maxx = src.maxx; miny = src.miny; maxy = src.maxy; sumx = src.sumx; sumy = src.sumy; sumxx = src.sumxx; sumyy = src.sumyy; sumxy = src.sumxy; mean = src.mean; stddev = src.stddev; externPerimeter = src.externPerimeter; // copiem els edges del blob origen a l'actual CvSeqReader reader; CvSeqWriter writer; CvPoint edgeactual; // creem una sequencia buida per als edges m_storage = cvCreateMemStorage(0); edges = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour), sizeof(CvPoint),m_storage); cvStartReadSeq( src.Edges(), &reader); cvStartAppendToSeq( edges, &writer ); for( int i=0; i< src.Edges()->total; i++) { CV_READ_SEQ_ELEM( edgeactual ,reader); CV_WRITE_SEQ_ELEM( edgeactual , writer ); } cvEndWriteSeq( &writer ); }
void Blob::filter(int x_min, int y_min, int x_max, int y_max) { CvMemStorage* new_storage = 0; CvSeq* new_edges = 0; CV_FUNCNAME( "Blob::filter" ); __BEGIN__; CV_CALL( new_storage = cvCreateMemStorage(0) ); CV_CALL( new_edges = cvCreateSeq(CV_SEQ_ELTYPE_POINT | CV_SEQ_KIND_CURVE, sizeof(CvContour), sizeof(CvPoint) , new_storage) ); CvSeqReader seq_reader; CvSeqWriter seq_writer; CvPoint current_edge; int i; CV_CALL( cvStartReadSeq( this->edges_, &seq_reader) ); CV_CALL( cvStartAppendToSeq( new_edges, &seq_writer ) ); for( i = 0; i < this->edges_->total; i++) { CV_READ_SEQ_ELEM ( current_edge , seq_reader); if ( current_edge.x >= x_min && current_edge.y >= y_min && current_edge.x <= x_max && current_edge.y <= y_max ) { CV_WRITE_SEQ_ELEM( current_edge , seq_writer); } } CV_CALL( cvEndWriteSeq( &seq_writer ) ); __END__; __ISL_CHECK_ERROR__; }
/***************************************************************************************\ * * This function compute intermediate polygon between contour1 and contour2 * * Correspondence between points of contours specify by corr * * param = [0,1]; 0 correspondence to contour1, 1 - contour2 * \***************************************************************************************/ CvSeq* icvBlendContours(CvSeq* contour1, CvSeq* contour2, CvSeq* corr, double param, CvMemStorage* storage) { int j; CvSeqWriter writer01; CvSeqReader reader01; int Ni,Nj; // size of contours int i; // counter CvPoint* point1; // array of first contour point CvPoint* point2; // array of second contour point CvPoint point_output; // intermediate storage of ouput point int corr_point; // Create output sequence. CvSeq* output = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvPoint), storage ); // Find size of contours. Ni = contour1->total + 1; Nj = contour2->total + 1; point1 = (CvPoint* )malloc( Ni*sizeof(CvPoint) ); point2 = (CvPoint* )malloc( Nj*sizeof(CvPoint) ); // Initialize arrays of point cvCvtSeqToArray( contour1, point1, CV_WHOLE_SEQ ); cvCvtSeqToArray( contour2, point2, CV_WHOLE_SEQ ); // First and last point mast be equal. point1[Ni-1] = point1[0]; point2[Nj-1] = point2[0]; // Initializes process of writing to sequence. cvStartAppendToSeq( output, &writer01); i = Ni-1; //correspondence to points of contour1 for( ; corr; corr = corr->h_next ) { //Initializes process of sequential reading from sequence cvStartReadSeq( corr, &reader01, 0 ); for(j=0; j < corr->total; j++) { // Read element from sequence. CV_READ_SEQ_ELEM( corr_point, reader01 ); // Compute point of intermediate polygon. point_output.x = cvRound(point1[i].x + param*( point2[corr_point].x - point1[i].x )); point_output.y = cvRound(point1[i].y + param*( point2[corr_point].y - point1[i].y )); // Write element to sequence. CV_WRITE_SEQ_ELEM( point_output, writer01 ); } i--; } // Updates sequence header. cvFlushSeqWriter( &writer01 ); return output; }
static CvStatus CV_STDCALL icvFindHandRegion( CvPoint3D32f * points, int count, CvSeq * indexs, float *line, CvSize2D32f size, int flag, CvPoint3D32f * center, CvMemStorage * storage, CvSeq ** numbers ) { /* IppmVect32f sub, cros; */ float *sub, *cros; CvSeqWriter writer; CvSeqReader reader; CvStatus status; int nbins = 20, i, l, i_point, left, right; int *bin_counts = 0; // pointer to the point's counter in the bickets int low_count; // low threshold CvPoint *tmp_number = 0, *pt; float value, vmin, vmax, vl, bsize, vc; float hand_length, hand_length2, hand_left, hand_right; float threshold, threshold2; float *vv = 0; float a[3]; status = CV_OK; hand_length = size.width; hand_length2 = hand_length / 2; threshold = (float) (size.height * 3 / 5.); threshold2 = threshold * threshold; /* low_count = count/nbins; */ low_count = (int) (count / 60.); assert( points != NULL && line != NULL ); if( points == NULL || line == NULL ) return CV_NULLPTR_ERR; assert( count > 5 ); if( count < 5 ) return CV_BADFLAG_ERR; assert( flag == 0 || flag == 1 ); if( flag != 0 && flag != 1 ) return CV_BADFLAG_ERR; /* create vectors */ sub = icvCreateVector_32f( 3 ); cros = icvCreateVector_32f( 3 ); if( sub == NULL || cros == NULL ) return CV_OUTOFMEM_ERR; /* alloc memory for the point's projections on the line */ vv = (float *) cvAlloc( count * sizeof( float )); if( vv == NULL ) return CV_OUTOFMEM_ERR; /* alloc memory for the point's counter in the bickets */ bin_counts = (int *) cvAlloc( nbins * sizeof( int )); if( bin_counts == NULL ) { status = CV_OUTOFMEM_ERR; goto M_END; } memset( bin_counts, 0, nbins * sizeof( int )); cvStartReadSeq( indexs, &reader, 0 ); /* alloc memory for the temporale point's numbers */ tmp_number = (CvPoint *) cvAlloc( count * sizeof( CvPoint )); if( tmp_number == NULL ) { status = CV_OUTOFMEM_ERR; goto M_END; } /* find min and max point's projection on the line */ vmin = 1000; vmax = -1000; i_point = 0; for( i = 0; i < count; i++ ) { /* icvSubVector_32f ((IppmVect32f )&points[i], (IppmVect32f )&line[3], sub, 3); icvCrossProduct2L_32f ((IppmVect32f )&line[0], sub, cros); */ sub[0] = points[i].x - line[3]; sub[1] = points[i].y - line[4]; sub[2] = points[i].z - line[5]; a[0] = sub[0] * line[1] - sub[1] * line[0]; a[1] = sub[1] * line[2] - sub[2] * line[1]; a[2] = sub[2] * line[0] - sub[0] * line[2]; /* if(IPPI_NORM_L22 ( cros ) < threshold2) */ if( _CV_NORM_L22( a ) < threshold2 ) { value = (float)icvDotProduct_32f( sub, &line[0], 3 ); if( value > vmax ) vmax = value; if( value < vmin ) vmin = value; vv[i_point] = value; pt = (CvPoint*)cvGetSeqElem( indexs, i ); tmp_number[i_point] = *pt; i_point++; } } /* compute the length of one bucket */ vl = vmax - vmin; bsize = vl / nbins; /* compute the number of points in each bucket */ for( i = 0; i < i_point; i++ ) { l = cvRound( (vv[i] - vmin) / bsize ); bin_counts[l]++; } *numbers = cvCreateSeq( CV_SEQ_POINT_SET, sizeof( CvSeq ), sizeof( CvPoint ), storage ); assert( numbers != 0 ); if( numbers == NULL ) { status = CV_OUTOFMEM_ERR; goto M_END; } cvStartAppendToSeq( *numbers, &writer ); if( flag == 0 ) { /* find the leftmost bucket */ for( l = 0; l < nbins; l++ ) { if( bin_counts[l] > low_count ) break; } left = l; /* compute center point of the left hand */ hand_left = vmin + left * bsize; vc = hand_left + hand_length2; hand_right = hand_left + hand_length; } else { /* find the rightmost bucket */ for( l = nbins - 1; l >= 0; l-- ) { if( bin_counts[l] > low_count ) break; } right = l; /* compute center point of the right hand */ hand_right = vmax - (nbins - right - 1) * bsize; vc = hand_right - hand_length2; hand_left = hand_right - hand_length; } icvScaleVector_32f( &line[0], sub, 3, vc ); icvAddVector_32f( &line[3], sub, (float *) center, 3 ); /* select hand's points and calculate mean value */ //ss.x = ss.y = ss.z = 0; for( l = 0; l < i_point; l++ ) { if( vv[l] >= hand_left && vv[l] <= hand_right ) { CV_WRITE_SEQ_ELEM( tmp_number[l], writer ); } } cvEndWriteSeq( &writer ); M_END: if( tmp_number != NULL ) cvFree( &tmp_number ); if( bin_counts != NULL ) cvFree( &bin_counts ); if( vv != NULL ) cvFree( &vv ); if( sub != NULL ) icvDeleteVector (sub); if( cros != NULL ) icvDeleteVector (cros); return status; }
static CvStatus CV_STDCALL icvFindHandRegionA( CvPoint3D32f * points, int count, CvSeq * indexs, float *line, CvSize2D32f size, int jc, CvPoint3D32f * center, CvMemStorage * storage, CvSeq ** numbers ) { /* IppmVect32f sub, cros; */ float *sub, *cros; float eps = (float) 0.01; CvSeqWriter writer; CvSeqReader reader; CvStatus status; float gor[3] = { 1, 0, 0 }; float ver[3] = { 0, 1, 0 }; int nbins = 20, i, l, i_point, left, right, jmin, jmax, jl; int j_left, j_right; int *bin_counts = 0; // pointer to the point's counter in the bickets // int *bin_countsj = 0; // pointer to the index's counter in the bickets int low_count; // low threshold CvPoint *tmp_number = 0, *pt; float value, vmin, vmax, vl, bsize, bsizej, vc, vcl, vcr; double v_ver, v_gor; float hand_length, hand_length2, hand_left, hand_right; float threshold, threshold2; float *vv = 0; float a[3]; char log; status = CV_OK; hand_length = size.width; hand_length2 = hand_length / 2; threshold = (float) (size.height * 3 / 5.); threshold2 = threshold * threshold; /* low_count = count/nbins; */ low_count = (int) (count / 60.); assert( points != NULL && line != NULL ); if( points == NULL || line == NULL ) return CV_NULLPTR_ERR; assert( count > 5 ); if( count < 5 ) return CV_BADFLAG_ERR; /* create vectors */ sub = icvCreateVector_32f( 3 ); cros = icvCreateVector_32f( 3 ); if( sub == NULL || cros == NULL ) return CV_OUTOFMEM_ERR; /* alloc memory for the point's projections on the line */ vv = (float *) cvAlloc( count * sizeof( float )); if( vv == NULL ) return CV_OUTOFMEM_ERR; /* alloc memory for the point's counter in the bickets */ bin_counts = (int *) cvAlloc( nbins * sizeof( int )); if( bin_counts == NULL ) { status = CV_OUTOFMEM_ERR; goto M_END; } memset( bin_counts, 0, nbins * sizeof( int )); /* alloc memory for the point's counter in the bickets */ // bin_countsj = (int*) icvAlloc(nbins*sizeof(int)); // if(bin_countsj == NULL) {status = CV_OUTOFMEM_ERR; goto M_END;} // memset(bin_countsj,0,nbins*sizeof(int)); cvStartReadSeq( indexs, &reader, 0 ); /* alloc memory for the temporale point's numbers */ tmp_number = (CvPoint *) cvAlloc( count * sizeof( CvPoint )); if( tmp_number == NULL ) { status = CV_OUTOFMEM_ERR; goto M_END; } /* find min and max point's projection on the line */ vmin = 1000; vmax = -1000; jmin = 1000; jmax = -1000; i_point = 0; for( i = 0; i < count; i++ ) { /* icvSubVector_32f ((IppmVect32f )&points[i], (IppmVect32f )&line[3], sub, 3); icvCrossProduct2L_32f ((IppmVect32f )&line[0], sub, cros); */ sub[0] = points[i].x - line[3]; sub[1] = points[i].y - line[4]; sub[2] = points[i].z - line[5]; // if(fabs(sub[0])<eps||fabs(sub[1])<eps||fabs(sub[2])<eps) continue; a[0] = sub[0] * line[1] - sub[1] * line[0]; a[1] = sub[1] * line[2] - sub[2] * line[1]; a[2] = sub[2] * line[0] - sub[0] * line[2]; v_gor = icvDotProduct_32f( gor, &line[0], 3 ); v_ver = icvDotProduct_32f( ver, &line[0], 3 ); if( v_ver > v_gor ) log = true; else log = false; /* if(IPPI_NORM_L22 ( cros ) < threshold2) */ /* if(fabs(a[0])<eps && fabs(a[1])<eps && fabs(a[2])<eps) { icvDotProduct_32f( sub, &line[0], 3, &value); if(value > vmax) vmax = value; if(value < vmin) vmin = value; vv[i_point] = value; pt = (CvPoint* )icvGetSeqElem ( indexs, i, 0); if(pt->x > jmax) jmax = pt->x; if(pt->x < jmin) jmin = pt->x; tmp_number[i_point] = *pt; i_point++; } else */ { if( _CV_NORM_L32( a ) < threshold2 ) { value = (float)icvDotProduct_32f( sub, &line[0], 3 ); if( value > vmax ) vmax = value; if( value < vmin ) vmin = value; vv[i_point] = value; pt = (CvPoint*)cvGetSeqElem( indexs, i ); if( !log ) { if( pt->x > jmax ) jmax = pt->x; if( pt->x < jmin ) jmin = pt->x; } else { if( pt->y > jmax ) jmax = pt->y; if( pt->y < jmin ) jmin = pt->y; } tmp_number[i_point] = *pt; i_point++; } } } /* compute the length of one bucket along the line */ vl = vmax - vmin; /* examining on the arm's existence */ if( vl < eps ) { *numbers = NULL; status = CV_OK; goto M_END; } bsize = vl / nbins; /* compute the number of points in each bucket along the line */ for( i = 0; i < i_point; i++ ) { l = cvRound( (vv[i] - vmin) / bsize ); bin_counts[l]++; } /* compute the length of one bucket along the X axe */ jl = jmax - jmin; if( jl <= 1 ) { *numbers = NULL; status = CV_OK; goto M_END; } bsizej = (float) (jl / (nbins + 0.)); /* compute the number of points in each bucket along the X axe */ // for(i=0;i<i_point;i++) // { // l = cvRound((tmp_number[i].x - jmin)/bsizej); // bin_countsj[l]++; // } left = right = -1; /* find the leftmost and the rightmost buckets */ for( l = 0; l < nbins; l++ ) { if( bin_counts[l] > low_count && left == -1 ) left = l; else if( bin_counts[l] > low_count && left >= 0 ) right = l; } /* compute center point of the left hand */ if( left == -1 && right == -1 ) { *numbers = NULL; status = CV_OK; goto M_END; } hand_left = vmin + left * bsize; j_left = (int) (jmin + left * bsizej); vcl = hand_left + hand_length2; /* compute center point of the right hand */ hand_right = vmax - (nbins - right - 1) * bsize; vcr = hand_right - hand_length2; j_right = (int) (jmax - (nbins - right - 1) * bsizej); j_left = abs( j_left - jc ); j_right = abs( j_right - jc ); if( j_left <= j_right ) { hand_right = hand_left + hand_length; vc = vcl; } else { hand_left = hand_right - hand_length; vc = vcr; } icvScaleVector_32f( &line[0], sub, 3, vc ); icvAddVector_32f( &line[3], sub, (float *) center, 3 ); /* select hand's points and calculate mean value */ *numbers = cvCreateSeq( CV_SEQ_POINT_SET, sizeof( CvSeq ), sizeof( CvPoint ), storage ); assert( *numbers != 0 ); if( *numbers == NULL ) { status = CV_OUTOFMEM_ERR; goto M_END; } cvStartAppendToSeq( *numbers, &writer ); for( l = 0; l < i_point; l++ ) { if( vv[l] >= hand_left && vv[l] <= hand_right ) { CV_WRITE_SEQ_ELEM( tmp_number[l], writer ); } } cvEndWriteSeq( &writer ); M_END: if( tmp_number != NULL ) cvFree( &tmp_number ); // if(bin_countsj != NULL) cvFree( &bin_countsj ); if( bin_counts != NULL ) cvFree( &bin_counts ); if( vv != NULL ) cvFree( &vv ); if( sub != NULL ) icvDeleteVector (sub); if( cros != NULL ) icvDeleteVector (cros); return status; }
//makes vertical list of segments for 1 contour CvSeq* icvCutContourRaster(CvSeq* current, CvMemStorage* storage, IplImage* image /*tmp image*/) { //iplSet(image, 0 ); // this can cause double edges if two contours have common edge // for example if object is circle with 1 pixel width // to remove such problem - remove this iplSet //approx contour by single edges CvSeqReader reader; CvSeqWriter writer; int writing = 0; cvStartReadSeq(current, &reader, 0); //below line just to avoid warning cvStartWriteSeq(current->flags, sizeof(CvContour), sizeof(CvPoint), storage, &writer); CvSeq* output = 0; CvSeq* tail = 0; //first pass through contour - compute number of branches at every point int i; for (i = 0; i < current->total; i++) { CvPoint cur; CV_READ_SEQ_ELEM(cur, reader); //mark point ((uchar*)image->imageData)[image->widthStep * cur.y + cur.x]++; assert(((uchar*)image->imageData)[image->widthStep* cur.y + cur.x] != 255); } //second pass - create separate edges for (i = 0; i < current->total; i++) { CvPoint cur; CV_READ_SEQ_ELEM(cur, reader); //get pixel at this point uchar flag = image->imageData[image->widthStep * cur.y + cur.x]; if (flag != 255 && flag < 3) { // if (!writing) { cvStartWriteSeq(current->flags, sizeof(CvContour), sizeof(CvPoint), storage, &writer); writing = 1 ; } //mark point if (flag < 3) { ((uchar*)image->imageData)[image->widthStep* cur.y + cur.x] = 255; } //add it to another seq CV_WRITE_SEQ_ELEM(cur, writer); } else { //exclude this point from contour if (writing) { CvSeq* newseq = cvEndWriteSeq(&writer); writing = 0; if (tail) { tail->v_next = newseq; newseq->v_prev = tail; tail = newseq; } else { output = tail = newseq; } } } } if (writing) { //if were not self intersections CvSeq* newseq = cvEndWriteSeq(&writer); writing = 0; if (tail) { tail->v_next = newseq; newseq->v_prev = tail; tail = newseq; } else { output = tail = newseq; } } return output; }
/*F/////////////////////////////////////////////////////////////////////////////////////// // Name: icvContourFromContourTree // Purpose: // reconstracts contour from binary tree representation // Context: // Parameters: // tree - pointer to the input binary tree representation // storage - pointer to the current storage block // contour - pointer to output contour object. // criteria - criteria for the definition threshold value // for the contour reconstracting (level or precision) //F*/ CV_IMPL CvSeq* cvContourFromContourTree( const CvContourTree* tree, CvMemStorage* storage, CvTermCriteria criteria ) { CvSeq* contour = 0; _CvTrianAttr **ptr_buf = 0; /* pointer to the pointer's buffer */ int *level_buf = 0; int i_buf; int lpt; double area_all; double threshold; int cur_level; int level; int seq_flags; char log_iter, log_eps; int out_hearder_size; _CvTrianAttr *tree_one = 0, tree_root; /* current vertex */ CvSeqReader reader; CvSeqWriter writer; CV_FUNCNAME("cvContourFromContourTree"); __BEGIN__; if( !tree ) CV_ERROR( CV_StsNullPtr, "" ); if( !CV_IS_SEQ_POLYGON_TREE( tree )) CV_ERROR_FROM_STATUS( CV_BADFLAG_ERR ); criteria = cvCheckTermCriteria( criteria, 0., 100 ); lpt = tree->total; ptr_buf = NULL; level_buf = NULL; i_buf = 0; cur_level = 0; log_iter = (char) (criteria.type == CV_TERMCRIT_ITER || (criteria.type == CV_TERMCRIT_ITER + CV_TERMCRIT_EPS)); log_eps = (char) (criteria.type == CV_TERMCRIT_EPS || (criteria.type == CV_TERMCRIT_ITER + CV_TERMCRIT_EPS)); cvStartReadSeq( (CvSeq *) tree, &reader, 0 ); out_hearder_size = sizeof( CvContour ); seq_flags = CV_SEQ_POLYGON; cvStartWriteSeq( seq_flags, out_hearder_size, sizeof( CvPoint ), storage, &writer ); ptr_buf = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * )); if( ptr_buf == NULL ) CV_ERROR_FROM_STATUS( CV_OUTOFMEM_ERR ); if( log_iter ) { level_buf = (int *) cvAlloc( lpt * (sizeof( int ))); if( level_buf == NULL ) CV_ERROR_FROM_STATUS( CV_OUTOFMEM_ERR ); } memset( ptr_buf, 0, lpt * sizeof( _CvTrianAttr * )); /* write the first tree root's point as a start point of the result contour */ CV_WRITE_SEQ_ELEM( tree->p1, writer ); /* write the second tree root"s point into buffer */ /* read the root of the tree */ CV_READ_SEQ_ELEM( tree_root, reader ); tree_one = &tree_root; area_all = tree_one->area; if( log_eps ) threshold = criteria.epsilon * area_all; else threshold = 10 * area_all; if( log_iter ) level = criteria.max_iter; else level = -1; /* contour from binary tree constraction */ while( i_buf >= 0 ) { if( tree_one != NULL && (cur_level <= level || tree_one->area >= threshold) ) /* go to left sub tree for the vertex and save pointer to the right vertex */ /* into the buffer */ { ptr_buf[i_buf] = tree_one; if( log_iter ) { level_buf[i_buf] = cur_level; cur_level++; } i_buf++; tree_one = tree_one->next_v1; } else { i_buf--; if( i_buf >= 0 ) { CvPoint pt = ptr_buf[i_buf]->pt; CV_WRITE_SEQ_ELEM( pt, writer ); tree_one = ptr_buf[i_buf]->next_v2; if( log_iter ) { cur_level = level_buf[i_buf] + 1; } } } } contour = cvEndWriteSeq( &writer ); cvBoundingRect( contour, 1 ); __CLEANUP__; __END__; cvFree( &level_buf ); cvFree( &ptr_buf ); return contour; }
/** - FUNCIÓ: ExternPerimeter - FUNCIONALITAT: Get extern perimeter (perimeter touching image borders) - PARÀMETRES: - maskImage: if != NULL, counts maskImage black pixels as external pixels and contour points touching them are counted as external contour points. - xBorder: true to consider blobs touching horizontal borders as extern - yBorder: true to consider blobs touching vertical borders as extern - RESULTAT: - - RESTRICCIONS: - - AUTOR: rborras - DATA DE CREACIÓ: 2008/05/05 - MODIFICACIÓ: Data. Autor. Descripció. - NOTA: If CBlobContour::GetContourPoints aproximates contours with a method different that NONE, this function will not give correct results */ double CBlob::ExternPerimeter( IplImage *maskImage, bool xBorder /* = true */, bool yBorder /* = true */) { t_PointList externContour, externalPoints; CvSeqReader reader; CvSeqWriter writer; CvPoint actualPoint, previousPoint; bool find = false; int i,j; int delta = 0; // it is calculated? if( m_externPerimeter != -1 ) { return m_externPerimeter; } // get contour pixels externContour = m_externalContour.GetContourPoints(); m_externPerimeter = 0; // there are contour pixels? if( externContour == NULL ) { return m_externPerimeter; } cvStartReadSeq( externContour, &reader); // create a sequence with the external points of the blob externalPoints = cvCreateSeq( externContour->flags, externContour->header_size, externContour->elem_size, m_storage ); cvStartAppendToSeq( externalPoints, &writer ); previousPoint.x = -1; // which contour pixels touch border? for( j=0; j< externContour->total; j++) { CV_READ_SEQ_ELEM( actualPoint, reader); find = false; // pixel is touching border? if ( xBorder & ((actualPoint.x == 0) || (actualPoint.x == m_originalImageSize.width - 1 )) || yBorder & ((actualPoint.y == 0) || (actualPoint.y == m_originalImageSize.height - 1 ))) { find = true; } else { if( maskImage != NULL ) { // verify if some of 8-connected neighbours is black in mask char *pMask; pMask = (maskImage->imageData + actualPoint.x - 1 + (actualPoint.y - 1) * maskImage->widthStep); for ( i = 0; i < 3; i++, pMask++ ) { if(*pMask == 0 && !find ) { find = true; break; } } if(!find) { pMask = (maskImage->imageData + actualPoint.x - 1 + (actualPoint.y ) * maskImage->widthStep); for ( i = 0; i < 3; i++, pMask++ ) { if(*pMask == 0 && !find ) { find = true; break; } } } if(!find) { pMask = (maskImage->imageData + actualPoint.x - 1 + (actualPoint.y + 1) * maskImage->widthStep); for ( i = 0; i < 3; i++, pMask++ ) { if(*pMask == 0 && !find ) { find = true; break; } } } } } if( find ) { if( previousPoint.x > 0 ) delta = abs(previousPoint.x - actualPoint.x) + abs(previousPoint.y - actualPoint.y); // calculate separately each external contour segment if( delta > 2 ) { cvEndWriteSeq( &writer ); m_externPerimeter += cvArcLength( externalPoints, CV_WHOLE_SEQ, 0 ); cvClearSeq( externalPoints ); cvStartAppendToSeq( externalPoints, &writer ); delta = 0; previousPoint.x = -1; } CV_WRITE_SEQ_ELEM( actualPoint, writer ); previousPoint = actualPoint; } } cvEndWriteSeq( &writer ); m_externPerimeter += cvArcLength( externalPoints, CV_WHOLE_SEQ, 0 ); cvClearSeq( externalPoints ); // divide by two because external points have one side inside the blob and the other outside // Perimeter of external points counts both sides, so it must be divided m_externPerimeter /= 2.0; return m_externPerimeter; }
static CvSeq* icvGetComponent(uchar* img, int step, CvRect rect, CvMemStorage* storage) { const char nbd = 4; int deltas[16]; int x, y; CvSeq* exterior = 0; char* ptr; /* initialize local state */ CV_INIT_3X3_DELTAS(deltas, step, 1); memcpy(deltas + 8, deltas, 8 * sizeof(deltas[0])); ptr = (char*)(img + step * rect.y); rect.width += rect.x; rect.height += rect.y; for (y = rect.y; y < rect.height; y++, ptr += step) { int prev = ptr[rect.x - 1] & -2; for (x = rect.x; x < rect.width; x++) { int p = ptr[x] & -2; //assert( exterior || ((p | prev) & -4) == 0 ); if (p != prev) { CvSeq* seq = 0; int is_hole = 0; CvSeqWriter writer; char* i0, *i1, *i3, *i4 = 0; int prev_s = -1, s, s_end; CvPoint pt = { x, y }; if (!(prev == 0 && p == 2)) { /* if not external contour */ /* check hole */ if (p != 0 || prev < 1) { prev = p; continue; } is_hole = 1; if (!exterior) { assert(0); return 0; } } cvStartWriteSeq(CV_SEQ_CONTOUR | (is_hole ? CV_SEQ_FLAG_HOLE : 0), sizeof(CvContour), sizeof(CvPoint), storage, &writer); s_end = s = is_hole ? 0 : 4; i0 = ptr + x - is_hole; do { s = (s - 1) & 7; i1 = i0 + deltas[s]; if ((*i1 & -2) != 0) { break; } } while (s != s_end); if (s == s_end) { /* single pixel domain */ *i0 = (char)(nbd | -128); CV_WRITE_SEQ_ELEM(pt, writer); } else { i3 = i0; prev_s = s ^ 4; /* follow border */ for (;;) { s_end = s; for (;;) { i4 = i3 + deltas[++s]; if ((*i4 & -2) != 0) { break; } } s &= 7; /* check "right" bound */ if ((unsigned)(s - 1) < (unsigned) s_end) { *i3 = (char)(nbd | -128); } else if (*i3 > 0) { *i3 = nbd; } if (s != prev_s) { CV_WRITE_SEQ_ELEM(pt, writer); prev_s = s; } pt.x += icvCodeDeltas[s].x; pt.y += icvCodeDeltas[s].y; if (i4 == i0 && i3 == i1) { break; } i3 = i4; s = (s + 4) & 7; } /* end of border following loop */ } seq = cvEndWriteSeq(&writer); cvContourBoundingRect(seq, 1); if (!is_hole) { exterior = seq; } else { seq->v_prev = exterior; seq->h_next = exterior->v_next; if (seq->h_next) { seq->h_next->h_prev = seq; } exterior->v_next = seq; } prev = ptr[x] & -2; } } } return exterior; }
CV_IMPL CvSeq* cvConvexHull2( const CvArr* array, void* hull_storage, int orientation, int return_points ) { union { CvContour* c; CvSeq* s; } hull; CvPoint** pointer = 0; CvPoint2D32f** pointerf = 0; int* stack = 0; CV_FUNCNAME( "cvConvexHull2" ); hull.s = 0; __BEGIN__; CvMat* mat = 0; CvSeqReader reader; CvSeqWriter writer; CvContour contour_header; union { CvContour c; CvSeq s; } hull_header; CvSeqBlock block, hullblock; CvSeq* ptseq = 0; CvSeq* hullseq = 0; int is_float; int* t_stack; int t_count; int i, miny_ind = 0, maxy_ind = 0, total; int hulltype; int stop_idx; sklansky_func sklansky; if( CV_IS_SEQ( array )) { ptseq = (CvSeq*)array; if( !CV_IS_SEQ_POINT_SET( ptseq )) CV_ERROR( CV_StsBadArg, "Unsupported sequence type" ); if( hull_storage == 0 ) hull_storage = ptseq->storage; } else { CV_CALL( ptseq = cvPointSeqFromMat( CV_SEQ_KIND_GENERIC, array, &contour_header, &block )); } if( CV_IS_STORAGE( hull_storage )) { if( return_points ) { CV_CALL( hullseq = cvCreateSeq( CV_SEQ_KIND_CURVE|CV_SEQ_ELTYPE(ptseq)| CV_SEQ_FLAG_CLOSED|CV_SEQ_FLAG_CONVEX, sizeof(CvContour), sizeof(CvPoint),(CvMemStorage*)hull_storage )); } else { CV_CALL( hullseq = cvCreateSeq( CV_SEQ_KIND_CURVE|CV_SEQ_ELTYPE_PPOINT| CV_SEQ_FLAG_CLOSED|CV_SEQ_FLAG_CONVEX, sizeof(CvContour), sizeof(CvPoint*), (CvMemStorage*)hull_storage )); } } else { if( !CV_IS_MAT( hull_storage )) CV_ERROR(CV_StsBadArg, "Destination must be valid memory storage or matrix"); mat = (CvMat*)hull_storage; if( mat->cols != 1 && mat->rows != 1 || !CV_IS_MAT_CONT(mat->type)) CV_ERROR( CV_StsBadArg, "The hull matrix should be continuous and have a single row or a single column" ); if( mat->cols + mat->rows - 1 < ptseq->total ) CV_ERROR( CV_StsBadSize, "The hull matrix size might be not enough to fit the hull" ); if( CV_MAT_TYPE(mat->type) != CV_SEQ_ELTYPE(ptseq) && CV_MAT_TYPE(mat->type) != CV_32SC1 ) CV_ERROR( CV_StsUnsupportedFormat, "The hull matrix must have the same type as input or 32sC1 (integers)" ); CV_CALL( hullseq = cvMakeSeqHeaderForArray( CV_SEQ_KIND_CURVE|CV_MAT_TYPE(mat->type)|CV_SEQ_FLAG_CLOSED, sizeof(contour_header), CV_ELEM_SIZE(mat->type), mat->data.ptr, mat->cols + mat->rows - 1, &hull_header.s, &hullblock )); cvClearSeq( hullseq ); } total = ptseq->total; if( total == 0 ) { if( mat ) CV_ERROR( CV_StsBadSize, "Point sequence can not be empty if the output is matrix" ); EXIT; } cvStartAppendToSeq( hullseq, &writer ); is_float = CV_SEQ_ELTYPE(ptseq) == CV_32FC2; hulltype = CV_SEQ_ELTYPE(hullseq); sklansky = !is_float ? (sklansky_func)icvSklansky_32s : (sklansky_func)icvSklansky_32f; CV_CALL( pointer = (CvPoint**)cvAlloc( ptseq->total*sizeof(pointer[0]) )); CV_CALL( stack = (int*)cvAlloc( (ptseq->total + 2)*sizeof(stack[0]) )); pointerf = (CvPoint2D32f**)pointer; cvStartReadSeq( ptseq, &reader ); for( i = 0; i < total; i++ ) { pointer[i] = (CvPoint*)reader.ptr; CV_NEXT_SEQ_ELEM( ptseq->elem_size, reader ); } // sort the point set by x-coordinate, find min and max y if( !is_float ) { icvSortPointsByPointers_32s( pointer, total, 0 ); for( i = 1; i < total; i++ ) { int y = pointer[i]->y; if( pointer[miny_ind]->y > y ) miny_ind = i; if( pointer[maxy_ind]->y < y ) maxy_ind = i; } } else { icvSortPointsByPointers_32f( pointerf, total, 0 ); for( i = 1; i < total; i++ ) { float y = pointerf[i]->y; if( pointerf[miny_ind]->y > y ) miny_ind = i; if( pointerf[maxy_ind]->y < y ) maxy_ind = i; } } if( pointer[0]->x == pointer[total-1]->x && pointer[0]->y == pointer[total-1]->y ) { if( hulltype == CV_SEQ_ELTYPE_PPOINT ) { CV_WRITE_SEQ_ELEM( pointer[0], writer ); } else if( hulltype == CV_SEQ_ELTYPE_INDEX ) { int index = 0; CV_WRITE_SEQ_ELEM( index, writer ); } else { CvPoint pt = pointer[0][0]; CV_WRITE_SEQ_ELEM( pt, writer ); } goto finish_hull; } /*upper half */ { int *tl_stack = stack; int tl_count = sklansky( pointer, 0, maxy_ind, tl_stack, -1, 1 ); int *tr_stack = tl_stack + tl_count; int tr_count = sklansky( pointer, ptseq->total - 1, maxy_ind, tr_stack, -1, -1 ); /* gather upper part of convex hull to output */ if( orientation == CV_COUNTER_CLOCKWISE ) { CV_SWAP( tl_stack, tr_stack, t_stack ); CV_SWAP( tl_count, tr_count, t_count ); } if( hulltype == CV_SEQ_ELTYPE_PPOINT ) { for( i = 0; i < tl_count - 1; i++ ) CV_WRITE_SEQ_ELEM( pointer[tl_stack[i]], writer ); for( i = tr_count - 1; i > 0; i-- ) CV_WRITE_SEQ_ELEM( pointer[tr_stack[i]], writer ); } else if( hulltype == CV_SEQ_ELTYPE_INDEX ) { CV_CALL( icvCalcAndWritePtIndices( pointer, tl_stack, 0, tl_count-1, ptseq, &writer )); CV_CALL( icvCalcAndWritePtIndices( pointer, tr_stack, tr_count-1, 0, ptseq, &writer )); } else { for( i = 0; i < tl_count - 1; i++ ) CV_WRITE_SEQ_ELEM( pointer[tl_stack[i]][0], writer ); for( i = tr_count - 1; i > 0; i-- ) CV_WRITE_SEQ_ELEM( pointer[tr_stack[i]][0], writer ); } stop_idx = tr_count > 2 ? tr_stack[1] : tl_count > 2 ? tl_stack[tl_count - 2] : -1; } /* lower half */ { int *bl_stack = stack; int bl_count = sklansky( pointer, 0, miny_ind, bl_stack, 1, -1 ); int *br_stack = stack + bl_count; int br_count = sklansky( pointer, ptseq->total - 1, miny_ind, br_stack, 1, 1 ); if( orientation != CV_COUNTER_CLOCKWISE ) { CV_SWAP( bl_stack, br_stack, t_stack ); CV_SWAP( bl_count, br_count, t_count ); } if( stop_idx >= 0 ) { int check_idx = bl_count > 2 ? bl_stack[1] : bl_count + br_count > 2 ? br_stack[2-bl_count] : -1; if( check_idx == stop_idx || check_idx >= 0 && pointer[check_idx]->x == pointer[stop_idx]->x && pointer[check_idx]->y == pointer[stop_idx]->y ) { /* if all the points lie on the same line, then the bottom part of the convex hull is the mirrored top part (except the exteme points).*/ bl_count = MIN( bl_count, 2 ); br_count = MIN( br_count, 2 ); } } if( hulltype == CV_SEQ_ELTYPE_PPOINT ) { for( i = 0; i < bl_count - 1; i++ ) CV_WRITE_SEQ_ELEM( pointer[bl_stack[i]], writer ); for( i = br_count - 1; i > 0; i-- ) CV_WRITE_SEQ_ELEM( pointer[br_stack[i]], writer ); } else if( hulltype == CV_SEQ_ELTYPE_INDEX ) { CV_CALL( icvCalcAndWritePtIndices( pointer, bl_stack, 0, bl_count-1, ptseq, &writer )); CV_CALL( icvCalcAndWritePtIndices( pointer, br_stack, br_count-1, 0, ptseq, &writer )); } else { for( i = 0; i < bl_count - 1; i++ ) CV_WRITE_SEQ_ELEM( pointer[bl_stack[i]][0], writer ); for( i = br_count - 1; i > 0; i-- ) CV_WRITE_SEQ_ELEM( pointer[br_stack[i]][0], writer ); } } finish_hull: CV_CALL( cvEndWriteSeq( &writer )); if( mat ) { if( mat->rows > mat->cols ) mat->rows = hullseq->total; else mat->cols = hullseq->total; } else { hull.s = hullseq; hull.c->rect = cvBoundingRect( ptseq, ptseq->header_size < (int)sizeof(CvContour) || &ptseq->flags == &contour_header.flags ); /*if( ptseq != (CvSeq*)&contour_header ) hullseq->v_prev = ptseq;*/ } __END__; cvFree( &pointer ); cvFree( &stack ); return hull.s; }
CvLCMNode* _cvConstructLCMComplexNode(CvLCM* pLCM, CvLCMEdge* pLCMEdge, CvLCMData* pLCMInputData) { CvLCMNode* pLCMNode; CvLCMEdge* pLCMEdge_prev = NULL; CvSeqWriter writer; CvVoronoiSite2D* pSite, *pSite_first, *pSite_last; CvVoronoiEdge2D* pEdge, *pEdge_stop; CvVoronoiNode2D* pNode0, *pNode1; CvLCMData LCMOutputData; CvLCMComplexNodeData LCMCCNData; int index = 0; _cvPrepareData(&LCMCCNData,pLCMInputData); pLCMNode = _cvCreateLCMNode(pLCM); _cvAttachLCMEdgeToLCMNode(pLCMNode,pLCMEdge,pLCMEdge_prev,1,1); cvStartAppendToSeq((CvSeq*)pLCMNode->contour,&writer); CV_WRITE_SEQ_ELEM(LCMCCNData.site_last_pt, writer); index++; if(pLCMEdge) { CV_WRITE_SEQ_ELEM(LCMCCNData.edge_node.pt, writer ); CV_WRITE_SEQ_ELEM(LCMCCNData.site_first_pt, writer ); index+=2; } pSite_first = LCMCCNData.site_first; pSite_last = LCMCCNData.site_last; pEdge = LCMCCNData.edge; for(pSite = pSite_first; pSite != pSite_last; pSite = CV_NEXT_VORONOISITE2D(pSite), pEdge = CV_PREV_VORONOIEDGE2D(CV_LAST_VORONOIEDGE2D(pSite),pSite)) { pEdge_stop = CV_FIRST_VORONOIEDGE2D(pSite); for(;pEdge && pEdge != pEdge_stop; pEdge = CV_PREV_VORONOIEDGE2D(pEdge,pSite)) { pNode0 = CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite); pNode1 = CV_VORONOIEDGE2D_ENDNODE(pEdge,pSite); if(pNode0->radius <= pLCM->maxWidth && pNode1->radius <= pLCM->maxWidth) { _CV_INITIALIZE_CVLCMDATA(&LCMOutputData,pSite,pEdge,pNode1); _cvPrepareData(&LCMCCNData,&LCMOutputData); CV_WRITE_SEQ_ELEM(LCMCCNData.site_first_pt, writer); CV_WRITE_SEQ_ELEM(LCMCCNData.edge_node.pt, writer ); index+=2; pLCMEdge = _cvConstructLCMEdge(pLCM,&LCMOutputData); _cvAttachLCMEdgeToLCMNode(pLCMNode,pLCMEdge,pLCMEdge_prev,index - 1,0); CV_WRITE_SEQ_ELEM(LCMCCNData.site_last_pt, writer); index++; pSite = CV_TWIN_VORONOISITE2D(pSite,pEdge); pEdge_stop = CV_FIRST_VORONOIEDGE2D(pSite); if(pSite == pSite_last) break; } } if(pSite == pSite_last) break; CV_WRITE_SEQ_ELEM(pSite->node[1]->pt, writer); index++; } if(pLCMEdge_prev) pLCMEdge_prev->next[(pLCMEdge_prev == (CvLCMEdge*)pLCMNode->first)] = pLCMNode->first; cvEndWriteSeq(&writer); return pLCMNode; }//end of _cvConstructLCMComplexNode
static CvStatus icvFindDominantPointsIPAN( CvSeq * contour, CvMemStorage * storage, CvSeq ** corners, int dmin2, int dmax2, int dneigh2, float amax ) { CvStatus status = CV_OK; /* variables */ int n = contour->total; float *sharpness; float *distance; icvPointInfo *ptInf; int i, j, k; CvSeqWriter writer; float mincos = (float) cos( 3.14159265359 * amax / 180 ); /* check bad arguments */ if( contour == NULL ) return CV_NULLPTR_ERR; if( storage == NULL ) return CV_NULLPTR_ERR; if( corners == NULL ) return CV_NULLPTR_ERR; if( dmin2 < 0 ) return CV_BADSIZE_ERR; if( dmax2 < dmin2 ) return CV_BADSIZE_ERR; if( (dneigh2 > dmax2) || (dneigh2 < 0) ) return CV_BADSIZE_ERR; if( (amax < 0) || (amax > 180) ) return CV_BADSIZE_ERR; sharpness = (float *) cvAlloc( n * sizeof( float )); distance = (float *) cvAlloc( n * sizeof( float )); ptInf = (icvPointInfo *) cvAlloc( n * sizeof( icvPointInfo )); /*****************************************************************************************/ /* First pass */ /*****************************************************************************************/ if( CV_IS_SEQ_CHAIN_CONTOUR( contour )) { CvChainPtReader reader; cvStartReadChainPoints( (CvChain *) contour, &reader ); for( i = 0; i < n; i++ ) { CV_READ_CHAIN_POINT( ptInf[i].pt, reader ); } } else if( CV_IS_SEQ_POLYGON( contour )) { CvSeqReader reader; cvStartReadSeq( contour, &reader, 0 ); for( i = 0; i < n; i++ ) { CV_READ_SEQ_ELEM( ptInf[i].pt, reader ); } } else { return CV_BADFLAG_ERR; } for( i = 0; i < n; i++ ) { /* find nearest suitable points which satisfy distance constraint >dmin */ int left_near = 0; int right_near = 0; int left_far, right_far; float dist_l = 0; float dist_r = 0; int i_plus = 0; int i_minus = 0; float max_cos_alpha; /* find right minimum */ while( dist_r < dmin2 ) { float dx, dy; int ind; if( i_plus >= n ) goto error; right_near = i_plus; if( dist_r < dneigh2 ) ptInf[i].right_neigh = i_plus; i_plus++; ind = (i + i_plus) % n; dx = (float) (ptInf[i].pt.x - ptInf[ind].pt.x); dy = (float) (ptInf[i].pt.y - ptInf[ind].pt.y); dist_r = dx * dx + dy * dy; } /* find right maximum */ while( dist_r <= dmax2 ) { float dx, dy; int ind; if( i_plus >= n ) goto error; distance[(i + i_plus) % n] = cvSqrt( dist_r ); if( dist_r < dneigh2 ) ptInf[i].right_neigh = i_plus; i_plus++; right_far = i_plus; ind = (i + i_plus) % n; dx = (float) (ptInf[i].pt.x - ptInf[ind].pt.x); dy = (float) (ptInf[i].pt.y - ptInf[ind].pt.y); dist_r = dx * dx + dy * dy; } right_far = i_plus; /* left minimum */ while( dist_l < dmin2 ) { float dx, dy; int ind; if( i_minus <= -n ) goto error; left_near = i_minus; if( dist_l < dneigh2 ) ptInf[i].left_neigh = i_minus; i_minus--; ind = i + i_minus; ind = (ind < 0) ? (n + ind) : ind; dx = (float) (ptInf[i].pt.x - ptInf[ind].pt.x); dy = (float) (ptInf[i].pt.y - ptInf[ind].pt.y); dist_l = dx * dx + dy * dy; } /* find left maximum */ while( dist_l <= dmax2 ) { float dx, dy; int ind; if( i_minus <= -n ) goto error; ind = i + i_minus; ind = (ind < 0) ? (n + ind) : ind; distance[ind] = cvSqrt( dist_l ); if( dist_l < dneigh2 ) ptInf[i].left_neigh = i_minus; i_minus--; left_far = i_minus; ind = i + i_minus; ind = (ind < 0) ? (n + ind) : ind; dx = (float) (ptInf[i].pt.x - ptInf[ind].pt.x); dy = (float) (ptInf[i].pt.y - ptInf[ind].pt.y); dist_l = dx * dx + dy * dy; } left_far = i_minus; if( (i_plus - i_minus) > n + 2 ) goto error; max_cos_alpha = -1; for( j = left_far + 1; j < left_near; j++ ) { float dx, dy; float a, a2; int leftind = i + j; leftind = (leftind < 0) ? (n + leftind) : leftind; a = distance[leftind]; a2 = a * a; for( k = right_near + 1; k < right_far; k++ ) { int ind = (i + k) % n; float c2, cosalpha; float b = distance[ind]; float b2 = b * b; /* compute cosinus */ dx = (float) (ptInf[leftind].pt.x - ptInf[ind].pt.x); dy = (float) (ptInf[leftind].pt.y - ptInf[ind].pt.y); c2 = dx * dx + dy * dy; cosalpha = (a2 + b2 - c2) / (2 * a * b); max_cos_alpha = MAX( max_cos_alpha, cosalpha ); if( max_cos_alpha < mincos ) max_cos_alpha = -1; sharpness[i] = max_cos_alpha; } } } /*****************************************************************************************/ /* Second pass */ /*****************************************************************************************/ cvStartWriteSeq( (contour->flags & ~CV_SEQ_ELTYPE_MASK) | CV_SEQ_ELTYPE_INDEX, sizeof( CvSeq ), sizeof( int ), storage, &writer ); /* second pass - nonmaxima suppression */ /* neighborhood of point < dneigh2 */ for( i = 0; i < n; i++ ) { int suppressed = 0; if( sharpness[i] == -1 ) continue; for( j = 1; (j <= ptInf[i].right_neigh) && (suppressed == 0); j++ ) { if( sharpness[i] < sharpness[(i + j) % n] ) suppressed = 1; } for( j = -1; (j >= ptInf[i].left_neigh) && (suppressed == 0); j-- ) { int ind = i + j; ind = (ind < 0) ? (n + ind) : ind; if( sharpness[i] < sharpness[ind] ) suppressed = 1; } if( !suppressed ) CV_WRITE_SEQ_ELEM( i, writer ); } *corners = cvEndWriteSeq( &writer ); cvFree( &sharpness ); cvFree( &distance ); cvFree( &ptInf ); return status; error: /* dmax is so big (more than contour diameter) that algorithm could become infinite cycle */ cvFree( &sharpness ); cvFree( &distance ); cvFree( &ptInf ); return CV_BADRANGE_ERR; }
void Gesture1::trackMarker (IplImage* destImg, CvPoint _r, CvPoint _b, CvPoint _g, CvPoint _y) { // find tissue box! CvPoint* objPoints = objectDetector->detect(destImg); // draw world->Step(1.0F/6.0F, 10, 10); cvLine(destImg, cvPoint(0,HEIGHT), cvPoint(1000,HEIGHT), CV_RGB(0,255,0), 3); for (b2Body* b = world->GetBodyList(); b; b = b->GetNext()) { //printf("**draw body\n"); Box2DData* userData = (Box2DData*)b->GetUserData(); if (userData != NULL) { if (strcmp(userData->type, "Circle") == 0) { //b2Vec2 v = b->GetWorldCenter(); b2Vec2 v = b->GetPosition(); //printf("** x=%f y=%f r=%f\n", v.x, v.y, userData->radius); CvPoint center = cvPoint(v.x*WORLD_SCALE, v.y*WORLD_SCALE); cvCircle(destImg, center, userData->radius*WORLD_SCALE, CV_RGB(255,0,0), -1); } else if (strcmp(userData->type, "Box") == 0) { world->DestroyBody(b); } } } if (objPoints != NULL) { printf("construct body\n"); b2PolygonShape cs; b2Vec2 vertices[4] = { b2Vec2((float)(objPoints[0].x)/WORLD_SCALE, (float)(objPoints[0].y)/WORLD_SCALE), b2Vec2((float)(objPoints[1].x)/WORLD_SCALE, (float)(objPoints[1].y)/WORLD_SCALE), b2Vec2((float)(objPoints[2].x)/WORLD_SCALE, (float)(objPoints[2].y)/WORLD_SCALE), b2Vec2((float)(objPoints[3].x)/WORLD_SCALE, (float)(objPoints[3].y)/WORLD_SCALE) }; cs.Set(vertices, 4); b2BodyDef bd; //bd.type = b2_staticBody; Box2DData* obj = new Box2DData(); strcpy(obj->type, "Box"); bd.userData = obj; b2Body* body1 = world->CreateBody(&bd); body1->CreateFixture(&cs, 0.0f); } if (_r.x < 0) return; Point2D r = toPoint2D(_r); // if marker is not moving for a while, reset the path int len = path.size(); if (len > KEEP_MAX) { path.erase(path.begin()); } int nearCount = 0; int actual = min(KEEP_COUNT, len); /* for(int i=0; i<actual; i++){ Point2D p = path[len-1-i]; double d = dist(p, r); //printf("dist=%f\n", d); if (d < NEAR_THRESHOLD) ++nearCount; } if (nearCount > (double)actual * DONT_MOVE_THRESHOLD_RATE) { // marker is not moving, so clear the path printf("cleared\n"); path.clear(); } */ path.push_back(r); // decide if we should recognize time_t current; time(¤t); double interval = difftime(current, lastTime); printf("interval=%f\n", interval); if (interval < INTERVAL_SEC) return; len = path.size(); if (len < 5) return; RecognitionResult res = g.recognize(path); printf("%s:%f\n", res.name.c_str(), res.score); if (res.name == "Circle" && res.score > SCORE_THRESHOLD) { printf("##circle detect##\n"); // convert to vector<Point2D> to CvSeq<CvPoint> CvSeqWriter writer; CvMemStorage* storage = cvCreateMemStorage(0); cvStartWriteSeq( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage, &writer); for (int i=0; i<len; i++) { CvPoint pt = toCvPoint(path[i]); CV_WRITE_SEQ_ELEM(pt, writer); } CvSeq* seq = cvEndWriteSeq(&writer); CvBox2D ellipse = cvFitEllipse2(seq); float radius = std::min(ellipse.size.width, ellipse.size.height)/(4.0F*WORLD_SCALE); cvEllipseBox(destImg, ellipse, CV_RGB(0,255,255), -1); // add Box2D object { b2CircleShape cs; cs.m_radius = radius; printf(" x=%f y=%f radius:%f\n", ellipse.center.x/WORLD_SCALE, ellipse.center.y/WORLD_SCALE, radius); b2BodyDef bd; bd.type = b2_dynamicBody; bd.position.Set(ellipse.center.x/WORLD_SCALE, ellipse.center.y/WORLD_SCALE); Box2DData* obj = new Box2DData(); strcpy(obj->type, "Circle"); obj->radius = radius; bd.userData = obj; b2Body* body1 = world->CreateBody(&bd); b2FixtureDef fixtureDef; fixtureDef.shape = &cs; fixtureDef.density = 1.0f; fixtureDef.friction = 0.3f; fixtureDef.restitution = 0.6f; body1->CreateFixture(&fixtureDef); } time(&lastTime); //cvEllipseBox(destImg, ellipse, CV_RGB(125,125,255)); } }
/*F/////////////////////////////////////////////////////////////////////////////////////// // Name: icvCreateContourTree // Purpose: // Create binary tree representation for the contour // Context: // Parameters: // contour - pointer to input contour object. // storage - pointer to the current storage block // tree - output pointer to the binary tree representation // threshold - threshold for the binary tree building // //F*/ static CvStatus icvCreateContourTree( const CvSeq * contour, CvMemStorage * storage, CvContourTree ** tree, double threshold ) { CvPoint *pt_p; /* pointer to previos points */ CvPoint *pt_n; /* pointer to next points */ CvPoint *pt1, *pt2; /* pointer to current points */ CvPoint t, tp1, tp2, tp3, tn1, tn2, tn3; int lpt, flag, i, j, i_tree, j_1, j_3, i_buf; double s, sp1, sp2, sn1, sn2, s_c, sp1_c, sp2_c, sn1_c, sn2_c, h, hp1, hp2, hn1, hn2, a, ap1, ap2, an1, an2, b, bp1, bp2, bn1, bn2; double a_s_c, a_sp1_c; _CvTrianAttr **ptr_p, **ptr_n, **ptr1, **ptr2; /* pointers to pointers of triangles */ _CvTrianAttr *cur_adr; int *num_p, *num_n, *num1, *num2; /* numbers of input contour points */ int nm, nmp1, nmp2, nmp3, nmn1, nmn2, nmn3; int seq_flags = 1, i_end, prev_null, prev2_null; double koef = 1.5; double eps = 1.e-7; double e; CvStatus status; int hearder_size; _CvTrianAttr tree_one, tree_two, *tree_end, *tree_root; CvSeqWriter writer; assert( contour != NULL && contour->total >= 4 ); status = CV_OK; if( contour == NULL ) return CV_NULLPTR_ERR; if( contour->total < 4 ) return CV_BADSIZE_ERR; if( !CV_IS_SEQ_POLYGON( contour )) return CV_BADFLAG_ERR; /* Convert Sequence to array */ lpt = contour->total; pt_p = pt_n = NULL; num_p = num_n = NULL; ptr_p = ptr_n = ptr1 = ptr2 = NULL; tree_end = NULL; pt_p = (CvPoint *) cvAlloc( lpt * sizeof( CvPoint )); pt_n = (CvPoint *) cvAlloc( lpt * sizeof( CvPoint )); num_p = (int *) cvAlloc( lpt * sizeof( int )); num_n = (int *) cvAlloc( lpt * sizeof( int )); hearder_size = sizeof( CvContourTree ); seq_flags = CV_SEQ_POLYGON_TREE; cvStartWriteSeq( seq_flags, hearder_size, sizeof( _CvTrianAttr ), storage, &writer ); ptr_p = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * )); ptr_n = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * )); memset( ptr_p, 0, lpt * sizeof( _CvTrianAttr * )); memset( ptr_n, 0, lpt * sizeof( _CvTrianAttr * )); if( pt_p == NULL || pt_n == NULL ) return CV_OUTOFMEM_ERR; if( ptr_p == NULL || ptr_n == NULL ) return CV_OUTOFMEM_ERR; /* write fild for the binary tree root */ /* start_writer = writer; */ tree_one.pt.x = tree_one.pt.y = 0; tree_one.sign = 0; tree_one.area = 0; tree_one.r1 = tree_one.r2 = 0; tree_one.next_v1 = tree_one.next_v2 = tree_one.prev_v = NULL; CV_WRITE_SEQ_ELEM( tree_one, writer ); tree_root = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size); if( cvCvtSeqToArray( contour, (char *) pt_p ) == (char *) contour ) return CV_BADPOINT_ERR; for( i = 0; i < lpt; i++ ) num_p[i] = i; i = lpt; flag = 0; i_tree = 0; e = 20.; /* initial threshold value */ ptr1 = ptr_p; ptr2 = ptr_n; pt1 = pt_p; pt2 = pt_n; num1 = num_p; num2 = num_n; /* binary tree constraction */ while( i > 4 ) { if( flag == 0 ) { ptr1 = ptr_p; ptr2 = ptr_n; pt1 = pt_p; pt2 = pt_n; num1 = num_p; num2 = num_n; flag = 1; } else { ptr1 = ptr_n; ptr2 = ptr_p; pt1 = pt_n; pt2 = pt_p; num1 = num_n; num2 = num_p; flag = 0; } t = pt1[0]; nm = num1[0]; tp1 = pt1[i - 1]; nmp1 = num1[i - 1]; tp2 = pt1[i - 2]; nmp2 = num1[i - 2]; tp3 = pt1[i - 3]; nmp3 = num1[i - 3]; tn1 = pt1[1]; nmn1 = num1[1]; tn2 = pt1[2]; nmn2 = num1[2]; i_buf = 0; i_end = -1; CV_MATCH_CHECK( status, icvCalcTriAttr( contour, t, tp1, nmp1, tn1, nmn1, &s, &s_c, &h, &a, &b )); CV_MATCH_CHECK( status, icvCalcTriAttr( contour, tp1, tp2, nmp2, t, nm, &sp1, &sp1_c, &hp1, &ap1, &bp1 )); CV_MATCH_CHECK( status, icvCalcTriAttr( contour, tp2, tp3, nmp3, tp1, nmp1, &sp2, &sp2_c, &hp2, &ap2, &bp2 )); CV_MATCH_CHECK( status, icvCalcTriAttr( contour, tn1, t, nm, tn2, nmn2, &sn1, &sn1_c, &hn1, &an1, &bn1 )); j_3 = 3; prev_null = prev2_null = 0; for( j = 0; j < i; j++ ) { tn3 = pt1[j_3]; nmn3 = num1[j_3]; if( j == 0 ) j_1 = i - 1; else j_1 = j - 1; CV_MATCH_CHECK( status, icvCalcTriAttr( contour, tn2, tn1, nmn1, tn3, nmn3, &sn2, &sn2_c, &hn2, &an2, &bn2 )); if( (s_c < sp1_c && s_c < sp2_c && s_c <= sn1_c && s_c <= sn2_c && s_c < e) || (s_c == sp1_c && s_c <= sp2_c || s_c == sp2_c && s_c <= sp1_c) && s_c <= sn1_c && s_c <= sn2_c && s_c < e && j > 1 && prev2_null == 0 || (s_c < eps && j > 0 && prev_null == 0) ) { prev_null = prev2_null = 1; if( s_c < threshold ) { if( ptr1[j_1] == NULL && ptr1[j] == NULL ) { if( i_buf > 0 ) ptr2[i_buf - 1] = NULL; else i_end = 0; } else { /* form next vertex */ tree_one.pt = t; tree_one.sign = (char) (CV_SIGN( s )); tree_one.r1 = h / a; tree_one.r2 = b / a; tree_one.area = fabs( s ); tree_one.next_v1 = ptr1[j_1]; tree_one.next_v2 = ptr1[j]; CV_WRITE_SEQ_ELEM( tree_one, writer ); cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size); if( ptr1[j_1] != NULL ) ptr1[j_1]->prev_v = cur_adr; if( ptr1[j] != NULL ) ptr1[j]->prev_v = cur_adr; if( i_buf > 0 ) ptr2[i_buf - 1] = cur_adr; else { tree_end = (_CvTrianAttr *) writer.ptr; i_end = 1; } i_tree++; } } else /* form next vertex */ { tree_one.pt = t; tree_one.sign = (char) (CV_SIGN( s )); tree_one.area = fabs( s ); tree_one.r1 = h / a; tree_one.r2 = b / a; tree_one.next_v1 = ptr1[j_1]; tree_one.next_v2 = ptr1[j]; CV_WRITE_SEQ_ELEM( tree_one, writer ); cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size); if( ptr1[j_1] != NULL ) ptr1[j_1]->prev_v = cur_adr; if( ptr1[j] != NULL ) ptr1[j]->prev_v = cur_adr; if( i_buf > 0 ) ptr2[i_buf - 1] = cur_adr; else { tree_end = cur_adr; i_end = 1; } i_tree++; } } else /* the current triangle is'not LMIAT */ { prev_null = 0; switch (prev2_null) { case 0: break; case 1: { prev2_null = 2; break; } case 2: { prev2_null = 0; break; } } if( j != i - 1 || i_end == -1 ) ptr2[i_buf] = ptr1[j]; else if( i_end == 0 ) ptr2[i_buf] = NULL; else ptr2[i_buf] = tree_end; pt2[i_buf] = t; num2[i_buf] = num1[j]; i_buf++; } /* go to next vertex */ tp3 = tp2; tp2 = tp1; tp1 = t; t = tn1; tn1 = tn2; tn2 = tn3; nmp3 = nmp2; nmp2 = nmp1; nmp1 = nm; nm = nmn1; nmn1 = nmn2; nmn2 = nmn3; sp2 = sp1; sp1 = s; s = sn1; sn1 = sn2; sp2_c = sp1_c; sp1_c = s_c; s_c = sn1_c; sn1_c = sn2_c; ap2 = ap1; ap1 = a; a = an1; an1 = an2; bp2 = bp1; bp1 = b; b = bn1; bn1 = bn2; hp2 = hp1; hp1 = h; h = hn1; hn1 = hn2; j_3++; if( j_3 >= i ) j_3 = 0; } i = i_buf; e = e * koef; } /* constract tree root */ if( i != 4 ) return CV_BADFACTOR_ERR; t = pt2[0]; tn1 = pt2[1]; tn2 = pt2[2]; tp1 = pt2[3]; nm = num2[0]; nmn1 = num2[1]; nmn2 = num2[2]; nmp1 = num2[3]; /* first pair of the triangles */ CV_MATCH_CHECK( status, icvCalcTriAttr( contour, t, tp1, nmp1, tn1, nmn1, &s, &s_c, &h, &a, &b )); CV_MATCH_CHECK( status, icvCalcTriAttr( contour, tn2, tn1, nmn1, tp1, nmp1, &sn2, &sn2_c, &hn2, &an2, &bn2 )); /* second pair of the triangles */ CV_MATCH_CHECK( status, icvCalcTriAttr( contour, tn1, t, nm, tn2, nmn2, &sn1, &sn1_c, &hn1, &an1, &bn1 )); CV_MATCH_CHECK( status, icvCalcTriAttr( contour, tp1, tn2, nmn2, t, nm, &sp1, &sp1_c, &hp1, &ap1, &bp1 )); a_s_c = fabs( s_c - sn2_c ); a_sp1_c = fabs( sp1_c - sn1_c ); if( a_s_c > a_sp1_c ) /* form child vertexs for the root */ { tree_one.pt = t; tree_one.sign = (char) (CV_SIGN( s )); tree_one.area = fabs( s ); tree_one.r1 = h / a; tree_one.r2 = b / a; tree_one.next_v1 = ptr2[3]; tree_one.next_v2 = ptr2[0]; tree_two.pt = tn2; tree_two.sign = (char) (CV_SIGN( sn2 )); tree_two.area = fabs( sn2 ); tree_two.r1 = hn2 / an2; tree_two.r2 = bn2 / an2; tree_two.next_v1 = ptr2[1]; tree_two.next_v2 = ptr2[2]; CV_WRITE_SEQ_ELEM( tree_one, writer ); cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size); if( s_c > sn2_c ) { if( ptr2[3] != NULL ) ptr2[3]->prev_v = cur_adr; if( ptr2[0] != NULL ) ptr2[0]->prev_v = cur_adr; ptr1[0] = cur_adr; i_tree++; CV_WRITE_SEQ_ELEM( tree_two, writer ); cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size); if( ptr2[1] != NULL ) ptr2[1]->prev_v = cur_adr; if( ptr2[2] != NULL ) ptr2[2]->prev_v = cur_adr; ptr1[1] = cur_adr; i_tree++; pt1[0] = tp1; pt1[1] = tn1; } else { CV_WRITE_SEQ_ELEM( tree_two, writer ); cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size); if( ptr2[1] != NULL ) ptr2[1]->prev_v = cur_adr; if( ptr2[2] != NULL ) ptr2[2]->prev_v = cur_adr; ptr1[0] = cur_adr; i_tree++; CV_WRITE_SEQ_ELEM( tree_one, writer ); cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size); if( ptr2[3] != NULL ) ptr2[3]->prev_v = cur_adr; if( ptr2[0] != NULL ) ptr2[0]->prev_v = cur_adr; ptr1[1] = cur_adr; i_tree++; pt1[0] = tn1; pt1[1] = tp1; } } else { tree_one.pt = tp1; tree_one.sign = (char) (CV_SIGN( sp1 )); tree_one.area = fabs( sp1 ); tree_one.r1 = hp1 / ap1; tree_one.r2 = bp1 / ap1; tree_one.next_v1 = ptr2[2]; tree_one.next_v2 = ptr2[3]; tree_two.pt = tn1; tree_two.sign = (char) (CV_SIGN( sn1 )); tree_two.area = fabs( sn1 ); tree_two.r1 = hn1 / an1; tree_two.r2 = bn1 / an1; tree_two.next_v1 = ptr2[0]; tree_two.next_v2 = ptr2[1]; CV_WRITE_SEQ_ELEM( tree_one, writer ); cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size); if( sp1_c > sn1_c ) { if( ptr2[2] != NULL ) ptr2[2]->prev_v = cur_adr; if( ptr2[3] != NULL ) ptr2[3]->prev_v = cur_adr; ptr1[0] = cur_adr; i_tree++; CV_WRITE_SEQ_ELEM( tree_two, writer ); cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size); if( ptr2[0] != NULL ) ptr2[0]->prev_v = cur_adr; if( ptr2[1] != NULL ) ptr2[1]->prev_v = cur_adr; ptr1[1] = cur_adr; i_tree++; pt1[0] = tn2; pt1[1] = t; } else { CV_WRITE_SEQ_ELEM( tree_two, writer ); cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size); if( ptr2[0] != NULL ) ptr2[0]->prev_v = cur_adr; if( ptr2[1] != NULL ) ptr2[1]->prev_v = cur_adr; ptr1[0] = cur_adr; i_tree++; CV_WRITE_SEQ_ELEM( tree_one, writer ); cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size); if( ptr2[2] != NULL ) ptr2[2]->prev_v = cur_adr; if( ptr2[3] != NULL ) ptr2[3]->prev_v = cur_adr; ptr1[1] = cur_adr; i_tree++; pt1[0] = t; pt1[1] = tn2; } } /* form root */ s = cvContourArea( contour ); tree_root->pt = pt1[1]; tree_root->sign = 0; tree_root->area = fabs( s ); tree_root->r1 = 0; tree_root->r2 = 0; tree_root->next_v1 = ptr1[0]; tree_root->next_v2 = ptr1[1]; tree_root->prev_v = NULL; ptr1[0]->prev_v = (_CvTrianAttr *) tree_root; ptr1[1]->prev_v = (_CvTrianAttr *) tree_root; /* write binary tree root */ /* CV_WRITE_SEQ_ELEM (tree_one, start_writer); */ i_tree++; /* create Sequence hearder */ *((CvSeq **) tree) = cvEndWriteSeq( &writer ); /* write points for the main segment into sequence header */ (*tree)->p1 = pt1[0]; M_END: cvFree( &ptr_n ); cvFree( &ptr_p ); cvFree( &num_n ); cvFree( &num_p ); cvFree( &pt_n ); cvFree( &pt_p ); return status; }
void icvCalcContoursCorrespondence(CvSeq* contour1, CvSeq* contour2, CvSeq** corr, CvMemStorage* storage) { int i,j; // counter of cycles int Ni,Nj; // size of contours _CvWork** W; // graph for search minimum of work CvPoint* point1; // array of first contour point CvPoint* point2; // array of second contour point CvPoint2D32f* edges1; // array of first contour edge CvPoint2D32f* edges2; // array of second contour edge //CvPoint null_edge = {0,0}; // CvPoint2D32f small_edge; //double inf; // infinity CvSeq* corr01; CvSeqWriter writer; char path; // // Find size of contours Ni = contour1->total + 1; Nj = contour2->total + 1; // Create arrays W = (_CvWork**)malloc(sizeof(_CvWork*)*Ni); for(i=0; i<Ni; i++) { W[i] = (_CvWork*)malloc(sizeof(_CvWork)*Nj); } point1 = (CvPoint* )malloc( Ni*sizeof(CvPoint) ); point2 = (CvPoint* )malloc( Nj*sizeof(CvPoint) ); edges1 = (CvPoint2D32f* )malloc( (Ni-1)*sizeof(CvPoint2D32f) ); edges2 = (CvPoint2D32f* )malloc( (Nj-1)*sizeof(CvPoint2D32f) ); // Initialize arrays of point cvCvtSeqToArray( contour1, point1, CV_WHOLE_SEQ ); cvCvtSeqToArray( contour2, point2, CV_WHOLE_SEQ ); point1[Ni-1] = point1[0]; point2[Nj-1] = point2[0]; for(i=0; i<Ni-1; i++) { edges1[i].x = (float)( point1[i+1].x - point1[i].x ); edges1[i].y = (float)( point1[i+1].y - point1[i].y ); }; for(i=0; i<Nj-1; i++) { edges2[i].x = (float)( point2[i+1].x - point2[i].x ); edges2[i].y = (float)( point2[i+1].y - point2[i].y ); }; // Find infinity constant //inf=1; ///////////// //Find min path in graph ///////////// W[0][0].w_east = 0; W[0][0].w_south = 0; W[0][0].w_southeast = 0; W[1][1].w_southeast = _cvStretchingWork( &edges1[0], &edges2[0] ); W[1][1].w_east = inf; W[1][1].w_south = inf; W[1][1].path_se = PATH_TO_SE; W[0][1].w_south = _cvStretchingWork( &null_edge, &edges2[0] ); W[0][1].path_s = 3; W[1][0].w_east = _cvStretchingWork( &edges2[0], &null_edge ); W[1][0].path_e = PATH_TO_E; for( i=1; i<Ni; i++ ) { W[i][0].w_south = inf; W[i][0].w_southeast = inf; } for(j=1; j<Nj; j++) { W[0][j].w_east = inf; W[0][j].w_southeast = inf; } for(i=2; i<Ni; i++) { j=0;///////// W[i][j].w_east = W[i-1][j].w_east; W[i][j].w_east = W[i][j].w_east /*+ _cvBendingWork( &edges1[i-2], &edges1[i-1], &null_edge, &null_edge, NULL )*/; W[i][j].w_east = W[i][j].w_east + _cvStretchingWork( &edges2[i-1], &null_edge ); W[i][j].path_e = PATH_TO_E; j=1;////////// W[i][j].w_south = inf; _cvWorkEast (i, j, W, edges1, edges2); W[i][j].w_southeast = W[i-1][j-1].w_east; W[i][j].w_southeast = W[i][j].w_southeast + _cvStretchingWork( &edges1[i-1], &edges2[j-1] ); small_edge.x = NULL_EDGE*edges1[i-2].x; small_edge.y = NULL_EDGE*edges1[i-2].y; W[i][j].w_southeast = W[i][j].w_southeast + _cvBendingWork( &edges1[i-2], &edges1[i-1], /*&null_edge*/&small_edge, &edges2[j-1]/*, &edges2[Nj-2]*/); W[i][j].path_se = PATH_TO_E; } for(j=2; j<Nj; j++) { i=0;////////// W[i][j].w_south = W[i][j-1].w_south; W[i][j].w_south = W[i][j].w_south + _cvStretchingWork( &null_edge, &edges2[j-1] ); W[i][j].w_south = W[i][j].w_south /*+ _cvBendingWork( &null_edge, &null_edge, &edges2[j-2], &edges2[j-1], NULL )*/; W[i][j].path_s = 3; i=1;/////////// W[i][j].w_east= inf; _cvWorkSouth(i, j, W, edges1, edges2); W[i][j].w_southeast = W[i-1][j-1].w_south; W[i][j].w_southeast = W[i][j].w_southeast + _cvStretchingWork( &edges1[i-1], &edges2[j-1] ); small_edge.x = NULL_EDGE*edges2[j-2].x; small_edge.y = NULL_EDGE*edges2[j-2].y; W[i][j].w_southeast = W[i][j].w_southeast + _cvBendingWork( /*&null_edge*/&small_edge, &edges1[i-1], &edges2[j-2], &edges2[j-1]/*, &edges1[Ni-2]*/); W[i][j].path_se = 3; } for(i=2; i<Ni; i++) for(j=2; j<Nj; j++) { _cvWorkEast (i, j, W, edges1, edges2); _cvWorkSouthEast(i, j, W, edges1, edges2); _cvWorkSouth (i, j, W, edges1, edges2); } i=Ni-1; j=Nj-1; *corr = cvCreateSeq(0, sizeof(CvSeq), sizeof(int), storage ); corr01 = *corr; cvStartAppendToSeq( corr01, &writer ); if( W[i][j].w_east > W[i][j].w_southeast ) { if( W[i][j].w_southeast > W[i][j].w_south ) { path = 3; } else { path = PATH_TO_SE; } } else { if( W[i][j].w_east < W[i][j].w_south ) { path = PATH_TO_E; } else { path = 3; } } do { CV_WRITE_SEQ_ELEM( j, writer ); switch( path ) { case PATH_TO_E: path = W[i][j].path_e; i--; cvFlushSeqWriter( &writer ); corr01->h_next = cvCreateSeq( 0, sizeof(CvSeq), sizeof(int), storage ); corr01 = corr01->h_next; cvStartAppendToSeq( corr01, &writer ); break; case PATH_TO_SE: path = W[i][j].path_se; j--; i--; cvFlushSeqWriter( &writer ); corr01->h_next = cvCreateSeq( 0, sizeof(CvSeq), sizeof(int), storage ); corr01 = corr01->h_next; cvStartAppendToSeq( corr01, &writer ); break; case 3: path = W[i][j].path_s; j--; break; } } while( (i>=0) && (j>=0) ); cvFlushSeqWriter( &writer ); // Free memory for(i=1; i<Ni; i++) { free(W[i]); } free(W); free(point1); free(point2); free(edges1); free(edges2); }
CV_IMPL CvBox2D cvMinAreaRect2( const CvArr* array, CvMemStorage* storage ) { CvMemStorage* temp_storage = 0; CvBox2D box; CvPoint2D32f* points = 0; CV_FUNCNAME( "cvMinAreaRect2" ); memset(&box, 0, sizeof(box)); __BEGIN__; int i, n; CvSeqReader reader; CvContour contour_header; CvSeqBlock block; CvSeq* ptseq = (CvSeq*)array; CvPoint2D32f out[3]; if( CV_IS_SEQ(ptseq) ) { if( !CV_IS_SEQ_POINT_SET(ptseq) && (CV_SEQ_KIND(ptseq) != CV_SEQ_KIND_CURVE || !CV_IS_SEQ_CONVEX(ptseq) || CV_SEQ_ELTYPE(ptseq) != CV_SEQ_ELTYPE_PPOINT )) CV_ERROR( CV_StsUnsupportedFormat, "Input sequence must consist of 2d points or pointers to 2d points" ); if( !storage ) storage = ptseq->storage; } else { CV_CALL( ptseq = cvPointSeqFromMat( CV_SEQ_KIND_GENERIC, array, &contour_header, &block )); } if( storage ) { CV_CALL( temp_storage = cvCreateChildMemStorage( storage )); } else { CV_CALL( temp_storage = cvCreateMemStorage(1 << 10)); } if( !CV_IS_SEQ_CONVEX( ptseq )) { CV_CALL( ptseq = cvConvexHull2( ptseq, temp_storage, CV_CLOCKWISE, 1 )); } else if( !CV_IS_SEQ_POINT_SET( ptseq )) { CvSeqWriter writer; if( !CV_IS_SEQ(ptseq->v_prev) || !CV_IS_SEQ_POINT_SET(ptseq->v_prev)) CV_ERROR( CV_StsBadArg, "Convex hull must have valid pointer to point sequence stored in v_prev" ); cvStartReadSeq( ptseq, &reader ); cvStartWriteSeq( CV_SEQ_KIND_CURVE|CV_SEQ_FLAG_CONVEX|CV_SEQ_ELTYPE(ptseq->v_prev), sizeof(CvContour), CV_ELEM_SIZE(ptseq->v_prev->flags), temp_storage, &writer ); for( i = 0; i < ptseq->total; i++ ) { CvPoint pt = **(CvPoint**)(reader.ptr); CV_WRITE_SEQ_ELEM( pt, writer ); } ptseq = cvEndWriteSeq( &writer ); } n = ptseq->total; CV_CALL( points = (CvPoint2D32f*)cvAlloc( n*sizeof(points[0]) )); cvStartReadSeq( ptseq, &reader ); if( CV_SEQ_ELTYPE( ptseq ) == CV_32SC2 ) { for( i = 0; i < n; i++ ) { CvPoint pt; CV_READ_SEQ_ELEM( pt, reader ); points[i].x = (float)pt.x; points[i].y = (float)pt.y; } } else { for( i = 0; i < n; i++ ) { CV_READ_SEQ_ELEM( points[i], reader ); } } if( n > 2 ) { icvRotatingCalipers( points, n, CV_CALIPERS_MINAREARECT, (float*)out ); box.center.x = out[0].x + (out[1].x + out[2].x)*0.5f; box.center.y = out[0].y + (out[1].y + out[2].y)*0.5f; box.size.height = (float)sqrt((double)out[1].x*out[1].x + (double)out[1].y*out[1].y); box.size.width = (float)sqrt((double)out[2].x*out[2].x + (double)out[2].y*out[2].y); box.angle = (float)atan2( -(double)out[1].y, (double)out[1].x ); } else if( n == 2 ) { box.center.x = (points[0].x + points[1].x)*0.5f; box.center.y = (points[0].y + points[1].y)*0.5f; double dx = points[1].x - points[0].x; double dy = points[1].y - points[0].y; box.size.height = (float)sqrt(dx*dx + dy*dy); box.size.width = 0; box.angle = (float)atan2( -dy, dx ); } else { if( n == 1 ) box.center = points[0]; } box.angle = (float)(box.angle*180/CV_PI); __END__; cvReleaseMemStorage( &temp_storage ); cvFree( &points ); return box; }
static int icvFindContoursInInterval( const CvArr* src, /*int minValue, int maxValue,*/ CvMemStorage* storage, CvSeq** result, int contourHeaderSize ) { int count = 0; CvMemStorage* storage00 = 0; CvMemStorage* storage01 = 0; CvSeq* first = 0; CV_FUNCNAME( "icvFindContoursInInterval" ); __BEGIN__; int i, j, k, n; uchar* src_data = 0; int img_step = 0; CvSize img_size; int connect_flag; int lower_total; int upper_total; int all_total; CvSeq* runs; CvLinkedRunPoint tmp; CvLinkedRunPoint* tmp_prev; CvLinkedRunPoint* upper_line = 0; CvLinkedRunPoint* lower_line = 0; CvLinkedRunPoint* last_elem; CvLinkedRunPoint* upper_run = 0; CvLinkedRunPoint* lower_run = 0; CvLinkedRunPoint* prev_point = 0; CvSeqWriter writer_ext; CvSeqWriter writer_int; CvSeqWriter writer; CvSeqReader reader; CvSeq* external_contours; CvSeq* internal_contours; CvSeq* prev = 0; if( !storage ) CV_ERROR( CV_StsNullPtr, "NULL storage pointer" ); if( !result ) CV_ERROR( CV_StsNullPtr, "NULL double CvSeq pointer" ); if( contourHeaderSize < (int)sizeof(CvContour)) CV_ERROR( CV_StsBadSize, "Contour header size must be >= sizeof(CvContour)" ); CV_CALL( storage00 = cvCreateChildMemStorage(storage)); CV_CALL( storage01 = cvCreateChildMemStorage(storage)); { CvMat stub, *mat; CV_CALL( mat = cvGetMat( src, &stub )); if( !CV_IS_MASK_ARR(mat)) CV_ERROR( CV_StsBadArg, "Input array must be 8uC1 or 8sC1" ); src_data = mat->data.ptr; img_step = mat->step; img_size = cvGetMatSize( mat ); } // Create temporary sequences runs = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvLinkedRunPoint), storage00 ); cvStartAppendToSeq( runs, &writer ); cvStartWriteSeq( 0, sizeof(CvSeq), sizeof(CvLinkedRunPoint*), storage01, &writer_ext ); cvStartWriteSeq( 0, sizeof(CvSeq), sizeof(CvLinkedRunPoint*), storage01, &writer_int ); tmp_prev = &(tmp); tmp_prev->next = 0; tmp_prev->link = 0; // First line. None of runs is binded tmp.pt.y = 0; i = 0; CV_WRITE_SEQ_ELEM( tmp, writer ); upper_line = (CvLinkedRunPoint*)CV_GET_WRITTEN_ELEM( writer ); tmp_prev = upper_line; for( j = 0; j < img_size.width; ) { for( ; j < img_size.width && !ICV_IS_COMPONENT_POINT(src_data[j]); j++ ) ; if( j == img_size.width ) break; tmp.pt.x = j; CV_WRITE_SEQ_ELEM( tmp, writer ); tmp_prev->next = (CvLinkedRunPoint*)CV_GET_WRITTEN_ELEM( writer ); tmp_prev = tmp_prev->next; for( ; j < img_size.width && ICV_IS_COMPONENT_POINT(src_data[j]); j++ ) ; tmp.pt.x = j-1; CV_WRITE_SEQ_ELEM( tmp, writer ); tmp_prev->next = (CvLinkedRunPoint*)CV_GET_WRITTEN_ELEM( writer ); tmp_prev->link = tmp_prev->next; // First point of contour CV_WRITE_SEQ_ELEM( tmp_prev, writer_ext ); tmp_prev = tmp_prev->next; } cvFlushSeqWriter( &writer ); upper_line = upper_line->next; upper_total = runs->total - 1; last_elem = tmp_prev; tmp_prev->next = 0; for( i = 1; i < img_size.height; i++ ) { //------// Find runs in next line src_data += img_step; tmp.pt.y = i; all_total = runs->total; for( j = 0; j < img_size.width; ) { for( ; j < img_size.width && !ICV_IS_COMPONENT_POINT(src_data[j]); j++ ) ; if( j == img_size.width ) break; tmp.pt.x = j; CV_WRITE_SEQ_ELEM( tmp, writer ); tmp_prev->next = (CvLinkedRunPoint*)CV_GET_WRITTEN_ELEM( writer ); tmp_prev = tmp_prev->next; for( ; j < img_size.width && ICV_IS_COMPONENT_POINT(src_data[j]); j++ ) ; tmp.pt.x = j-1; CV_WRITE_SEQ_ELEM( tmp, writer ); tmp_prev = tmp_prev->next = (CvLinkedRunPoint*)CV_GET_WRITTEN_ELEM( writer ); }//j cvFlushSeqWriter( &writer ); lower_line = last_elem->next; lower_total = runs->total - all_total; last_elem = tmp_prev; tmp_prev->next = 0; //------// //------// Find links between runs of lower_line and upper_line upper_run = upper_line; lower_run = lower_line; connect_flag = ICV_SINGLE; for( k = 0, n = 0; k < upper_total/2 && n < lower_total/2; ) { switch( connect_flag ) { case ICV_SINGLE: if( upper_run->next->pt.x < lower_run->next->pt.x ) { if( upper_run->next->pt.x >= lower_run->pt.x -1 ) { lower_run->link = upper_run; connect_flag = ICV_CONNECTING_ABOVE; prev_point = upper_run->next; } else upper_run->next->link = upper_run; k++; upper_run = upper_run->next->next; } else { if( upper_run->pt.x <= lower_run->next->pt.x +1 ) { lower_run->link = upper_run; connect_flag = ICV_CONNECTING_BELOW; prev_point = lower_run->next; } else { lower_run->link = lower_run->next; // First point of contour CV_WRITE_SEQ_ELEM( lower_run, writer_ext ); } n++; lower_run = lower_run->next->next; } break; case ICV_CONNECTING_ABOVE: if( upper_run->pt.x > lower_run->next->pt.x +1 ) { prev_point->link = lower_run->next; connect_flag = ICV_SINGLE; n++; lower_run = lower_run->next->next; } else { prev_point->link = upper_run; if( upper_run->next->pt.x < lower_run->next->pt.x ) { k++; prev_point = upper_run->next; upper_run = upper_run->next->next; } else { connect_flag = ICV_CONNECTING_BELOW; prev_point = lower_run->next; n++; lower_run = lower_run->next->next; } } break; case ICV_CONNECTING_BELOW: if( lower_run->pt.x > upper_run->next->pt.x +1 ) { upper_run->next->link = prev_point; connect_flag = ICV_SINGLE; k++; upper_run = upper_run->next->next; } else { // First point of contour CV_WRITE_SEQ_ELEM( lower_run, writer_int ); lower_run->link = prev_point; if( lower_run->next->pt.x < upper_run->next->pt.x ) { n++; prev_point = lower_run->next; lower_run = lower_run->next->next; } else { connect_flag = ICV_CONNECTING_ABOVE; k++; prev_point = upper_run->next; upper_run = upper_run->next->next; } } break; } }// k, n for( ; n < lower_total/2; n++ ) { if( connect_flag != ICV_SINGLE ) { prev_point->link = lower_run->next; connect_flag = ICV_SINGLE; lower_run = lower_run->next->next; continue; } lower_run->link = lower_run->next; //First point of contour CV_WRITE_SEQ_ELEM( lower_run, writer_ext ); lower_run = lower_run->next->next; } for( ; k < upper_total/2; k++ ) { if( connect_flag != ICV_SINGLE ) { upper_run->next->link = prev_point; connect_flag = ICV_SINGLE; upper_run = upper_run->next->next; continue; } upper_run->next->link = upper_run; upper_run = upper_run->next->next; } upper_line = lower_line; upper_total = lower_total; }//i upper_run = upper_line; //the last line of image for( k = 0; k < upper_total/2; k++ ) { upper_run->next->link = upper_run; upper_run = upper_run->next->next; } //------// //------//Find end read contours external_contours = cvEndWriteSeq( &writer_ext ); internal_contours = cvEndWriteSeq( &writer_int ); for( k = 0; k < 2; k++ ) { CvSeq* contours = k == 0 ? external_contours : internal_contours; cvStartReadSeq( contours, &reader ); for( j = 0; j < contours->total; j++, count++ ) { CvLinkedRunPoint* p_temp; CvLinkedRunPoint* p00; CvLinkedRunPoint* p01; CvSeq* contour; CV_READ_SEQ_ELEM( p00, reader ); p01 = p00; if( !p00->link ) continue; cvStartWriteSeq( CV_SEQ_ELTYPE_POINT | CV_SEQ_POLYLINE | CV_SEQ_FLAG_CLOSED, contourHeaderSize, sizeof(CvPoint), storage, &writer ); do { CV_WRITE_SEQ_ELEM( p00->pt, writer ); p_temp = p00; p00 = p00->link; p_temp->link = 0; } while( p00 != p01 ); contour = cvEndWriteSeq( &writer ); cvBoundingRect( contour, 1 ); if( k != 0 ) contour->flags |= CV_SEQ_FLAG_HOLE; if( !first ) prev = first = contour; else { contour->h_prev = prev; prev = prev->h_next = contour; } } } __END__; if( !first ) count = -1; if( result ) *result = first; cvReleaseMemStorage(&storage00); cvReleaseMemStorage(&storage01); return count; }
static CvStatus icvFetchContourEx( char* ptr, int step, CvPoint pt, CvSeq* contour, int _method, int nbd, CvRect* _rect ) { int deltas[16]; CvSeqWriter writer; char *i0 = ptr, *i1, *i3, *i4; CvRect rect; int prev_s = -1, s, s_end; int method = _method - 1; assert( (unsigned) _method <= CV_CHAIN_APPROX_SIMPLE ); assert( 1 < nbd && nbd < 128 ); /* initialize local state */ CV_INIT_3X3_DELTAS( deltas, step, 1 ); memcpy( deltas + 8, deltas, 8 * sizeof( deltas[0] )); /* initialize writer */ cvStartAppendToSeq( contour, &writer ); if( method < 0 ) ((CvChain *)contour)->origin = pt; rect.x = rect.width = pt.x; rect.y = rect.height = pt.y; s_end = s = CV_IS_SEQ_HOLE( contour ) ? 0 : 4; do { s = (s - 1) & 7; i1 = i0 + deltas[s]; if( *i1 != 0 ) break; } while( s != s_end ); if( s == s_end ) /* single pixel domain */ { *i0 = (char) (nbd | 0x80); if( method >= 0 ) { CV_WRITE_SEQ_ELEM( pt, writer ); } } else { i3 = i0; prev_s = s ^ 4; /* follow border */ for( ;; ) { s_end = s; for( ;; ) { i4 = i3 + deltas[++s]; if( *i4 != 0 ) break; } s &= 7; /* check "right" bound */ if( (unsigned) (s - 1) < (unsigned) s_end ) { *i3 = (char) (nbd | 0x80); } else if( *i3 == 1 ) { *i3 = (char) nbd; } if( method < 0 ) { char _s = (char) s; CV_WRITE_SEQ_ELEM( _s, writer ); } else if( s != prev_s || method == 0 ) { CV_WRITE_SEQ_ELEM( pt, writer ); } if( s != prev_s ) { /* update bounds */ if( pt.x < rect.x ) rect.x = pt.x; else if( pt.x > rect.width ) rect.width = pt.x; if( pt.y < rect.y ) rect.y = pt.y; else if( pt.y > rect.height ) rect.height = pt.y; } prev_s = s; pt.x += icvCodeDeltas[s].x; pt.y += icvCodeDeltas[s].y; if( i4 == i0 && i3 == i1 ) break; i3 = i4; s = (s + 4) & 7; } /* end of border following loop */ } rect.width -= rect.x - 1; rect.height -= rect.y - 1; cvEndWriteSeq( &writer ); if( _method != CV_CHAIN_CODE ) ((CvContour*)contour)->rect = rect; assert( writer.seq->total == 0 && writer.seq->first == 0 || writer.seq->total > writer.seq->first->count || (writer.seq->first->prev == writer.seq->first && writer.seq->first->next == writer.seq->first) ); if( _rect ) *_rect = rect; return CV_OK; }
static int fmaConvexHullContour(void* prm) { long lErrors = 0; static int read_param = 0; int i,j; CvRect rect; int minx = 1000000, maxx = -10000; int miny = 1000000, maxy = -10000; long lParam = (long)prm; CvPoint* points; CvPoint** pointers; CvSeqWriter writer; CvSeqReader reader; CvSeq* contour; CvSeq* hull = NULL; CvMemStorage* storage; if(!read_param) { read_param=1; /* Reading test-parameters */ trslRead( &lNumPoints, "4096", "Maximal number of points" ); trslRead( &lLoopsProp, "100", "Loops" ); } storage = cvCreateMemStorage(0); cvClearMemStorage( storage ); points = (CvPoint*)icvAlloc( lNumPoints * sizeof(CvPoint) ); pointers = (CvPoint**)icvAlloc( lNumPoints * sizeof(CvPoint*) ); for( j = 0; j < lLoopsProp; j++ ) { int numpts; /* Allocating points */ cvStartWriteSeq( CV_SEQ_SIMPLE_POLYGON , sizeof(CvSeq), sizeof(CvPoint), storage, &writer ); ats1iInitRandom( 5, lNumPoints, &numpts, 1 ); /* init points */ ats1iInitRandom( 5, 1024, &lScreenSize, 1 ); for( i = 0; i < numpts ; i++ ) { CvPoint pt; ats1iInitRandom( 0, lScreenSize, (int*)&pt, 2 ); CV_WRITE_SEQ_ELEM( pt, writer ); minx = MIN(pt.x, minx ); maxx = MAX(pt.x, maxx ); miny = MIN(pt.y, miny ); maxy = MAX(pt.y, maxy ); } contour = cvEndWriteSeq( &writer ); rect.x = minx; rect.y = miny; rect.width = maxx- minx + 1; rect.height = maxy- miny + 1; switch (lParam) { case APPROX: hull = cvContourConvexHullApprox( contour, 1, CV_COUNTER_CLOCKWISE, storage ); break; case EXACT: hull = cvContourConvexHull( contour,CV_COUNTER_CLOCKWISE, storage ); break; }/*switch */ /* check errors */ cvStartReadSeq( contour, &reader, 0 ); for( i = 0; i < contour->total; i++ ) { CV_READ_SEQ_ELEM( points[i], reader ); } cvStartReadSeq( hull, &reader, 0 ); for( i = 0; i < hull->total; i++ ) { CV_READ_SEQ_ELEM( pointers[i], reader ); } cvClearMemStorage( storage ); lErrors += atsCheckConvexHullP( points, contour->total, pointers, hull->total, CV_COUNTER_CLOCKWISE ); } /* for */ icvFree(&points); icvFree(&pointers); cvReleaseMemStorage(&storage); if( lErrors == 0 ) return trsResult( TRS_OK, "No errors fixed for this test" ); else return trsResult( TRS_FAIL, "Total fixed %d errors", lErrors ); }