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

Argon

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

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

  • Посещение

  • Days Won

    11

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


  1. Приветствую!

    начал изучать каскад Хаара и тут же напоролся на "грабли"

    вот немного переделанный код с этого форума(среда Qt), за инклюды не пинайте

    #include "mainwindow.h"
    
    #include "ui_mainwindow.h"
    
    #include<opencv/cv.h>
    
    #include<opencv/highgui.h>
    
    #include<QEvent>
    
    #include<QtCore>
    
    #include<QFileDialog>
    
    #include<QtGui>
    
    #include<QMessageBox>
    
    #include<QImage>
    
    #include<QTimer>
    
    #include<QWidget>
    
    #include<qwidget.h>
    
    #include<QString>
    
    #include<QSlider>
    
    #include<qslider.h>
    
    #include<QHeaderView>
    
    #include<qstyleoption.h>
    
    #include<qabstractitemview.h>
    
    #include<QSpinBox>
    
    #include<qspinbox.h>
    
    #include<QTime>
    
    #include<QTimeEdit>
    
    #include<QSettings>
    
    #include "opencv2/core/core.hpp"
    
    #include "opencv2/highgui/highgui.hpp"
    
    #include "opencv2/imgproc/imgproc.hpp"
    
    #include "opencv2/imgproc/imgproc.hpp"
    
    #include "opencv2/objdetect/objdetect.hpp"
    
    
    using namespace std;
    
    using namespace cv;
    
    
    
    
    MainWindow::MainWindow(QWidget *parent) :
    
        QMainWindow(parent),
    
        ui(new Ui::MainWindow)
    
    {
    
        ui->setupUi(this);
    
    
        timerStartStop = new QTimer(this);
    
        connect(timerStartStop, SIGNAL(timeout()), this, SLOT(StartStopVideoFromWebcam()));
    
        timerStartStop->stop();
    
    
        // Указатель на каскад Хаара
    
        this->cascade = 0;
    
    
        camWebcam.open(0);
    
    
        if(camWebcam.isOpened() == false)
    
        {
    
            ui->statusBar->showMessage("Невозможно определить камеру, проверьте подключение.");
    
            QMessageBox::information(this, "Внимание", "Камера не обнаружена, проверьте подключение");
    
        }
    
        else
    
        {
    
            ui->statusBar->showMessage("Подключение прошло успешно, камера готова к работе.");
    
        }
    
    
        camWebcam.release();
    
    
        // Создаем строку, содержащую точное имя каскад
    
        const char* cascade_name ="C://haarcascade_frontalface_alt.xml";
    
        // Загружаем HaarClassifierCascade
    
        cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
    
    }
    
    
    MainWindow::~MainWindow()
    
    {
    
        delete ui;
    
    }
    
    
    void MainWindow::ShawImage(cv::Mat img) //собственно и сама функция поиска лица
    
    {
    
        CvMemStorage* storage = 0;
    
        int scale = 1;
    
        // Создаем две точки, представляющие местоположение лица
    
        CvPoint pt1, pt2;
    
        int i;
    
    
        // Выделим память для хранения
    
        storage = cvCreateMemStorage(0);
    
    
        // Очистим хранилище памяти, который использовался до
    
        cvClearMemStorage( storage );
    
    
        // Найдем загрузился каскад, чтобы найти лица. Если да, то:
    
        if( cascade )
    
        {
    
            CvSize min = cvSize(40,40);
    
            CvSeq* faces = cvHaarDetectObjects(&img, cascade, storage, 1.1, 2, CV_HAAR_DO_CANNY_PRUNING, min); //в отладчике на этой строке валится программа img = cv::Mat
    
    
            for( i = 0; i < (faces ? faces->total : 0); i++ )
    
            {
    
                // Создаем новый прямоугольник для рисования лица
    
                CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
    
    
                // Найдем размеры лица, и масштабы его, если необходимо,
    
                pt1.x = r->x*scale;
    
                pt2.x = (r->x+r->width)*scale;
    
                pt1.y = r->y*scale;
    
                pt2.y = (r->y+r->height)*scale;
    
    
                // Нарисуем прямоугольник, в входное изображение
    
    
                cv::rectangle( img, pt1, pt2, CV_RGB(255,0,0), 3, 8, 0 );
    
            }
    
        }
    
        cv::cvtColor(img, img, CV_BGR2RGB);
    
        QImage imgshow((uchar*)img.data, img.cols, img.rows, img.step, QImage::Format_RGB888);
    
        ui->lblImage->setPixmap(QPixmap::fromImage(imgshow));
    
    }
    
    
    void MainWindow::StartStopVideoFromWebcam() //таймер обработки кадров с вэб камеры
    
    {
    
        camWebcam.open(0);
    
        camWebcam.read(frame);
    
    
        if (frame.empty() == true)
    
        {
    
            ui->statusBar->showMessage("Ошибка при захвате видео!");
    
            return;
    
        }
    
    
        ShawImage(frame);
    
    }
    
    void MainWindow::on_pushButton_3_clicked() //кнопка выхода
    
    {
    
        close();
    
    }
    
    
    void MainWindow::on_pushButton_clicked() //кнопка запуска трэкинга
    
    {
    
        timerStartStop->start(33);
    
    }
    
    
    void MainWindow::on_pushButton_2_clicked() //кнопка остановки таймера
    
    {
    
        timerStartStop->stop();
    
    }
    программа валится на этой строке
    CvSeq* faces = cvHaarDetectObjects(&img, cascade, storage, 1.1, 2, CV_HAAR_DO_CANNY_PRUNING, min);

    ошибка следующая: OpenCV Error: Bad flag (parameter or structure field) (Unrecognized or unsupported array type) in cvGetMat, file C:\opencv\modules\core\src\array.cpp, line 2482

    что я делаю не так?


  2. из описания функции очевидно, что она возвращает число. Разумно предположить, что это число что-то означает. Скорее всего оно сигнализирует об успешной или нет записи кадра. Что в принципе подтверждается просмотром исходников. Так какое значение это числа?

    Попробуй тогда использовать различные, установленные в твоей системе кодеки, а не только xvid.

    Ну и третье.

    У тебя есть opencv_ffmpeg*.dll? Если есть, то удали/перемести/переименуй её. Помогло?

    возвращает чило 0....

    установил все кодаки...

    opencv_ffmpeg*.dll удалить нельзя т.к. он используется при обработку видео файлов... а как только скрываю его, то вся программа перестает работать...

    проблема актуальна....


  3. 1. Что возвращает cvWriteFrame?

    2. Ты закрываешь файл после записи?

    1) что то я не совсем понимаю что долна возвращать эта фукция... ...вроде она должна только инициировать запись кадра в файл...

    2) пробовал закрывать, не помогло...

    зы: пробую просматривать записываемые кадры, все гуд на просмотре, а записываться не хотят...


  4. отладчик выдает следующее:

    writer	 @0x1d051aa0	
    
    		[CvVideoWriter]		
    
    			[vptr]	0x9afe28	
    
    			[0]	0x7aaf4c <CvVideoWriter_FFMPEG_proxy::~CvVideoWriter_FFMPEG_proxy()>	
    
    			[1]	0x7aaf28 <CvVideoWriter_FFMPEG_proxy::~CvVideoWriter_FFMPEG_proxy()>	
    
    			[2]	0x7aaa74 <CvVideoWriter_FFMPEG_proxy::writeFrame(_IplImage const*)>	
    
    			[3]	0x7aadfc <CvVideoWriter_FFMPEG_proxy::open(char const*, int, double, CvSize, bool)>	
    
    			[4]	0x7aae9c <CvVideoWriter_FFMPEG_proxy::close()>	
    
    			ffmpegWriter	0x1d0bb6a8	void *


  5. Как это делается я знаю(благо в интернете полно информации), но вот сам вопрос таков: почему не формирует выходной файл?

    задаю значения переменым

        fps = 16;
    
        sizeForFile = cvSize(640,480);
    
        cFileForWriteInFile = "MouseTrecking.avi";
    
        writer = cvCreateVideoWriter(cFileForWriteInFile, CV_FOURCC('X','V','I','D'), fps, sizeForFile, 0);
    хочу провеести запись в файл:
     IplImage imgforwrite = matOriginal;
    
            IplImage* temp = &imgforwrite;
    
    
            cvWriteFrame(writer, temp);

    в итоге у меня получается только пустой файл с названием ...

    ЗЫ: думал что некорректно конвертируеся файл, но все ок...

    ЗЫЫ: на кодак не ругается, все находит...


  6. Мда. Современные отладчиики понимают скрипты, умеют многопоточную отладку, стек вызовов, условные брейк поинты, откатываться назад по времени, позволяют просматривать любой адрес памяти и регистры, отображать значения любых переменных,... А ты всего лишь смог найти строку, в которой падает программа?!! Чувак...

    неправдали я охеренен :), буду разбираться дальше...

    • Like 1

  7. А воспользоваться отладчиком и узнать, в чём конкретно проблема не вариант?

    чувак... отладчиком я и нашел где ошибка выскакивает, точнее после каких действий...

    2Smorodov

    у меня 32-х разрядный Qt и библиотеки opencv сформированные в 32-х разрядной ОС

    но все равно поробую еще раз перенастроить


  8. Надо перестроить еще и QT.

    что значит перестроить? я на вторую "машину" отдельно устанавливал QT и переформировывал библиотеки, и естественно сделал подключение к новым библиокекам(каторые формировал на 32-х битной машине)


  9. Доброго времени суток!

    Изначально писал программу на 64-ох битной системе, затем перенес ее на 32-х битную, переформировал все библиотеки программой cmake, и в итоге имею следующее

    на 64 битной системе код обрабатывается правильно:

    void MouseDetected::on_btnLoadFromFile_clicked()
    
    {
    
        QString qVideofileName = QFileDialog::getOpenFileName(this,
    
                                                              tr("Выберите видео файл"), "",
    
                                                              tr("Video file (*.avi);;All Files (*)"));
    
        if(qVideofileName.isEmpty() == false)
    
        {
    
            ui->txtFileOpen->setText(qVideofileName);
    
            capture = cvCreateFileCapture(qVideofileName.toStdString().c_str());
    
            framesCount = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);
    
            iPositin = (int)framesCount;
    
            frame = cvQueryFrame(capture);
    
            dPosSlid = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES);
    
            iFirstPosition = (int)dPosSlid;
    
            ui->horizontalSlider->setMaximum(iPositin);
    
            ui->horizontalSlider->setRange(iFirstPosition, iPositin);
    
            ui->progressBar->setMaximum(iPositin);
    
            ui->nomKadr->setMaximum(iPositin);
    
            storage = 0;
    
            //загружаем фоновое изображение(временно, переделать для кнопки(изменить) и добавить просмотр из формы)
    
    
            matFon = cvLoadImage("D:\\myProjekt\\MouseTreking\\fon\\fon.png");
    
            cv::cvtColor(matFon, matFon, CV_RGB2GRAY);
    
            cv::GaussianBlur(matFon, matFon, cv::Size(3,3), -1);
    
    
            cv::cvtColor(frame, frame, CV_BGR2RGB);
    
    
            QImage gimgOriginal((uchar*)frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888);
    
            ui->IplOutputImage->setPixmap(QPixmap::fromImage(gimgOriginal));
    
    
    
        }
    
    }
    а на 32-х ошибка возникает тут
    frame = cvQueryFrame(capture);
    
    
    ......
    
    
     cv::cvtColor(frame, frame, CV_BGR2RGB);
    
    
    

    т.е. программа не может разложить файл на кадры... в чем может быть проблема?


  10. Еще вопрос:

    Есть QTime t_TimeObjA в который я записываю время пребывания объекта в определенной области, но как тольок хочу наложить это время на изображение, то выбрасывает ошибку...

    накладываю так

    cv::putText(matOriginal, "Object in ROI A: " + t_TimeObjA.toString() ,cv::Point(10,25),CV_FONT_HERSHEY_COMPLEX, 0.4f, cv::Scalar(255,255,255),1,CV_AA);
    но если использую
    QMessagebox::information(this, "1", t_TimeObjA.toString())

    то выводит сообщение с временем как нужно (00:00:00)...


  11. Спасибо!

    Еще маленьки вопросик:

    есть переменные в которых храню координады точек прямоугольника(левая верхняя, нижняя правая)

    к примеру(int)

    ixAUp = 100;
    
         iyAUp = 100;
    
         ixADown = 200;
    
         iyADown = 300;
    а вот когда начинаю их записывать в спинбоксы, то тут хз что происходит: записывается только первая переменная в первый спинбокс... ...остальные игнорируются записываю так:
    ui->spinXup->setValue(ixAUp);
    
            ui->spinYup->valueChanged(iyAUp);
    
            ui->spinXdown->setValue(ixADown);
    
            ui->spinYdown->setValue(iyADown);

    еще нюанс: когда закоменчу первую строку заполнения спинбоксов, то будет заполнять только второй спинбокс....

    помогите разобраться с бональным кодом....


  12. то, только я не совсем понимаю как это у Вас работает.

    а точнее: как вы сохраняете по клику мыши координаты точки?

    каким параметром передаете на рисование?

    как делаете только одну прорисовку области до отжатия левой кнопки мыши?

    и почему везде ссылки на класс annotation?

    подробнее опишите процеесс сохранения ROI в переменную(cv::Rect)


  13. еще вопрос

    решил попробовать дать пользователю выделять область ROI самому, но у меня не получается выделить область....

    делаю сл. образом:

    void drawTarget(cv::Mat img, int xA, int yA, cv::Rect poli1)
    
    {
    
        cv::rectangle(img, cv::Point(poli1.x, poli1.y), cv::Point(xA, yA),cv::Scalar(250,0,0),1,8);
    
    }
    
    
    void MouseDetected::myMouseCallback( int event, int xA, int yA, int flags, void* param )
    
    {
    
    
        cv::Mat matImg(*(cv::Mat*)param);
    
        cv::Rect pol1;
    
    
            switch( event ){
    
    
                    case CV_EVENT_LBUTTONDOWN:
    
            {
    
                            pol1.width = xA;
    
                            pol1.height = yA;
    
    
                            cv::circle(matImg,cv::Point(xA, yA),1,cv::Scalar(250,0,0),3,8);
    
            }
    
                            break;
    
    
                    case CV_EVENT_LBUTTONUP:
    
    
                            break;
    
    
                    case (CV_EVENT_LBUTTONDOWN && CV_EVENT_MOUSEMOVE):
    
    
                            {
    
                                 if ((pol1.x != NULL) || (pol1.y != NULL) )
    
                                 {
    
                                       drawTarget(matImg, xA ,yA, pol1);
    
                                 }
    
                            }
    
                            break;
    
            }
    
    }

    но ничего не происходит... ставится только точка нажатия курсора и все.... подскажите что не так???

    ЗЫ: чет я совсем запутался с cv::Point и cv::Rect....


  14. Все тот же синтаксис....

    для простоты и удобства при ранесении ROI вызываю дополнительное окно:

    void MouseDetected::on_pushButton_2_clicked()
    
    {
    
        cv::namedWindow("ROI", 1);
    
        cv::imshow("ROI", frame);
    
    
        //вызываю обработчик нажатия книпки мыши frame беру как кадр из видео файла
    
        cv::setMouseCallback("ROI", myMouseCallback, (void*) frame);
    
    
    }
    пишу обработчик для функции myMouseCallback
    void myMouseCallback( int event, int xA, int yA, int flags, void* param )
    
    {
    
            IplImage* img = (IplImage*) param;
    
            cv::Mat matImg(img);
    
    
            switch( event ){
    
                    case CV_EVENT_MOUSEMOVE:
    
                            break;
    
    
                    case CV_EVENT_LBUTTONDOWN:
    
    
                            drawTarget(img, xA, yA, 10);
    
                            break;
    
    
                    case CV_EVENT_LBUTTONUP:
    
                            break;
    
            }
    
    }
    и описываю drawTarget
    void drawTarget(cv::Mat img, int xA, int yA, int radius)
    
    {
    
    
            cv::circle(img,cv::Point(xA, yA),radius,cv::Scalar(250,0,0),1,8);
    
            cv::line(img, cv::Point(xA-radius/2, yA-radius/2), cv::Point(xA+radius/2, yA+radius/2),cv::Scalar(250,0,0),1,8);
    
            cv::line(img, cv::Point(xA-radius/2, yA+radius/2), cv::Point(xA+radius/2, yA-radius/2),cv::Scalar(250,0,0),1,8);
    
    }

    в итоге ругается на строку

    cv::setMouseCallback("ROI", myMouseCallback, (void*) frame);

    488: ошибка: cannot convert 'MouseDetected::myMouseCallback' from type 'void (MouseDetected::)/>()' to type 'cv::MouseCallback {aka void (*)(int, int, int, int, void*)}'

    гугл особо ничем не помог. В чем может быть проблема?


  15. спасибо! помогло и заработало!

    Только как найти центр выделенного объекта вообще догнать немогу... ... сказывается тяжелая неделя....

    Приведите небольшой пример установки средней точки в объекте после обработки изображения cv::drawContours


  16. используя поиск элементов получаю из кода:

    int idx = 0;
    
        for( ; idx >= 0; idx = v4i[idx][0] )
    
        {
    
            cv::Scalar color( 0, 0, 255 );
    
            for(int i = 0; i < vP.size(); i++)
    
            {
    
                cv::Rect rect = cv::boundingRect(vP[i]);
    
                if((rect.x >= x) && (rect.y <= y + height) && (cv::contourArea(vP[i]) > 100))
    
                {
    
                    cv::drawContours( matOriginal, vP, i, color, CV_FILLED, 8, v4i);
    
                }
    
            }
    
        }
    результат http://floomby.ru/s1/mavejr весь объект закрашен, а нужно только очертить контур... что не так делаю?? второй вопрос: как можно ускорить обработку из такого кода
    void MouseDetected::StartVideoFile(){
    
    
        frame = cvQueryFrame(capture);
    
    
        if (frame.empty() == true)
    
        {
    
            return;
    
            QMessageBox::information(this, "Сообщение программы", "Видео " + qVideofileName + "обработано успешно.");
    
            ui->IplOutputImage->setPixmap(QPixmap::fromImage(qimgNoFoto));
    
    
        }
    
        // для визуализации происходящего
    
        dPosSlid = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES);
    
        int iFirstPosition = (int)dPosSlid;
    
        ui->lcdNumber->display(iFirstPosition);
    
        ui->horizontalSlider->setValue(iFirstPosition);
    
    
        /////////---------Обработка кадра
    
    
        matOriginalGray = frame;
    
        matOriginal = frame;
    
    
        cv::cvtColor(matOriginalGray, matOriginalGray, CV_RGB2GRAY);
    
        cv::GaussianBlur(matOriginalGray, matOriginalGray, cv::Size(3,3), 1);
    
        cv::absdiff(matOriginalGray, matFon, matItog);
    
        cv::GaussianBlur(matItog, matItog, cv::Size(9,9), 1.5);
    
    
        cv::threshold(matItog, matItog, hSlider3, hSlider2, CV_THRESH_BINARY);
    
        cv::GaussianBlur(matItog, matItog, cv::Size(3,3), 1);
    
    
        cv::Canny(matItog, matItog, 50, dcanny, 3);
    
    
        cv::findContours(matItog, vP, v4i,CV_RETR_CCOMP , CV_CHAIN_APPROX_NONE);
    
    
        //Обработка контролов
    
    
        int idx = 0;
    
        for( ; idx >= 0; idx = v4i[idx][0] )
    
        {
    
            cv::Scalar color( 0, 0, 255 );
    
            for(int i = 0; i < vP.size(); i++)
    
            {
    
                cv::Rect rect = cv::boundingRect(vP[i]);
    
                if((rect.x >= x) && (rect.y <= y + height) && (cv::contourArea(vP[i]) > 100))
    
                {
    
                    cv::drawContours( matOriginal, vP, i, color, CV_FILLED, 8, v4i);
    
                }
    
            }
    
        }
    
        cv::cvtColor(matOriginal, matOriginal, CV_BGR2RGB);
    
        QImage gimgOriginal((uchar*)matOriginal.data ,matOriginal.cols, matOriginal.rows, matOriginal.step, QImage::Format_RGB888);
    
        ui->IplOutputImage->setPixmap(QPixmap::fromImage(gimgOriginal));
    
    }


  17. спасибо, как определять все контуры разобрался, а как выделить среди них только один, который должен находиться в определенных координатах на изображении???

    вопрос больше по синтаксису чем по реализации....

    на С делал так, 1) задавал интересующую меня область ROI

    
    int x = 172;
    
    int y  = 42;
    
    int width = 379;
    
    int height = 365;
    
    int add = 1;
    2) после преобразований над изображением делеа следующее, т.е. обрезал границы и выделяо объект:
    
    cvFindContours(itog, storage, &contours);
    
    for( ; contours!=0; contours->h_next)
    
    {
    
    CvRect* rect = cvBoundingRect(contours, 0);
    
    			if (((rect.x >= x) && (rect.y <= y + height)) && ((rect.x >= rect.x + 5) || (rect.y <= rect.y + 5)))
    
    			{
    
    				if ((rect.x + 25 <= rect.x + rect.width )|| (rect.y + 25 <= rect.y + rect.height))
    
    				{
    
    					cvRectangle(image, cvPoint(rect.x, rect.y), cvPoint(rect.x + rect.width, rect.y +rect.height), cvScalar(0,0,255,0), 1, 8, 0);
    
    				}
    
    			}
    
    		}
    
    
    

    как мне на Qt проделать такое же выделение???

    и еще, так и не понял как находить центр выделенного контура после cv::drawContours.... если не сложно, приведите простой пример....

×