예제 #1
0
// Returns the number of clean char
int FTS_ANPR_Seg::findCleanChar( FTS_ANPR_SegResult& oSegResult, CvCmpFunc is_equal )
{
    cvClearSeq( m_poSegCharSeq );

    // Fill an opencv sequence with chars
    // --------------------------------------------------------------------
    std::list<FTS_ANPR_SegChar*>::iterator i  = oSegResult.m_oChars.begin();
    std::list<FTS_ANPR_SegChar*>::iterator iE = oSegResult.m_oChars.end();
    for( ; i != iE; ++i )
    {
        FTS_ANPR_SegChar* poSegChar = *i;

        cvSeqPush( m_poSegCharSeq, &poSegChar );
    }

    // Partition into equivalent classes such that all chars in the same class
    // are the same size and non-overlapping.
    // --------------------------------------------------------------------
    CvSeq* poLabels = 0;
    int nClassCount = cvSeqPartition( m_poSegCharSeq,
                                      0,
                                      &poLabels,
                                      is_equal,// FTS_ANPR_Seg::isSameSizeAndNoOverlap,
                                      this );

    int nCleanCharCount = 0;

    if( nClassCount < (int) oSegResult.m_oChars.size() ) // means there's at least one class with at least 2 chars in it
    {
        // Find the biggest partition. This partition contains all the chars that are
        // the same size and DO NOT overlap with each other.
        // --------------------------------------------------------------------

        std::vector<int>& oCount = m_oIntVector; // Num chars in each class

        oCount.clear();
        oCount.assign( nClassCount, 0 );

        for( int n = 0; n < poLabels->total; ++n )
        {
            int nClassIdx = *(int*) cvGetSeqElem( poLabels, n );
            ++oCount.at( nClassIdx );
        }

        int nBiggestClassIdx = std::distance(                   oCount.begin(),
                                              std::max_element( oCount.begin(), oCount.end() )
                                              );

        // Mark all chars in the biggest class as clean chars.
        // --------------------------------------------------------------------
        i  = oSegResult.m_oChars.begin();
        iE = oSegResult.m_oChars.end();
        for( unsigned int nIdx = 0; i != iE; ++i, ++nIdx )
        {
            int nClassIdx = *(int*) cvGetSeqElem(poLabels, nIdx);
            if (nClassIdx == nBiggestClassIdx)
            {
                (*i)->m_bClean = true;
                ++nCleanCharCount;
            }
            else
            {
                (*i)->m_bClean = false;
            }
        }

    } // if at least one class with more than one char


    // Release the memory storage of label sequence
    // --------------------------------------------------------------------
    cvClearSeq( poLabels );
    cvClearSeq( m_poSegCharSeq );

    cvClearMemStorage( m_poStorage ); // clear, don't deallocate

    return nCleanCharCount;
}
void cvFindBlobsByCCClasters(IplImage* pFG, CvBlobSeq* pBlobs, CvMemStorage* storage)
{   /* Create contours: */
    IplImage*       pIB = NULL;
    CvSeq*          cnt = NULL;
    CvSeq*          cnt_list = cvCreateSeq(0,sizeof(CvSeq),sizeof(CvSeq*), storage );
    CvSeq*          clasters = NULL;
    int             claster_cur, claster_num;

    pIB = cvCloneImage(pFG);
    cvThreshold(pIB,pIB,128,255,CV_THRESH_BINARY);
    cvFindContours(pIB,storage, &cnt, sizeof(CvContour), CV_RETR_EXTERNAL);
    cvReleaseImage(&pIB);

    /* Create cnt_list.      */
    /* Process each contour: */
    for(; cnt; cnt=cnt->h_next)
    {
        cvSeqPush( cnt_list, &cnt);
    }

    claster_num = cvSeqPartition( cnt_list, storage, &clasters, CompareContour, NULL );

    for(claster_cur=0; claster_cur<claster_num; ++claster_cur)
    {
        int         cnt_cur;
        CvBlob      NewBlob;
        double      M00,X,Y,XX,YY; /* image moments */
        CvMoments   m;
        CvRect      rect_res = cvRect(-1,-1,-1,-1);
        CvMat       mat;

        for(cnt_cur=0; cnt_cur<clasters->total; ++cnt_cur)
        {
            CvRect  rect;
            CvSeq*  cnt;
            int k = *(int*)cvGetSeqElem( clasters, cnt_cur );
            if(k!=claster_cur) continue;
            cnt = *(CvSeq**)cvGetSeqElem( cnt_list, cnt_cur );
            rect = ((CvContour*)cnt)->rect;

            if(rect_res.height<0)
            {
                rect_res = rect;
            }
            else
            {   /* Unite rects: */
                int x0,x1,y0,y1;
                x0 = MIN(rect_res.x,rect.x);
                y0 = MIN(rect_res.y,rect.y);
                x1 = MAX(rect_res.x+rect_res.width,rect.x+rect.width);
                y1 = MAX(rect_res.y+rect_res.height,rect.y+rect.height);
                rect_res.x = x0;
                rect_res.y = y0;
                rect_res.width = x1-x0;
                rect_res.height = y1-y0;
            }
        }

        if(rect_res.height < 1 || rect_res.width < 1)
        {
            X = 0;
            Y = 0;
            XX = 0;
            YY = 0;
        }
        else
        {
            cvMoments( cvGetSubRect(pFG,&mat,rect_res), &m, 0 );
            M00 = cvGetSpatialMoment( &m, 0, 0 );
            if(M00 <= 0 ) continue;
            X = cvGetSpatialMoment( &m, 1, 0 )/M00;
            Y = cvGetSpatialMoment( &m, 0, 1 )/M00;
            XX = (cvGetSpatialMoment( &m, 2, 0 )/M00) - X*X;
            YY = (cvGetSpatialMoment( &m, 0, 2 )/M00) - Y*Y;
        }
        NewBlob = cvBlob(rect_res.x+(float)X,rect_res.y+(float)Y,(float)(4*sqrt(XX)),(float)(4*sqrt(YY)));
        pBlobs->AddBlob(&NewBlob);

    }   /* Next cluster. */

    #if 0
    {   // Debug info:
        IplImage* pI = cvCreateImage(cvSize(pFG->width,pFG->height),IPL_DEPTH_8U,3);
        cvZero(pI);
        for(claster_cur=0; claster_cur<claster_num; ++claster_cur)
        {
            int         cnt_cur;
            CvScalar    color = CV_RGB(rand()%256,rand()%256,rand()%256);

            for(cnt_cur=0; cnt_cur<clasters->total; ++cnt_cur)
            {
                CvSeq*  cnt;
                int k = *(int*)cvGetSeqElem( clasters, cnt_cur );
                if(k!=claster_cur) continue;
                cnt = *(CvSeq**)cvGetSeqElem( cnt_list, cnt_cur );
                cvDrawContours( pI, cnt, color, color, 0, 1, 8);
            }

            CvBlob* pB = pBlobs->GetBlob(claster_cur);
            int x = cvRound(CV_BLOB_RX(pB)), y = cvRound(CV_BLOB_RY(pB));
            cvEllipse( pI,
                cvPointFrom32f(CV_BLOB_CENTER(pB)),
                cvSize(MAX(1,x), MAX(1,y)),
                0, 0, 360,
                color, 1 );
        }

        cvNamedWindow( "Clusters", 0);
        cvShowImage( "Clusters",pI );

        cvReleaseImage(&pI);

    }   /* Debug info. */
    #endif

}   /* cvFindBlobsByCCClasters */
예제 #3
0
CvSeq * MBLBPDetectMultiScale( const IplImage* img,
                               MBLBPCascade * pCascade,
                               CvMemStorage* storage, 
                               int scale_factor1024x,
                               int min_neighbors, 
                               int min_size,
							   int max_size)
{
    IplImage stub;
    CvMat mat, *pmat;
    CvSeq* seq = 0;
    CvSeq* seq2 = 0;
    CvSeq* idx_seq = 0;
    CvSeq* result_seq = 0;
    CvSeq* positions = 0;
    CvMemStorage* temp_storage = 0;
    CvAvgComp* comps = 0;
    
    CV_FUNCNAME( "MBLBPDetectMultiScale" );

    __BEGIN__;

    int factor1024x;
    int factor1024x_max;
    int coi;

    if( ! pCascade) 
        CV_ERROR( CV_StsNullPtr, "Invalid classifier cascade" );

    if( !storage )
        CV_ERROR( CV_StsNullPtr, "Null storage pointer" );

    CV_CALL( img = cvGetImage( img, &stub));
    CV_CALL( pmat = cvGetMat( img, &mat, &coi));

    if( coi )
        CV_ERROR( CV_BadCOI, "COI is not supported" );

    if( CV_MAT_DEPTH(pmat->type) != CV_8U )
        CV_ERROR( CV_StsUnsupportedFormat, "Only 8-bit images are supported" );

    if( CV_MAT_CN(pmat->type) > 1 )
    	CV_ERROR( CV_StsUnsupportedFormat, "Only single-channel images are supported" );

    min_size  = MAX(pCascade->win_width,  min_size);
	if(max_size <=0 )
		max_size = MIN(img->width, img->height);
	if(max_size < min_size)
		return NULL;

	CV_CALL( temp_storage = cvCreateChildMemStorage( storage ));
    seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvRect), temp_storage );
    seq2 = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvAvgComp), temp_storage );
    result_seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvAvgComp), storage );
    positions = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), temp_storage );

    if( min_neighbors == 0 )
        seq = result_seq;

    factor1024x = ((min_size<<10)+(pCascade->win_width/2)) / pCascade->win_width;
	factor1024x_max = (max_size<<10) / pCascade->win_width; //do not round it, to avoid the scan window be out of range

#ifdef _OPENMP
	omp_init_lock(&lock); 
#endif
    for( ; factor1024x <= factor1024x_max;
         factor1024x = ((factor1024x*scale_factor1024x+512)>>10) )
    {
        IplImage * pSmallImage = cvCreateImage( cvSize( ((img->width<<10)+factor1024x/2)/factor1024x, ((img->height<<10)+factor1024x/2)/factor1024x),
                                                IPL_DEPTH_8U, 1);
        try{
			cvResize(img, pSmallImage);
		}
		catch(...)
		{
			cvReleaseImage(&pSmallImage);
			return NULL;
		}
		
		
        CvSize winStride = cvSize( (factor1024x<=2048)+1,  (factor1024x<=2048)+1 );

		cvClearSeq(positions);

        MBLBPDetectSingleScale( pSmallImage, pCascade, positions, winStride);

        for(int i=0; i < (positions ? positions->total : 0); i++)
        {
            CvPoint pt = *(CvPoint*)cvGetSeqElem( positions, i );
            CvRect r = cvRect( (pt.x * factor1024x + 512)>>10,
                               (pt.y * factor1024x + 512)>>10,
                               (pCascade->win_width * factor1024x + 512)>>10,
                               (pCascade->win_height * factor1024x + 512)>>10);

            cvSeqPush(seq, &r);
        }

        cvReleaseImage(&pSmallImage);
    }
#ifdef _OPENMP
	omp_destroy_lock(&lock); 
#endif
  
    if( min_neighbors != 0 )
    {
        // group retrieved rectangles in order to filter out noise 
        int ncomp = cvSeqPartition( seq, 0, &idx_seq, (CvCmpFunc)is_equal, 0 );
        CV_CALL( comps = (CvAvgComp*)cvAlloc( (ncomp+1)*sizeof(comps[0])));
        memset( comps, 0, (ncomp+1)*sizeof(comps[0]));

        // count number of neighbors
        for(int i = 0; i < seq->total; i++ )
        {
            CvRect r1 = *(CvRect*)cvGetSeqElem( seq, i );
            int idx = *(int*)cvGetSeqElem( idx_seq, i );
            assert( (unsigned)idx < (unsigned)ncomp );

            comps[idx].neighbors++;
             
            comps[idx].rect.x += r1.x;
            comps[idx].rect.y += r1.y;
            comps[idx].rect.width += r1.width;
            comps[idx].rect.height += r1.height;
        }

        // calculate average bounding box
        for(int i = 0; i < ncomp; i++ )
        {
            int n = comps[i].neighbors;
            if( n >= min_neighbors )
            {
                CvAvgComp comp;
                comp.rect.x = (comps[i].rect.x*2 + n)/(2*n);
                comp.rect.y = (comps[i].rect.y*2 + n)/(2*n);
                comp.rect.width = (comps[i].rect.width*2 + n)/(2*n);
                comp.rect.height = (comps[i].rect.height*2 + n)/(2*n);
                comp.neighbors = comps[i].neighbors;

                cvSeqPush( seq2, &comp );
            }
        }

        // filter out small face rectangles inside large face rectangles
        for(int i = 0; i < seq2->total; i++ )
        {
            CvAvgComp r1 = *(CvAvgComp*)cvGetSeqElem( seq2, i );
            int j, flag = 1;

            for( j = 0; j < seq2->total; j++ )
            {
                CvAvgComp r2 = *(CvAvgComp*)cvGetSeqElem( seq2, j );
                int distance = (r2.rect.width *2+5)/10;//cvRound( r2.rect.width * 0.2 );
            
                if( i != j &&
                    r1.rect.x >= r2.rect.x - distance &&
                    r1.rect.y >= r2.rect.y - distance &&
                    r1.rect.x + r1.rect.width <= r2.rect.x + r2.rect.width + distance &&
                    r1.rect.y + r1.rect.height <= r2.rect.y + r2.rect.height + distance &&
                    (r2.neighbors > MAX( 3, r1.neighbors ) || r1.neighbors < 3) )
                {
                    flag = 0;
                    break;
                }
            }

            if( flag )
            {
                cvSeqPush( result_seq, &r1 );
                /* cvSeqPush( result_seq, &r1.rect ); */
            }
        }
    }   


    __END__;

    cvReleaseMemStorage( &temp_storage );
    cvFree( &comps );

    return result_seq;
}