Перейти к содержимому
Compvision.ru

anton

Пользователи
  • Количество публикаций

    6
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные пользователем anton


  1. Здравствуйте.

    У меня небольшая проблема - создаю контур cvSeq, а потом рисую его с помощью cvDrawContours, но ничего программа не рисует.

    Видать проблема в том, что Вы указываете глубину прорисовки равной 0! - попробуйте cvDrawContours( src, seq, color, color,1,3,8); и всё зарисуется!


  2. Как выделить полученный контур в прямоугольник?

    Как вырезать полученный контур в ROI?

    НАШЁЛ ОТВЕТ:

    CvRect rect = cvBoundingRect(temp);
    
    cvRectangle(img, cvPoint(rect.x, rect.y), cvPoint(rect.x+rect.width,rect.y+rect.height),CV_RGB(0,255,0), 0);
    
    


  3. Вот, наваял! - берёт изображение с камеры - бинаризует, ищет прямоугольники... крайне нехорошо ищет, подтормаживает и утекает память!

    Кто знает, как бороться?

    #ifdef _CH_
    
    #pragma package <opencv>
    
    #endif
    
    
    #define CV_NO_BACKWARD_COMPATIBILITY
    
    
    #include "cv.h"
    
    #include "highgui.h"
    
    #include <time.h>
    
    #include <math.h>
    
    #include <ctype.h>
    
    #include <stdio.h>
    
    #include <string.h>
    
    
    int thresh = 50;
    
    IplImage* img = 0;
    
    IplImage* img0 = 0;
    
    CvMemStorage* storage = 0;
    
    const char* wndname = "Square Detection";
    
    
    
    double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 )
    
    {
    
        double dx1 = pt1->x - pt0->x;
    
        double dy1 = pt1->y - pt0->y;
    
        double dx2 = pt2->x - pt0->x;
    
        double dy2 = pt2->y - pt0->y;
    
        return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
    
    }
    
    
    CvSeq* findSquares4( IplImage* img, CvMemStorage* storage )
    
    {
    
        CvSeq* contours;
    
        int i, c, l, N = 11;
    
        CvSize sz = cvSize( img->width & -2, img->height & -2 );
    
        IplImage* timg = cvCloneImage( img ); // make a copy of input image
    
        IplImage* gray = cvCreateImage( sz, 8, 1 );
    
        IplImage* pyr = cvCreateImage( cvSize(sz.width/2, sz.height/2), 8, 3 );
    
        IplImage* tgray;
    
        CvSeq* result;
    
        double s, t;
    
        // create empty sequence that will contain points -
    
        // 4 points per square (the square's vertices)
    
        CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );
    
    
        // select the maximum ROI in the image
    
        // with the width and height divisible by 2
    
        cvSetImageROI( timg, cvRect( 0, 0, sz.width, sz.height ));
    
    
        // down-scale and upscale the image to filter out the noise
    
        cvPyrDown( timg, pyr, 7 );
    
        cvPyrUp( pyr, timg, 7 );
    
        tgray = cvCreateImage( sz, 8, 1 );
    
    
        // find squares in every color plane of the image
    
        for( c = 0; c < 3; c++ )
    
        {
    
            // extract the c-th color plane
    
            cvSetImageCOI( timg, c+1 );
    
            cvCopy( timg, tgray, 0 );
    
    
            // try several threshold levels
    
            for( l = 0; l < N; l++ )
    
            {
    
                // hack: use Canny instead of zero threshold level.
    
                // Canny helps to catch squares with gradient shading
    
                if( l == 0 )
    
                {
    
                    // apply Canny. Take the upper threshold from slider
    
                    // and set the lower to 0 (which forces edges merging)
    
                    cvCanny( tgray, gray, 0, thresh, 5 );
    
                    // dilate canny output to remove potential
    
                    // holes between edge segments
    
                    cvDilate( gray, gray, 0, 1 );
    
                }
    
                else
    
                {
    
                    // apply threshold if l!=0:
    
                    //     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
    
                    cvThreshold( tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY );
    
                }
    
    
                // find contours and store them all as a list
    
                cvFindContours( gray, storage, &contours, sizeof(CvContour),
    
                    CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );
    
    
                // test each contour
    
                while( contours )
    
                {
    
                    // approximate contour with accuracy proportional
    
                    // to the contour perimeter
    
                    result = cvApproxPoly( contours, sizeof(CvContour), storage,
    
                        CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 );
    
                    // square contours should have 4 vertices after approximation
    
                    // relatively large area (to filter out noisy contours)
    
                    // and be convex.
    
                    // Note: absolute value of an area is used because
    
                    // area may be positive or negative - in accordance with the
    
                    // contour orientation
    
                    if( result->total == 4 &&
    
                        cvContourArea(result,CV_WHOLE_SEQ,0) > 1000 &&
    
                        cvCheckContourConvexity(result) )
    
                    {
    
                        s = 0;
    
    
                        for( i = 0; i < 5; i++ )
    
                        {
    
                            // find minimum angle between joint
    
                            // edges (maximum of cosine)
    
                            if( i >= 2 )
    
                            {
    
                                t = fabs(angle(
    
                                (CvPoint*)cvGetSeqElem( result, i ),
    
                                (CvPoint*)cvGetSeqElem( result, i-2 ),
    
                                (CvPoint*)cvGetSeqElem( result, i-1 )));
    
                                s = s > t ? s : t;
    
                            }
    
                        }
    
    
                        // if cosines of all angles are small
    
                        // (all angles are ~90 degree) then write quandrange
    
                        // vertices to resultant sequence
    
                        if( s < 0.3 )
    
                            for( i = 0; i < 4; i++ )
    
                                cvSeqPush( squares,
    
                                    (CvPoint*)cvGetSeqElem( result, i ));
    
                    }
    
    
                    // take the next contour
    
                    contours = contours->h_next;
    
                }
    
            }
    
        }
    
    
        // release all the temporary images
    
        cvReleaseImage( &gray );
    
        cvReleaseImage( &pyr );
    
        cvReleaseImage( &tgray );
    
        cvReleaseImage( &timg );
    
    
        return squares;
    
    }
    
    
    void drawSquares( IplImage* img, CvSeq* squares )
    
    {
    
        CvSeqReader reader;
    
        IplImage* cpy = cvCloneImage( img );
    
        int i;
    
    
        // initialize reader of the sequence
    
        cvStartReadSeq( squares, &reader, 0 );
    
    
        // read 4 sequence elements at a time (all vertices of a square)
    
        for( i = 0; i < squares->total; i += 4 )
    
        {
    
            CvPoint pt[4], *rect = pt;
    
            int count = 4;
    
    
            // read 4 vertices
    
            CV_READ_SEQ_ELEM( pt[0], reader );
    
            CV_READ_SEQ_ELEM( pt[1], reader );
    
            CV_READ_SEQ_ELEM( pt[2], reader );
    
            CV_READ_SEQ_ELEM( pt[3], reader );
    
    
            // draw the square as a closed polyline
    
            cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 );
    
        }
    
    
        // show the resultant image
    
        cvShowImage( wndname, cpy );
    
        cvReleaseImage( &cpy );
    
    }
    
    
    
    
    
    
    IplImage* frame = 0;
    
    IplImage* imgForSquare = 0;
    
    IplImage* imgGray = 0;
    
    IplImage* imgBinary = 0;
    
    
    int main()
    
    {
    
    	storage = cvCreateMemStorage(0);
    
    
    	cvNamedWindow("original",CV_WINDOW_AUTOSIZE);
    
    	//cvNamedWindow("gray",CV_WINDOW_AUTOSIZE);
    
    	cvNamedWindow("binary",CV_WINDOW_AUTOSIZE);
    
    
    	CvCapture* capture = cvCreateCameraCapture(CV_CAP_ANY);
    
    
        while(1)
    
    	{
    
    		frame = cvQueryFrame( capture );
    
    
    		imgGray = cvCreateImage(cvGetSize(frame), frame->depth, 1);
    
    		cvConvertImage(frame, imgGray, CV_BGR2GRAY);	
    
    		imgBinary = cvCreateImage( cvGetSize(imgGray), IPL_DEPTH_8U, 1);
    
    		//cvAdaptiveThreshold(imgGray, imgBinary, 50, 250, CV_THRESH_BINARY);
    
    		cvAdaptiveThreshold(imgGray, imgBinary, 250, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 5, 3);
    
    
            if( !frame ) 
    
    		{
    
    			break;
    
            }
    
    
    		drawSquares( frame, findSquares4( frame, storage ) );
    
            cvShowImage( "original", frame );
    
            //cvShowImage( "gray", imgGray );
    
    		cvShowImage( "binary", imgBinary);
    
    
    		//cvReleaseImage(&frame); cvReleaseImage(&imgGray); cvReleaseImage(&imgBinary);
    
    //		drawSquares( imgGray, findSquares4( imgGray, storage ) );
    
    
            char c = cvWaitKey(33);
    
            if (c == 27) 
    
    		{ 
    
    			break;
    
            }
    
    	 }
    
    		cvClearMemStorage( storage );
    
            cvReleaseCapture( &capture );
    
    		///cvReleaseImage(&frame); cvReleaseImage(&imgGray); cvReleaseImage(&imgBinary);
    
    		cvDestroyAllWindows();
    
            return 0;
    
    }


  4. Уже успел встроить в код поиск прямоугольников из вышеупомянутого примера!... Работает конечно кривова-то: находит всё, что ни попадя... И бинаризация, кстати, хорошая идея для решения части из проблем.

    Пока решил попробовать, с определённой частотой, например 6 кадров в секунду, брать изображение и искать на нём прямоугольники... Тут отпадёт необходимость поиска движения! И если есть прямоугольники - то пытаться их распознавать, при этом их отфильтровав: Очевидно, что их верхняя и нижняя стороны примерно равны, тоже и с правой - левой, а боковинки будут меньше, чем верхушки.... Коечно в расчёт берётся то, что номер мы получаем без искажений.

    Маленькое уточнение, это учебный проект, в конце которого необходимо иметь рабочий прототип, который потом уже можно будет оптимизировать, так что пока - что грязь, искажения и прочие трудности в расчёт не беруться.

    Есть встроеные функции для бинаризации?

    Код после небольшой оптимизации выложу для желающих.


  5. Да, я читал форум и схожую тему, но ничего конечного не нашел, только наброски и предположения. В связи с этим создаю новую тему, результатами которой станет законченный код от получения картинки с камеры до текста с автомобильного номера.

    Суть идеи пока такая:

    1. Получаем картинку с камеры.

    2. Определяем наличие движения.

    3. Когда присутствует движение - выхватываем его и ищем на нём автомобильные номера.

    4. Вырезаем этот самый номер.

    5. Распознаем номер.

    Собственно, подскажите пожалуйста, где я прав или не прав, какие функции можно дёргать.... спасибо за любую помощь!

    Для начала есть (взято с примеров) - получение изображения с камеры и детектирование движения:

    #include "cv.h"
    
    #include "highgui.h"
    
    #include <time.h>
    
    #include <math.h>
    
    #include <ctype.h>
    
    #include <stdio.h>
    
    
    // various tracking parameters (in seconds)
    
    const double MHI_DURATION = 1;
    
    const double MAX_TIME_DELTA = 0.5;
    
    const double MIN_TIME_DELTA = 0.05;
    
    
    // number of cyclic frame buffer used for motion detection
    
    // (should, probably, depend on FPS)
    
    const int N = 5;
    
    
    // ring image buffer
    
    IplImage **buf = 0;
    
    int last = 0;
    
    
    // temporary images
    
    
    IplImage *mhi = 0; // MHI
    
    IplImage *orient = 0; // orientation
    
    IplImage *mask = 0; // valid orientation mask
    
    IplImage *segmask = 0; // motion segmentation map
    
    CvMemStorage* storage = 0; // temporary storage
    
    
    // parameters:
    
    //  img – input video frame
    
    //  dst – resultant motion picture
    
    //  args – optional parameters
    
    
    void  update_mhi( IplImage* img, IplImage* dst, int diff_threshold )
    
    {
    
        double timestamp = (double)clock()/CLOCKS_PER_SEC; // get current time in seconds
    
        CvSize size = cvSize(img->width,img->height); // get current frame size
    
        int i, idx1 = last, idx2;
    
        IplImage* silh;
    
        CvSeq* seq;
    
        CvRect comp_rect;
    
        double count;
    
        double angle;
    
    
        double magnitude;         
    
        CvScalar color;
    
    
    
        // allocate images at the beginning or
    
        // reallocate them if the frame size is changed
    
    
        if( !mhi || mhi->width != size.width || mhi->height != size.height ) 
    
    	{
    
            if( buf == 0 ) 
    
    		{
    
                buf = (IplImage**)malloc(N*sizeof(buf[0]));
    
                memset( buf, 0, N*sizeof(buf[0]));
    
    		}
    
    
            for( i = 0; i < N; i++ ) 
    
    		{
    
                cvReleaseImage( &buf[i] );
    
                buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 );
    
                cvZero( buf[i] );
    
            }
    
    
            cvReleaseImage( &mhi );
    
            cvReleaseImage( &orient );
    
            cvReleaseImage( &segmask );
    
            cvReleaseImage( &mask );
    
    
            mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 );
    
            cvZero( mhi ); // clear MHI at the beginning
    
            orient = cvCreateImage( size, IPL_DEPTH_32F, 1 );
    
            segmask = cvCreateImage( size, IPL_DEPTH_32F, 1 );
    
            mask = cvCreateImage( size, IPL_DEPTH_8U, 1 );
    
        }
    
    
    
    
        cvCvtColor( img, buf[last], CV_BGR2GRAY ); // convert frame to grayscale
    
    
        idx2 = (last + 1) % N; // index of (last – (N-1))th frame
    
        last = idx2;
    
        silh = buf[idx2];
    
        cvAbsDiff( buf[idx1], buf[idx2], silh ); // get difference between frames   
    
    
        cvThreshold( silh, silh, diff_threshold, 1, CV_THRESH_BINARY ); // and threshold it
    
        cvUpdateMotionHistory( silh, mhi, timestamp, MHI_DURATION ); // update MHI
    
    
        // convert MHI to blue 8u image
    
        cvCvtScale( mhi, mask, 255./MHI_DURATION,
    
    
                    (MHI_DURATION - timestamp)*255./MHI_DURATION );
    
        cvZero( dst );
    
        cvCvtPlaneToPix( mask, 0, 0, 0, dst ); 
    
    
        // calculate motion gradient orientation and valid orientation mask
    
        cvCalcMotionGradient( mhi, mask, orient, MAX_TIME_DELTA, MIN_TIME_DELTA, 3 );
    
    
        if( !storage )
    
            storage = cvCreateMemStorage(0);
    
        else
    
            cvClearMemStorage(storage);   
    
        // segment motion: get sequence of motion components
    
        // segmask is marked motion components map. It is not used further
    
        seq = cvSegmentMotion( mhi, segmask, storage, timestamp, MAX_TIME_DELTA ); 
    
    
        // iterate through the motion components,
    
        // One more iteration (i == -1) corresponds to the whole image (global motion)
    
        for( i = -1; i < seq->total; i++ ) 
    
    	{ 
    
            if( i < 0 ) 
    
    		{ // case of the whole image
    
                comp_rect = cvRect( 0, 0, size.width, size.height );
    
                color = CV_RGB(255,255,255);
    
                magnitude = 100;
    
            }
    
            else { // i-th motion component
    
                comp_rect = ((CvConnectedComp*)cvGetSeqElem( seq, i ))->rect;
    
                if( comp_rect.width + comp_rect.height < 100 ) // reject very small components
    
                    continue;
    
                color = CV_RGB(255,0,0);
    
                magnitude = 30;
    
            }
    
            // select componen ROI
    
            cvSetImageROI( silh, comp_rect );
    
            cvSetImageROI( mhi, comp_rect );
    
            cvSetImageROI( orient, comp_rect );
    
            cvSetImageROI( mask, comp_rect );
    
            // calculate orientation
    
            angle = cvCalcGlobalOrientation( orient, mask, mhi, timestamp, MHI_DURATION);
    
            angle = 360.0 - angle;  // adjust for images with top-left origin
    
            count = cvNorm( silh, 0, CV_L1, 0 ); // calculate number of points within silhouette ROI
    
            cvResetImageROI( mhi );
    
            cvResetImageROI( orient );
    
            cvResetImageROI( mask );
    
            cvResetImageROI( silh ); 
    
            // check for the case of little motion
    
            if( count < comp_rect.width*comp_rect.height * 0.05 )
    
                continue;
    
        }
    
    }
    
    
    
    
    
    
    int main(int argc, char** argv)
    
    {
    
        IplImage* motion = 0;
    
        CvCapture* capture = 0; 
    
    
        if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
    
            capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
    
        else if( argc == 2 )
    
            capture = cvCaptureFromFile( argv[1] );
    
        if( capture )
    
        {
    
            cvNamedWindow( "Motion", 1 );
    
    		cvNamedWindow( "Original", 2 );
    
            for(;
    
            {
    
                IplImage* image;
    
                if( !cvGrabFrame( capture ))
    
                    break;
    
                image = cvRetrieveFrame( capture );
    
                if( image )
    
                {
    
                    if( !motion )
    
                    {
    
                        motion = cvCreateImage( cvSize(image->width,image->height), 8, 3 );
    
                        cvZero( motion );
    
                        motion->origin = image->origin;
    
                    }
    
                }
    
    
                update_mhi( image, motion, 30 );
    
    			cvShowImage( "Original", image );
    
                cvShowImage( "Motion", motion );
    
    
    //			cvAbsDiff();
    
    
                if( cvWaitKey(10) >= 0 )
    
                    break;
    
            }
    
            cvReleaseCapture( &capture );
    
    		cvDestroyAllWindows();
    
        }
    
        return 0;
    
    }
    
    
    
    
    [/code]

    Вопрос первый, как по полученному движению - вырезать область движения (прямоугольную) из оригинального изображения?

    Вопрос второй, как искать номер? - Каскады Хаара, наверное слишком для этого?

×