Beispiel #1
0
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;
}
Beispiel #3
0
/**
- 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
Beispiel #5
0
/**
- 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 );
}
Beispiel #6
0
/**
- 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 );

}
Beispiel #7
0
/**
- 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 );
}
Beispiel #8
0
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__;
}
Beispiel #9
0
/**
- 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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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
Beispiel #13
0
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;
}
Beispiel #14
0
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;
}
Beispiel #15
0
/***************************************************************************************\
*
*   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;
}
Beispiel #16
0
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);
}
Beispiel #17
0
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;
}