CV_IMPL CvBox2D cvMinAreaRect2( const CvArr* array, CvMemStorage* storage ) { cv::Ptr<CvMemStorage> temp_storage; CvBox2D box; cv::AutoBuffer<CvPoint2D32f> _points; CvPoint2D32f* points; memset(&box, 0, sizeof(box)); int i, n; CvSeqReader reader; CvContour contour_header; CvSeqBlock block; CvSeq* ptseq = (CvSeq*)array; CvPoint2D32f out[3]; if( CV_IS_SEQ(ptseq) ) { if( !CV_IS_SEQ_POINT_SET(ptseq) && (CV_SEQ_KIND(ptseq) != CV_SEQ_KIND_CURVE || CV_SEQ_ELTYPE(ptseq) != CV_SEQ_ELTYPE_PPOINT )) CV_Error( CV_StsUnsupportedFormat, "Input sequence must consist of 2d points or pointers to 2d points" ); if( !storage ) storage = ptseq->storage; } else { ptseq = cvPointSeqFromMat( CV_SEQ_KIND_GENERIC, array, &contour_header, &block ); } if( storage ) { temp_storage = cvCreateChildMemStorage( storage ); } else { temp_storage = cvCreateMemStorage(1 << 10); } ptseq = cvConvexHull2( ptseq, temp_storage, CV_CLOCKWISE, 1 ); n = ptseq->total; _points.allocate(n); points = _points; cvStartReadSeq( ptseq, &reader ); if( CV_SEQ_ELTYPE( ptseq ) == CV_32SC2 ) { for( i = 0; i < n; i++ ) { CvPoint pt; CV_READ_SEQ_ELEM( pt, reader ); points[i].x = (float)pt.x; points[i].y = (float)pt.y; } } else { for( i = 0; i < n; i++ ) { CV_READ_SEQ_ELEM( points[i], reader ); } } if( n > 2 ) { icvRotatingCalipers( points, n, CV_CALIPERS_MINAREARECT, (float*)out ); box.center.x = out[0].x + (out[1].x + out[2].x)*0.5f; box.center.y = out[0].y + (out[1].y + out[2].y)*0.5f; box.size.width = (float)sqrt((double)out[1].x*out[1].x + (double)out[1].y*out[1].y); box.size.height = (float)sqrt((double)out[2].x*out[2].x + (double)out[2].y*out[2].y); box.angle = (float)atan2( (double)out[1].y, (double)out[1].x ); } else if( n == 2 ) { box.center.x = (points[0].x + points[1].x)*0.5f; box.center.y = (points[0].y + points[1].y)*0.5f; double dx = points[1].x - points[0].x; double dy = points[1].y - points[0].y; box.size.width = (float)sqrt(dx*dx + dy*dy); box.size.height = 0; box.angle = (float)atan2( dy, dx ); } else { if( n == 1 ) box.center = points[0]; } box.angle = (float)(box.angle*180/CV_PI); return box; }
CvSeq * find_quad( CvSeq * src_contour, CvMemStorage *storage, int min_size) { // stolen from icvGenerateQuads CvMemStorage * temp_storage = cvCreateChildMemStorage( storage ); int flags = CV_CALIB_CB_FILTER_QUADS; CvSeq *dst_contour = 0; const int min_approx_level = 2, max_approx_level = MAX_CONTOUR_APPROX; int approx_level; for( approx_level = min_approx_level; approx_level <= max_approx_level; approx_level++ ) { dst_contour = cvApproxPoly( src_contour, sizeof(CvContour), temp_storage, CV_POLY_APPROX_DP, (float)approx_level ); // we call this again on its own output, because sometimes // cvApproxPoly() does not simplify as much as it should. dst_contour = cvApproxPoly( dst_contour, sizeof(CvContour), temp_storage, CV_POLY_APPROX_DP, (float)approx_level ); if( dst_contour->total == 4 ) break; } // reject non-quadrangles if( dst_contour->total == 4 && cvCheckContourConvexity(dst_contour) ) { CvPoint pt[4]; double d1, d2, p = cvContourPerimeter(dst_contour); double area = fabs(cvContourArea(dst_contour, CV_WHOLE_SEQ)); double dx, dy; for( int i = 0; i < 4; i++ ) pt[i] = *(CvPoint*)cvGetSeqElem(dst_contour, i); dx = pt[0].x - pt[2].x; dy = pt[0].y - pt[2].y; d1 = sqrt(dx*dx + dy*dy); dx = pt[1].x - pt[3].x; dy = pt[1].y - pt[3].y; d2 = sqrt(dx*dx + dy*dy); // philipg. Only accept those quadrangles which are more square // than rectangular and which are big enough double d3, d4; dx = pt[0].x - pt[1].x; dy = pt[0].y - pt[1].y; d3 = sqrt(dx*dx + dy*dy); dx = pt[1].x - pt[2].x; dy = pt[1].y - pt[2].y; d4 = sqrt(dx*dx + dy*dy); if( !(flags & CV_CALIB_CB_FILTER_QUADS) || (d3*1.1 > d4 && d4*1.1 > d3 && d3*d4 < area*1.5 && area > min_size && d1 >= 0.15 * p && d2 >= 0.15 * p) ) { // CvContourEx* parent = (CvContourEx*)(src_contour->v_prev); // parent->counter++; // if( !board || board->counter < parent->counter ) // board = parent; // dst_contour->v_prev = (CvSeq*)parent; //for( i = 0; i < 4; i++ ) cvLine( debug_img, pt[i], pt[(i+1)&3], cvScalar(200,255,255), 1, CV_AA, 0 ); // cvSeqPush( root, &dst_contour ); return dst_contour; } } return NULL; }
/* Initializes scanner structure. Prepare image for scanning ( clear borders and convert all pixels to 0-1. */ CV_IMPL CvContourScanner cvStartFindContours( void* _img, CvMemStorage* storage, int header_size, int mode, int method, CvPoint offset ) { int y; int step; CvSize size; uchar *img = 0; CvContourScanner scanner = 0; CvMat stub, *mat = (CvMat*)_img; CV_FUNCNAME( "cvStartFindContours" ); __BEGIN__; if( !storage ) CV_ERROR( CV_StsNullPtr, "" ); CV_CALL( mat = cvGetMat( mat, &stub )); if( !CV_IS_MASK_ARR( mat )) CV_ERROR( CV_StsUnsupportedFormat, "[Start]FindContours support only 8uC1 images" ); size = cvSize( mat->width, mat->height ); step = mat->step; img = (uchar*)(mat->data.ptr); if( method < 0 || method > CV_CHAIN_APPROX_TC89_KCOS ) CV_ERROR_FROM_STATUS( CV_BADRANGE_ERR ); if( header_size < (int) (method == CV_CHAIN_CODE ? sizeof( CvChain ) : sizeof( CvContour ))) CV_ERROR_FROM_STATUS( CV_BADSIZE_ERR ); scanner = (CvContourScanner)cvAlloc( sizeof( *scanner )); if( !scanner ) CV_ERROR_FROM_STATUS( CV_OUTOFMEM_ERR ); memset( scanner, 0, sizeof( *scanner )); scanner->storage1 = scanner->storage2 = storage; scanner->img0 = (char *) img; scanner->img = (char *) (img + step); scanner->img_step = step; scanner->img_size.width = size.width - 1; /* exclude rightest column */ scanner->img_size.height = size.height - 1; /* exclude bottomost row */ scanner->mode = mode; scanner->offset = offset; scanner->pt.x = scanner->pt.y = 1; scanner->lnbd.x = 0; scanner->lnbd.y = 1; scanner->nbd = 2; scanner->mode = (int) mode; scanner->frame_info.contour = &(scanner->frame); scanner->frame_info.is_hole = 1; scanner->frame_info.next = 0; scanner->frame_info.parent = 0; scanner->frame_info.rect = cvRect( 0, 0, size.width, size.height ); scanner->l_cinfo = 0; scanner->subst_flag = 0; scanner->frame.flags = CV_SEQ_FLAG_HOLE; scanner->approx_method2 = scanner->approx_method1 = method; if( method == CV_CHAIN_APPROX_TC89_L1 || method == CV_CHAIN_APPROX_TC89_KCOS ) scanner->approx_method1 = CV_CHAIN_CODE; if( scanner->approx_method1 == CV_CHAIN_CODE ) { scanner->seq_type1 = CV_SEQ_CHAIN_CONTOUR; scanner->header_size1 = scanner->approx_method1 == scanner->approx_method2 ? header_size : sizeof( CvChain ); scanner->elem_size1 = sizeof( char ); } else { scanner->seq_type1 = CV_SEQ_POLYGON; scanner->header_size1 = scanner->approx_method1 == scanner->approx_method2 ? header_size : sizeof( CvContour ); scanner->elem_size1 = sizeof( CvPoint ); } scanner->header_size2 = header_size; if( scanner->approx_method2 == CV_CHAIN_CODE ) { scanner->seq_type2 = scanner->seq_type1; scanner->elem_size2 = scanner->elem_size1; } else { scanner->seq_type2 = CV_SEQ_POLYGON; scanner->elem_size2 = sizeof( CvPoint ); } scanner->seq_type1 = scanner->approx_method1 == CV_CHAIN_CODE ? CV_SEQ_CHAIN_CONTOUR : CV_SEQ_POLYGON; scanner->seq_type2 = scanner->approx_method2 == CV_CHAIN_CODE ? CV_SEQ_CHAIN_CONTOUR : CV_SEQ_POLYGON; cvSaveMemStoragePos( storage, &(scanner->initial_pos) ); if( method > CV_CHAIN_APPROX_SIMPLE ) { scanner->storage1 = cvCreateChildMemStorage( scanner->storage2 ); } if( mode > CV_RETR_LIST ) { scanner->cinfo_storage = cvCreateChildMemStorage( scanner->storage2 ); scanner->cinfo_set = cvCreateSet( 0, sizeof( CvSet ), sizeof( _CvContourInfo ), scanner->cinfo_storage ); if( scanner->cinfo_storage == 0 || scanner->cinfo_set == 0 ) CV_ERROR_FROM_STATUS( CV_OUTOFMEM_ERR ); } /* make zero borders */ memset( img, 0, size.width ); memset( img + step * (size.height - 1), 0, size.width ); for( y = 1, img += step; y < size.height - 1; y++, img += step ) { img[0] = img[size.width - 1] = 0; } /* converts all pixels to 0 or 1 */ cvThreshold( mat, mat, 0, 1, CV_THRESH_BINARY ); CV_CHECK(); __END__; if( cvGetErrStatus() < 0 ) cvFree( &scanner ); return scanner; }
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; }
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; }
CV_IMPL CvFileStorage* cvOpenFileStorage( const char* query, CvMemStorage* dststorage, int flags, const char* encoding ) { CvFileStorage* fs = 0; int default_block_size = 1 << 18; bool append = (flags & 3) == CV_STORAGE_APPEND; bool mem = (flags & CV_STORAGE_MEMORY) != 0; bool write_mode = (flags & 3) != 0; bool write_base64 = (write_mode || append) && (flags & CV_STORAGE_BASE64) != 0; bool isGZ = false; size_t fnamelen = 0; const char * filename = query; std::vector<std::string> params; if ( !mem ) { params = analyze_file_name( query ); if ( !params.empty() ) filename = params.begin()->c_str(); if ( write_base64 == false && is_param_exist( params, "base64" ) ) write_base64 = (write_mode || append); } if( !filename || filename[0] == '\0' ) { if( !write_mode ) CV_Error( CV_StsNullPtr, mem ? "NULL or empty filename" : "NULL or empty buffer" ); mem = true; } else fnamelen = strlen(filename); if( mem && append ) CV_Error( CV_StsBadFlag, "CV_STORAGE_APPEND and CV_STORAGE_MEMORY are not currently compatible" ); fs = (CvFileStorage*)cvAlloc( sizeof(*fs) ); CV_Assert(fs); memset( fs, 0, sizeof(*fs)); fs->memstorage = cvCreateMemStorage( default_block_size ); fs->dststorage = dststorage ? dststorage : fs->memstorage; fs->flags = CV_FILE_STORAGE; fs->write_mode = write_mode; if( !mem ) { fs->filename = (char*)cvMemStorageAlloc( fs->memstorage, fnamelen+1 ); strcpy( fs->filename, filename ); char* dot_pos = strrchr(fs->filename, '.'); char compression = '\0'; if( dot_pos && dot_pos[1] == 'g' && dot_pos[2] == 'z' && (dot_pos[3] == '\0' || (cv_isdigit(dot_pos[3]) && dot_pos[4] == '\0')) ) { if( append ) { cvReleaseFileStorage( &fs ); CV_Error(CV_StsNotImplemented, "Appending data to compressed file is not implemented" ); } isGZ = true; compression = dot_pos[3]; if( compression ) dot_pos[3] = '\0', fnamelen--; } if( !isGZ ) { fs->file = fopen(fs->filename, !fs->write_mode ? "rt" : !append ? "wt" : "a+t" ); if( !fs->file ) goto _exit_; } else { #if USE_ZLIB char mode[] = { fs->write_mode ? 'w' : 'r', 'b', compression ? compression : '3', '\0' }; fs->gzfile = gzopen(fs->filename, mode); if( !fs->gzfile ) goto _exit_; #else cvReleaseFileStorage( &fs ); CV_Error(CV_StsNotImplemented, "There is no compressed file storage support in this configuration"); #endif } } fs->roots = 0; fs->struct_indent = 0; fs->struct_flags = 0; fs->wrap_margin = 71; if( fs->write_mode ) { int fmt = flags & CV_STORAGE_FORMAT_MASK; if( mem ) fs->outbuf = new std::deque<char>; if( fmt == CV_STORAGE_FORMAT_AUTO && filename ) { const char* dot_pos = NULL; const char* dot_pos2 = NULL; // like strrchr() implementation, but save two last positions simultaneously for (const char* pos = filename; pos[0] != 0; pos++) { if (pos[0] == '.') { dot_pos2 = dot_pos; dot_pos = pos; } } if (cv_strcasecmp(dot_pos, ".gz") && dot_pos2 != NULL) { dot_pos = dot_pos2; } fs->fmt = (cv_strcasecmp(dot_pos, ".xml") || cv_strcasecmp(dot_pos, ".xml.gz")) ? CV_STORAGE_FORMAT_XML : (cv_strcasecmp(dot_pos, ".json") || cv_strcasecmp(dot_pos, ".json.gz")) ? CV_STORAGE_FORMAT_JSON : CV_STORAGE_FORMAT_YAML ; } else if ( fmt != CV_STORAGE_FORMAT_AUTO ) { fs->fmt = fmt; } else { fs->fmt = CV_STORAGE_FORMAT_XML; } // we use factor=6 for XML (the longest characters (' and ") are encoded with 6 bytes (' and ") // and factor=4 for YAML ( as we use 4 bytes for non ASCII characters (e.g. \xAB)) int buf_size = CV_FS_MAX_LEN*(fs->fmt == CV_STORAGE_FORMAT_XML ? 6 : 4) + 1024; if (append) { fseek( fs->file, 0, SEEK_END ); if (ftell(fs->file) == 0) append = false; } fs->write_stack = cvCreateSeq( 0, sizeof(CvSeq), fs->fmt == CV_STORAGE_FORMAT_XML ? sizeof(CvXMLStackRecord) : sizeof(int), fs->memstorage ); fs->is_first = 1; fs->struct_indent = 0; fs->struct_flags = CV_NODE_EMPTY; fs->buffer_start = fs->buffer = (char*)cvAlloc( buf_size + 1024 ); fs->buffer_end = fs->buffer_start + buf_size; fs->base64_writer = 0; fs->is_default_using_base64 = write_base64; fs->state_of_writing_base64 = base64::fs::Uncertain; fs->is_write_struct_delayed = false; fs->delayed_struct_key = 0; fs->delayed_struct_flags = 0; fs->delayed_type_name = 0; if( fs->fmt == CV_STORAGE_FORMAT_XML ) { size_t file_size = fs->file ? (size_t)ftell( fs->file ) : (size_t)0; fs->strstorage = cvCreateChildMemStorage( fs->memstorage ); if( !append || file_size == 0 ) { if( encoding ) { if( strcmp( encoding, "UTF-16" ) == 0 || strcmp( encoding, "utf-16" ) == 0 || strcmp( encoding, "Utf-16" ) == 0 ) { cvReleaseFileStorage( &fs ); CV_Error( CV_StsBadArg, "UTF-16 XML encoding is not supported! Use 8-bit encoding\n"); } CV_Assert( strlen(encoding) < 1000 ); char buf[1100]; sprintf(buf, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", encoding); icvPuts( fs, buf ); } else icvPuts( fs, "<?xml version=\"1.0\"?>\n" ); icvPuts( fs, "<opencv_storage>\n" ); } else { int xml_buf_size = 1 << 10; char substr[] = "</opencv_storage>"; int last_occurence = -1; xml_buf_size = MIN(xml_buf_size, int(file_size)); fseek( fs->file, -xml_buf_size, SEEK_END ); char* xml_buf = (char*)cvAlloc( xml_buf_size+2 ); // find the last occurrence of </opencv_storage> for(;;) { int line_offset = (int)ftell( fs->file ); char* ptr0 = icvGets( fs, xml_buf, xml_buf_size ), *ptr; if( !ptr0 ) break; ptr = ptr0; for(;;) { ptr = strstr( ptr, substr ); if( !ptr ) break; last_occurence = line_offset + (int)(ptr - ptr0); ptr += strlen(substr); } } cvFree( &xml_buf ); if( last_occurence < 0 ) { cvReleaseFileStorage( &fs ); CV_Error( CV_StsError, "Could not find </opencv_storage> in the end of file.\n" ); } icvCloseFile( fs ); fs->file = fopen( fs->filename, "r+t" ); CV_Assert(fs->file); fseek( fs->file, last_occurence, SEEK_SET ); // replace the last "</opencv_storage>" with " <!-- resumed -->", which has the same length icvPuts( fs, " <!-- resumed -->" ); fseek( fs->file, 0, SEEK_END ); icvPuts( fs, "\n" ); } fs->start_write_struct = icvXMLStartWriteStruct; fs->end_write_struct = icvXMLEndWriteStruct; fs->write_int = icvXMLWriteInt; fs->write_real = icvXMLWriteReal; fs->write_string = icvXMLWriteString; fs->write_comment = icvXMLWriteComment; fs->start_next_stream = icvXMLStartNextStream; } else if( fs->fmt == CV_STORAGE_FORMAT_YAML ) { if( !append) icvPuts( fs, "%YAML:1.0\n---\n" ); else icvPuts( fs, "...\n---\n" ); fs->start_write_struct = icvYMLStartWriteStruct; fs->end_write_struct = icvYMLEndWriteStruct; fs->write_int = icvYMLWriteInt; fs->write_real = icvYMLWriteReal; fs->write_string = icvYMLWriteString; fs->write_comment = icvYMLWriteComment; fs->start_next_stream = icvYMLStartNextStream; } else { if( !append ) icvPuts( fs, "{\n" ); else { bool valid = false; long roffset = 0; for ( ; fseek( fs->file, roffset, SEEK_END ) == 0; roffset -= 1 ) { const char end_mark = '}'; if ( fgetc( fs->file ) == end_mark ) { fseek( fs->file, roffset, SEEK_END ); valid = true; break; } } if ( valid ) { icvCloseFile( fs ); fs->file = fopen( fs->filename, "r+t" ); CV_Assert(fs->file); fseek( fs->file, roffset, SEEK_END ); fputs( ",", fs->file ); } else { CV_Error( CV_StsError, "Could not find '}' in the end of file.\n" ); } } fs->struct_indent = 4; fs->start_write_struct = icvJSONStartWriteStruct; fs->end_write_struct = icvJSONEndWriteStruct; fs->write_int = icvJSONWriteInt; fs->write_real = icvJSONWriteReal; fs->write_string = icvJSONWriteString; fs->write_comment = icvJSONWriteComment; fs->start_next_stream = icvJSONStartNextStream; } } else { if( mem ) { fs->strbuf = filename; fs->strbufsize = fnamelen; } size_t buf_size = 1 << 20; const char* yaml_signature = "%YAML"; const char* json_signature = "{"; const char* xml_signature = "<?xml"; char buf[16]; icvGets( fs, buf, sizeof(buf)-2 ); char* bufPtr = cv_skip_BOM(buf); size_t bufOffset = bufPtr - buf; if(strncmp( bufPtr, yaml_signature, strlen(yaml_signature) ) == 0) fs->fmt = CV_STORAGE_FORMAT_YAML; else if(strncmp( bufPtr, json_signature, strlen(json_signature) ) == 0) fs->fmt = CV_STORAGE_FORMAT_JSON; else if(strncmp( bufPtr, xml_signature, strlen(xml_signature) ) == 0) fs->fmt = CV_STORAGE_FORMAT_XML; else if(fs->strbufsize == bufOffset) CV_Error(CV_BADARG_ERR, "Input file is empty"); else CV_Error(CV_BADARG_ERR, "Unsupported file storage format"); if( !isGZ ) { if( !mem ) { fseek( fs->file, 0, SEEK_END ); buf_size = ftell( fs->file ); } else buf_size = fs->strbufsize; buf_size = MIN( buf_size, (size_t)(1 << 20) ); buf_size = MAX( buf_size, (size_t)(CV_FS_MAX_LEN*2 + 1024) ); } icvRewind(fs); fs->strbufpos = bufOffset; fs->str_hash = cvCreateMap( 0, sizeof(CvStringHash), sizeof(CvStringHashNode), fs->memstorage, 256 ); fs->roots = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvFileNode), fs->memstorage ); fs->buffer = fs->buffer_start = (char*)cvAlloc( buf_size + 256 ); fs->buffer_end = fs->buffer_start + buf_size; fs->buffer[0] = '\n'; fs->buffer[1] = '\0'; //mode = cvGetErrMode(); //cvSetErrMode( CV_ErrModeSilent ); CV_TRY { switch (fs->fmt) { case CV_STORAGE_FORMAT_XML : { icvXMLParse ( fs ); break; } case CV_STORAGE_FORMAT_YAML: { icvYMLParse ( fs ); break; } case CV_STORAGE_FORMAT_JSON: { icvJSONParse( fs ); break; } default: break; } } CV_CATCH_ALL { fs->is_opened = true; cvReleaseFileStorage( &fs ); CV_RETHROW(); } //cvSetErrMode( mode ); // release resources that we do not need anymore cvFree( &fs->buffer_start ); fs->buffer = fs->buffer_end = 0; } fs->is_opened = true; _exit_: if( fs ) { if( cvGetErrStatus() < 0 || (!fs->file && !fs->gzfile && !fs->outbuf && !fs->strbuf) ) { cvReleaseFileStorage( &fs ); } else if( !fs->write_mode ) { icvCloseFile(fs); // we close the file since it's not needed anymore. But icvCloseFile() resets is_opened, // which may be misleading. Since we restore the value of is_opened. fs->is_opened = true; } } return fs; }