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; }
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
/** - 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: 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: 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__; }
/** - 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 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 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; }
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 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; }
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; }
/***************************************************************************************\ * * 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; }
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); }
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; }