diff --git a/SRC/Video.pro b/SRC/Video.pro index 03cf6da..311c5c8 100644 --- a/SRC/Video.pro +++ b/SRC/Video.pro @@ -3,18 +3,18 @@ # unix { # Path to global OpenCV installation directory - MY_OPENCV_DIR = /Users/dechamps/Documents/Codes/Cpp/Images/Libraries/opencv-4.3.0/install + MY_OPENCV_DIR = /Users/dechamps/Documents/Codes/Libraries/opencv-4.5.2/install # # If you don't have the OpenCV object detect library, comment the following 2 lines CONFIG += objdetect # (Macro) Path to the directory containing the cascade classifier files for face detection - DEFINES += OPENCV_HAARCASCADES_DIR=\\\"/Users/dechamps/Documents/Codes/Cpp/Images/Libraries/opencv-4.3.0/install/share/opencv4/haarcascades/\\\" + DEFINES += OPENCV_HAARCASCADES_DIR=\\\"/Users/dechamps/Documents/Codes/Libraries/opencv-4.5.2/install/share/opencv4/haarcascades/\\\" # # If you don't have the OpenCV extra module Face, comment the following line CONFIG += face # https://github.com/kurnianggoro/GSOC2017/blob/master/data/lbfmodel.yaml # (Macro) Path to the directory containing the facemark file "lbfmodel.yaml" - DEFINES += OPENCV_FACEMARK_DIR=\\\"/Users/dechamps/Documents/Codes/Cpp/Images/Libraries/opencv-4.3.0/install/share/opencv4/lbfmodel/\\\" + DEFINES += OPENCV_FACEMARK_DIR=\\\"/Users/dechamps/Documents/Codes/Libraries/opencv-4.5.2/install/share/opencv4/lbfmodel/\\\" # # If you don't have the ZBar library, comment the following line CONFIG += zbar @@ -24,33 +24,33 @@ unix { CONFIG += tesseract MY_TESSERACT_DIR = /Users/dechamps/Documents/Codes/Libraries/tesseract-4.1.1/install DEFINES += TESSERACT_DATA=\\\"/Users/dechamps/Documents/Codes/Libraries/tesseract-4.1.1/tessdata-master/\\\" - DEFINES += TESSERACT_DNN=\\\"/Users/dechamps/Documents/Codes/Cpp/Images/Libraries/opencv-4.3.0/install/share/opencv4/dnn/frozen_east_text_detection.pb\\\" + DEFINES += TESSERACT_DNN=\\\"/Users/dechamps/Documents/Codes/Libraries/opencv-4.5.2/install/share/opencv4/dnn/frozen_east_text_detection.pb\\\" # } win32 { # Path to global OpenCV installation directory - MY_OPENCV_DIR = D:\Libraries\opencv-4.3.0\build\install + MY_OPENCV_DIR = D:\Libraries\opencv-4.5.2\build\install # # If you don't have the OpenCV object detect library, comment the following 2 lines CONFIG += objdetect # (Macro) Path to the directory containing the cascade classifier files for face detection - DEFINES += OPENCV_HAARCASCADES_DIR=\\\"D:/Libraries/opencv-4.3.0/build/install/etc/haarcascades/\\\" + DEFINES += OPENCV_HAARCASCADES_DIR=\\\"D:/Libraries/opencv-4.5.2/build/install/etc/haarcascades/\\\" # # If you don't have the OpenCV extra module Face, comment the following line CONFIG += face # https://github.com/kurnianggoro/GSOC2017/blob/master/data/lbfmodel.yaml # (Macro) Path to the directory containing the facemark file "lbfmodel.yaml" - DEFINES += OPENCV_FACEMARK_DIR=\\\"D:/Libraries/opencv-4.3.0/build/install/etc/facemark/\\\" + DEFINES += OPENCV_FACEMARK_DIR=\\\"D:/Libraries/opencv-4.5.2/build/install/etc/facemark/\\\" # # If you don't have the ZBar library, comment the following line #CONFIG += zbar - #MY_ZBAR_DIR = + #MY_ZBAR_DIR = } # If you don't have the OpenCV stiching library, comment the following line CONFIG += stitching -# +# # If you don't have the OpenCV extra module Xphoto, comment the following line CONFIG += xphoto # @@ -73,6 +73,7 @@ TEMPLATE = app RESOURCES = images.qrc SOURCES = main.cpp \ + dialog_choose_camera.cpp \ myimage.cpp \ mainwindow.cpp \ dialog_blur.cpp \ @@ -84,11 +85,12 @@ SOURCES = main.cpp \ dialog_motion_detection.cpp \ secondarywindow.cpp \ dialog_photo.cpp \ - capturevideo.cpp + capturevideo.cpp stitching: SOURCES+=dialog_panorama.cpp tesseract: SOURCES += window_tesseract.cpp HEADERS += myimage.h \ + dialog_choose_camera.h \ mainwindow.h \ dialog_blur.h \ dialog_edge.h \ @@ -99,7 +101,7 @@ HEADERS += myimage.h \ dialog_motion_detection.h \ secondarywindow.h \ dialog_photo.h \ - capturevideo.h + capturevideo.h stitching: HEADERS += dialog_panorama.h tesseract: HEADERS += window_tesseract.h @@ -114,19 +116,19 @@ win32 { INCLUDEPATH += $${MY_OPENCV_DIR}\include # Required OpenCV libraries - LIBS = $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_imgcodecs430.lib \ - $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_core430.lib \ - $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_highgui430.lib \ - $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_videoio430.lib \ - $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_imgproc430.lib \ - $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_video430.lib \ - $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_photo430.lib - stitching: LIBS += $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_stitching430.lib - objdetect: LIBS += $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_objdetect430.lib - xphoto: LIBS += $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_xphoto430.lib - face: LIBS += $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_face430.lib + LIBS = $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_imgcodecs452.lib \ + $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_core452.lib \ + $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_highgui452.lib \ + $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_videoio452.lib \ + $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_imgproc452.lib \ + $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_video452.lib \ + $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_photo452.lib + stitching: LIBS += $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_stitching452.lib + objdetect: LIBS += $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_objdetect452.lib + xphoto: LIBS += $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_xphoto452.lib + face: LIBS += $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_face452.lib zbar: LIBS += $${MY_ZBAR_DIR}\lib\libzbar-0.lib - tesseract: LIBS += $${MY_TESSERACT_DIR}\lib\tesseract41.lib $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_dnn430.lib + tesseract: LIBS += $${MY_TESSERACT_DIR}\lib\tesseract41.lib $${MY_OPENCV_DIR}\x64\vc15\lib\opencv_dnn452.lib } unix { @@ -137,14 +139,14 @@ unix { # Compilator flags QMAKE_CXXFLAGS += -std=c++11 - + # Linker flags QMAKE_LFLAGS += -Wl,-rpath,$${MY_OPENCV_DIR}/lib # Include libraries from ZBar zbar: QMAKE_LFLAGS += -Wl,-rpath,$${MY_ZBAR_DIR}/lib # Include libraries from Tesseract zbar: QMAKE_LFLAGS += -Wl,-rpath,$${MY_TESSERACT_DIR}/lib - + # Required OpenCV libraries LIBS = -L$${MY_OPENCV_DIR}/lib LIBS += -lopencv_imgcodecs \ diff --git a/SRC/capturevideo.cpp b/SRC/capturevideo.cpp old mode 100644 new mode 100755 index c4f2695..4ff3dcd --- a/SRC/capturevideo.cpp +++ b/SRC/capturevideo.cpp @@ -2,7 +2,7 @@ * Copyright (C) 2019-2020 Xavier Dechamps * * PURPOSE - * Management of thread that takes care of capturing the camera, applying image + * Management of the Qthread that takes care of capturing the camera, applying image * processes on it and sending the treated image to the GUI MainWindow through signals * * Multithreaded implementation. The class captureVideo is solely dedicated to the treatment @@ -70,11 +70,12 @@ void captureVideo::setCamera(int camera){ /** * @brief captureVideo::openCamera + * @param integers width and height passed as parameters are set when the camera is opened * @return true if the camera is open. False if the camera ID is not set yet * * Open the camera anad initialize a new object of class MyImage */ -bool captureVideo::openCamera(){ +bool captureVideo::openCamera(int &width, int &height){ if (this->camID<0) { qDebug() << "captureVideo::openCamera - Cannot open camera"; return false; @@ -107,7 +108,16 @@ bool captureVideo::openCamera(){ return false; } - return this->capture.open(this->camID); + // Open the camera in OpenCV + bool test = this->capture.open(this->camID); + + // Get the dimensions of the camera frame + if (test) { + width = capture.get(cv::CAP_PROP_FRAME_WIDTH); + height = capture.get(cv::CAP_PROP_FRAME_HEIGHT); + } + + return test; } /** @@ -127,7 +137,7 @@ bool captureVideo::closeCamera() { } // Stop saving the movie - file_save_movie(false); + if (this->recording) file_save_movie(false); } return true; } @@ -155,8 +165,9 @@ bool captureVideo::getQRcodedata(std::string &qrdata, std::string &qrtype){ /** * @brief captureVideo::run * - * The core of the class captureVideo. It loops indefenitely to capture frames from the camera and - * to apply image processings on them. The treated images are sent to the GUI through signals. + * The core of the class captureVideo. It is called by mainWindow through this->worker->start() + * It loops indefenitely to capture frames from the camera and to apply image processings on them. + * The treated images are sent to the GUI through signals. */ void captureVideo::run() { this->running = true; @@ -166,13 +177,16 @@ void captureVideo::run() { int current_count = 0; bool first_time = true; + // While loop as long as running is true while (this->running) { if(cameraIsOpen()) { if (first_time){ timer.start(); first_time = false; } + // capture the camera frame and save it in imageMat this->capture >> imageMat; + // Stay in the while loop as long as the camera has not started while (imageMat.empty()) { this->capture >> imageMat; qDebug() << "captureVideo::run() : Empty image"; @@ -204,8 +218,7 @@ void captureVideo::run() { // emit this->setFPSrate(this->cameraFPS); } } - else - { + else { qDebug() << "captureVideo::run() : Camera is not open"; imageMat = cv::Mat::zeros(480, 640, CV_8UC1); myFrame->set_image_content(imageMat); @@ -213,10 +226,14 @@ void captureVideo::run() { } // Convert the opencv image to a QImage that will be displayed on the main window + // The first step is to convert the colour from BGR to RGB cv::cvtColor(imageMat, imageMat, cv::COLOR_BGR2RGB); + // Lock mechanism to ensure that the data is not overwritten by another thread this->data_lock->lock(); + // Create the QImage on the basis of the data from the OpenCV image this->myQimage = QImage(imageMat.data, imageMat.cols, imageMat.rows, imageMat.cols*3, QImage::Format_RGB888); + // Unlock the data this->data_lock->unlock(); // Launch the motion detection algorithm and send the result to the Qt manager @@ -259,7 +276,7 @@ void captureVideo::run() { * @param state: boolean the new status * * Change the status of the thread. If state=true, the thread is activated. - * If false, the while loop in run() is escaped and + * If false, the while loop in run() is terminated */ void captureVideo::setThreadStatus(bool state){ this->running = state; @@ -360,22 +377,6 @@ void captureVideo::toggleMotionDetection(bool state) { * Activate/desactivate the face detection algorithm. A background image is fetch from a local directory */ void captureVideo::toggleFaceDetection(bool state) { -/* - if (!this->myFrame->getFace_Status()) { - this->file_background = this->main_directory + "cartoon_background.jpg"; - bool test = this->myFrame->set_background_image(this->file_background); - while (!test){ - QString QfileNameLocal = QFileDialog::getOpenFileName(this->mainWindowParent, - tr("Select a background image"), - QString::fromStdString(this->main_directory), - tr("Images (*.bmp *.png *.jpg *.jpeg *.jpe *.jp2 *.webp *.pbm *.pgm *.ppm *.pnm *.pfm *.src *.tiff *.tif *.exr *.hdr *.pic)") ); - if ( ! QfileNameLocal.isEmpty() ) { - this->file_background = QfileNameLocal.toStdString() ; - test = this->myFrame->set_background_image(this->file_background); - } - } - } -*/ this->myFrame->toggleFace_Recon(state); if (state) emit changeInfo("Face detection activated"); @@ -773,7 +774,6 @@ bool captureVideo::setCascadeFile(){ } else return false; - } } else { @@ -843,11 +843,10 @@ bool captureVideo::setFacemarkFile(){ tr("Images (*.yaml)") ); if ( ! QfileNameLocal.isEmpty() ) { this->file_facemark = QfileNameLocal.toStdString() ; - testCascade = this->myFrame->set_Face_Cascade_Name(this->file_facemark); + testCascade = this->myFrame->set_Face_Facemark_Name(this->file_facemark); } else return false; - } } else { diff --git a/SRC/capturevideo.h b/SRC/capturevideo.h old mode 100644 new mode 100755 index 1cd0178..88b2b23 --- a/SRC/capturevideo.h +++ b/SRC/capturevideo.h @@ -30,7 +30,7 @@ class captureVideo : public QThread public: explicit captureVideo(QMainWindow *parent=nullptr,QMutex* data_lock=nullptr); void setCamera(int camID); - bool openCamera(); + bool openCamera(int &width, int &height); bool closeCamera(); bool cameraIsOpen(); void setThreadStatus(bool); @@ -115,7 +115,6 @@ public slots: void file_save_image(); - protected: void run() override; diff --git a/SRC/dialog_choose_camera.cpp b/SRC/dialog_choose_camera.cpp new file mode 100755 index 0000000..f5bf81d --- /dev/null +++ b/SRC/dialog_choose_camera.cpp @@ -0,0 +1,40 @@ +#include "dialog_choose_camera.h" + +Dialog_choose_camera::Dialog_choose_camera(QList cameras,QWidget *parent): QDialog(parent){ + this->list_cameras = cameras; + + QList< QPushButton* > PB; + QButtonGroup* group = new QButtonGroup(this); + QGridLayout *grid = new QGridLayout; + + QLabel* label = new QLabel("Please choose one of the following cameras:"); + grid->addWidget(label, 0, 0); + int i=0; + foreach (const QCameraInfo &cameraInfo, cameras) { + // Retrieve camera name + QString info = cameraInfo.description() ; + + // Create new button with textValue == camera name + QPushButton *button = new QPushButton(info, this); + + // Store button in an array + PB << button; + group->addButton(button,i); + grid->addWidget(button, i+1, 0); + i++; + } + + connect(group, SIGNAL(buttonClicked(int)), this, SLOT(onClick_Choose_Camera(int))); + + setLayout(grid); + setWindowTitle(tr("Camera control window")); +} + +void Dialog_choose_camera::onClick_Choose_Camera(int val) { + this->info_camera = this->list_cameras[val].description(); + emit this->Signal_camera_chosen( val ) ; +} + +QString Dialog_choose_camera::get_info_camera() { + return this->info_camera ; +} diff --git a/SRC/dialog_choose_camera.h b/SRC/dialog_choose_camera.h new file mode 100755 index 0000000..44768ef --- /dev/null +++ b/SRC/dialog_choose_camera.h @@ -0,0 +1,30 @@ +#ifndef DIALOG_CHOOSE_CAMERA_H +#define DIALOG_CHOOSE_CAMERA_H + +#include +#include +#include +#include +#include +#include +#include + +class Dialog_choose_camera : public QDialog +{ + Q_OBJECT +public: + explicit Dialog_choose_camera(QList cameras,QWidget *parent = nullptr); + QString get_info_camera() ; + +private: + QString info_camera ; + QList list_cameras ; + +private slots: + void onClick_Choose_Camera(int); + +signals: + void Signal_camera_chosen(int value); +}; + +#endif // DIALOG_CHOOSE_CAMERA_H diff --git a/SRC/main.cpp b/SRC/main.cpp old mode 100644 new mode 100755 index 6b79841..a4451d3 --- a/SRC/main.cpp +++ b/SRC/main.cpp @@ -91,9 +91,9 @@ Generating a Makefile through qmake has never been so easy. Simply modify the fi qmake.exe Video.pro to generate a Makefile (MinGW) or a project for VisualStudio. Don't forget to put the required *.dll libraries in the same directory as the executable before launching it! The list of required libraries is -- OpenCV: opencv_calib3d430.dll opencv_core430.dll opencv_face430.dll opencv_features430.dll opencv_flann430.dll opencv_imgcodecs430.dll opencv_imgproc430.dll opencv_objdetect430.dll opencv_photo430.dll opencv_stitching430.dll opencv_video430.dll opencv_video_ffmpeg430_64.dll opencv_videoio430.dll opencv_xphoto430.dll +- OpenCV: opencv_calib3d452.dll opencv_core452.dll opencv_face452.dll opencv_features452.dll opencv_flann452.dll opencv_imgcodecs452.dll opencv_imgproc452.dll opencv_objdetect452.dll opencv_photo452.dll opencv_stitching452.dll opencv_video452.dll opencv_video_ffmpeg452_64.dll opencv_videoio452.dll opencv_xphoto452.dll - ZBar: libzbar-0.dll -- Tesseract: tesseract41.dll opencv_dnn430.dll +- Tesseract: tesseract41.dll opencv_dnn452.dll - Qt5: Qt5Core.dll Qt5Gui.dll Qt5Multimedia.dll Qt5Network.dll Qt5Widgets.dll */ diff --git a/SRC/mainwindow.cpp b/SRC/mainwindow.cpp index 46a2f5e..6237aeb 100755 --- a/SRC/mainwindow.cpp +++ b/SRC/mainwindow.cpp @@ -24,50 +24,36 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), menu_Filters(nullptr), currentImage(nullptr) { - // Get the number and name of the available cameras, if more than 1 camera available - QList cameras = QCameraInfo::availableCameras(); - if (cameras.size() > 1) { - QString info = QString("Available Cameras: \n"); - foreach (const QCameraInfo &cameraInfo, cameras) { - info += " - " + cameraInfo.deviceName() + " : "; - info += cameraInfo.description() + " : " ; - } - QMessageBox::information(this, "Cameras", info); - } - - if (cameras.size() == 0) { - std::cerr << "Error: the number of available cameras is equal to zero"<data_lock = new QMutex(); this->worker = new captureVideo(this,this->data_lock); // Links signals from the video capturer to functions that update the display - connect(this->worker, &captureVideo::frameCaptured, this, &MainWindow::updateFrame ); - connect(this->worker, &captureVideo::changeInfo , this, &MainWindow::updateMainStatusLabel ); - connect(this->worker, &captureVideo::motionCaptured, this, &MainWindow::update_motion_window ); - connect(this->worker, &captureVideo::objectsCaptured, this, &MainWindow::update_objects_window ); - connect(this->worker, &captureVideo::histogramCaptured, this, &MainWindow::update_histogram_window ); + connect(worker, &captureVideo::frameCaptured, this, &MainWindow::updateFrame ); + connect(worker, &captureVideo::changeInfo , this, &MainWindow::updateMainStatusLabel ); + connect(worker, &captureVideo::motionCaptured, this, &MainWindow::update_motion_window ); + connect(worker, &captureVideo::objectsCaptured, this, &MainWindow::update_objects_window ); + connect(worker, &captureVideo::histogramCaptured, this, &MainWindow::update_histogram_window ); #ifdef withstitching - connect(this->worker, &captureVideo::panoramaCaptured, this, &MainWindow::update_panorama_window ); + connect(worker, &captureVideo::panoramaCaptured, this, &MainWindow::update_panorama_window ); #endif - // Initialization of the OpenCV thread - this->worker->setCamera(camID); - if (this->worker->openCamera()) - this->worker->start(); // Launch the new thread (call to run() in capturevideo) - else { - std::cerr << "Error: could not open the camera"< cameras = QCameraInfo::availableCameras(); + this->dialog_choose_camera = new Dialog_choose_camera(cameras,this); + connect(this->dialog_choose_camera,SIGNAL(Signal_camera_chosen(int)), this, SLOT(launchCamera(int)) ); + this->dialog_choose_camera->hide(); + if (cameras.size() > 1) { + this->dialog_choose_camera->show(); + } + else if (cameras.size() == 1) { + this->launchCamera(0); + } + else if (cameras.size() == 0) { + std::cerr << "Error: the number of available cameras is equal to zero"<resize(800, 600); // Setup menubar this->menu_File = menuBar()->addMenu(tr("&File")); @@ -96,25 +82,52 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), createToolBars(); createWindows(); -// this->setFixedSize(740, 480); - +// this->setFixedSize(740, 480); } /** * @brief MainWindow::~MainWindow * - * Kill the OpenCV thread when the main window is closed + * Stop the OpenCV thread when the main window is closed */ MainWindow::~MainWindow() { - // Delete the tesseract object + // Delete the tesseract object + delete this->window_tesseract; + + // Stop the thread + stopThread(); +} + +/** + * @brief MainWindow::closeEvent + * @param event + * + * Overwrite the closeEvent event handler in order to stop the OpenCV thread in a safe way + * when the close button is clicked + */ +void MainWindow::closeEvent(QCloseEvent *event) { + event->accept(); + + // Delete the tesseract object delete this->window_tesseract; - if (this->thread.isRunning() ) { - this->thread.quit(); // Nice way to tell the other thread to stop - if(!this->thread.wait(3000)) //Wait until it actually has terminated (max. 3 sec) + stopThread(); + qDebug() << "QCloseEvent : MainWindow closed"; +} + +/** + * @brief MainWindow::stopThread + * + * The code that actually stops the OpenCV thread + */ +void MainWindow::stopThread() { + this->worker->setThreadStatus(false); + if (this->worker->isRunning() ) { + this->worker->quit(); // Nice way to tell the other thread to stop + if(!this->worker->wait(3000)) //Wait until it actually has terminated (max. 3 sec) { - this->thread.terminate(); //Thread didn't exit in time, probably deadlocked, terminate it! - this->thread.wait(); //We have to wait again here! + this->worker->terminate(); //Thread didn't exit in time, probably deadlocked, terminate it! + this->worker->wait(); //We have to wait again here! } } } @@ -237,6 +250,11 @@ void MainWindow::createActions() { this->actionSaveImage = new QAction(tr("&Save"), this ); this->actionSaveImage->setToolTip(tr("Save the current image")); connect(this->actionSaveImage, SIGNAL(triggered()), this->worker, SLOT(file_save_image()) ); + + // File / Change camera + this->actionChangeCamera = new QAction(tr("Change camera"),this); + this->actionChangeCamera->setToolTip(tr("Change the camera that is used as an input")); + connect(this->actionChangeCamera, SIGNAL(triggered()), this, SLOT(showCameraSettings()) ); } /** @@ -247,6 +265,7 @@ void MainWindow::createActions() { void MainWindow::createToolBars() { this->menu_File->addAction(this->actionSaveImage); this->menu_File->addAction(this->actionRecord); + this->menu_File->addAction(this->actionChangeCamera); this->menu_Filters->addAction(this->actionColour_BW); this->menu_Filters->addAction(this->actionInverse); @@ -387,6 +406,40 @@ void MainWindow::createWindows(){ this->motion_detection_window_opened = false; } +/** + * @brief MainWindow::launchCamera + * @param camID: integer, ID of the camera + * + * Send the camera ID to the OpenCV thread and launch it + */ +void MainWindow::launchCamera(int camID){ + // Initialization of the OpenCV thread + this->worker->setCamera(camID); + this->worker->setThreadStatus(false); + int width,height ; // will hold the dimensions of the camera frame + if (this->worker->openCamera(width,height)) { + stopThread();// stop any running thread + this->worker->start(); // Launch the new thread (call to run() in capturevideo) + this->dialog_choose_camera->hide();// hide the dialog window + setWindowTitle(this->dialog_choose_camera->get_info_camera());//change the title of the main window to the camera name + this->resize(width+25, height+70); // add some space around the frame + } + else { + std::cerr << "Error: could not open the camera"<dialog_choose_camera->show(); +} + /** * @brief MainWindow::treat_Button_Blur * @param state: boolean diff --git a/SRC/mainwindow.h b/SRC/mainwindow.h index a6e8c26..f2af346 100755 --- a/SRC/mainwindow.h +++ b/SRC/mainwindow.h @@ -6,6 +6,7 @@ #define MAINWINDOW_H #include +#include #include #include #include @@ -23,6 +24,7 @@ #include #include +#include "dialog_choose_camera.h" #include "dialog_blur.h" #include "dialog_edge.h" #include "dialog_threshold.h" @@ -55,7 +57,7 @@ class MainWindow: public QMainWindow private: // For capture thread captureVideo *worker; - QThread thread; +// QThread thread; QMutex *data_lock; QImage myQimage; @@ -69,6 +71,7 @@ class MainWindow: public QMainWindow QStatusBar *mainStatusBar; QLabel *mainStatusLabel; + Dialog_choose_camera *dialog_choose_camera; Dialog_Blur *dialog_blur; Dialog_Edge *dialog_edge; Dialog_Threshold *dialog_threshold; @@ -122,6 +125,7 @@ class MainWindow: public QMainWindow QAction *actionPhoto; QAction *actionRecord; QAction *actionSaveImage; + QAction *actionChangeCamera; #ifdef withzbar QAction *actionQRcode; #endif @@ -135,14 +139,18 @@ class MainWindow: public QMainWindow void createActions(); void createToolBars(); void createWindows(); + void stopThread(); #ifdef withzbar void look_for_qrURL(); #endif protected: void paintEvent(QPaintEvent* ); + void closeEvent(QCloseEvent * event); private slots: + void launchCamera(int); + void showCameraSettings(); void updateFrame(QImage *image); void updateMainStatusLabel(QString); diff --git a/SRC/myimage.cpp b/SRC/myimage.cpp old mode 100644 new mode 100755 index dfb92db..f93bae9 --- a/SRC/myimage.cpp +++ b/SRC/myimage.cpp @@ -16,7 +16,7 @@ */ MyImage::MyImage() { - // Initializations for the all image operations + // Initializations for all the image operations #ifdef withobjdetect this->face_cascade_name = ""; #endif @@ -35,10 +35,10 @@ MyImage::MyImage() this->threshold_method = 1; this->threshold_value = 127; this->threshold_blocksize = 3; // for adaptive methods - this->threshold_type = 1; // 1 Normal, 0 inverted + this->threshold_type = 1; // [1] Normal, [0] inverted this->transformed = false; - this->transformation_method = 1; + this->transformation_method = 1; // [1] Rotation this->transf_rotation_value = 0; this->coloured = true; @@ -70,20 +70,6 @@ MyImage::MyImage() this->photo_method = 1; this->photo_sigmar = 0.15; this->photo_sigmas = 50; - - -// std::string model = TESSERACT_DNN; - cv::String model = TESSERACT_DNN ; -// cv::String model = "/Users/dechamps/Documents/Codes/Cpp/Images/Libraries/opencv-4.3.0/install/share/opencv4/dnn/frozen_east_text_detection.pb"; - // Load DNN network. - if (this->net.empty()) { - this->net = cv::dnn::readNet(model); - - std::cout << "MyImage::MyImage(): DNN model loaded" << std::endl; - -// this->net = cv::dnn::readNetFromTensorflow(model); - } - } /** @@ -173,7 +159,7 @@ bool MyImage::getFace_Status(){ * Receives the ornamental pictures from the database images.qrc, they have been loaded by the OpenCV thread */ void MyImage::loadOrnaments(std::vector Mat2receive){ - assert ( Mat2receive.size() >2 ); + assert ( Mat2receive.size() >3 ); this->ornament_glasses = Mat2receive.at(0) ; this->ornament_mustache = Mat2receive.at(1); this->ornament_mouse_nose = Mat2receive.at(2) ; @@ -519,14 +505,15 @@ cv::Mat& MyImage::get_image_content() { */ cv::Mat& MyImage::get_image_histogram() { std::vector bgr_planes; - cv::split( this->image, bgr_planes ); + cv::split( this->image, bgr_planes ); // split the BGR content of the image into different layers - int histSize = 256; + int histSize = 256; // max size for the range [0-255] float range[] = { 0, 256 } ; const float* histRange = { range }; bool uniform = true; bool accumulate = false; cv::Mat b_hist, g_hist, r_hist; + // Get the histogram for each of the BGR content cv::calcHist( &bgr_planes[0], 1, 0, cv::Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate ); cv::calcHist( &bgr_planes[1], 1, 0, cv::Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate ); cv::calcHist( &bgr_planes[2], 1, 0, cv::Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate ); @@ -542,12 +529,15 @@ cv::Mat& MyImage::get_image_histogram() { cv::normalize(r_hist, r_hist, 0, this->histogram.rows, cv::NORM_MINMAX, -1, cv::Mat() ); for( int i = 1; i < histSize; i++ ) { + // Plot the blue histogram cv::line( this->histogram, cv::Point( bin_w*(i-1), hist_h - cvRound(b_hist.at(i-1)) ) , cv::Point( bin_w*(i), hist_h - cvRound(b_hist.at(i)) ), cv::Scalar( 255, 0, 0), 2, 8, 0 ); + // Plot the green histogram cv::line( this->histogram, cv::Point( bin_w*(i-1), hist_h - cvRound(g_hist.at(i-1)) ) , cv::Point( bin_w*(i), hist_h - cvRound(g_hist.at(i)) ), cv::Scalar( 0, 255, 0), 2, 8, 0 ); + // Plot the red histogram cv::line( this->histogram, cv::Point( bin_w*(i-1), hist_h - cvRound(r_hist.at(i-1)) ) , cv::Point( bin_w*(i), hist_h - cvRound(r_hist.at(i)) ), cv::Scalar( 0, 0, 255), 2, 8, 0 ); @@ -883,7 +873,7 @@ void MyImage::detect_faces() { #ifdef withface // Detect the facial land marks std::vector< std::vector > shapes; - cv::Scalar color = cv::Scalar(0, 0, 255); // red +// cv::Scalar color = cv::Scalar(0, 0, 255); // red if (mark_detector->fit(this->image, faces, shapes)) { // draw facial land marks @@ -1382,7 +1372,6 @@ bool MyImage::getQRcodedata(std::string &data, std::string &type) { #endif - #ifdef withtesseract /** * @brief MyImage::detectTextAreas @@ -1407,8 +1396,7 @@ cv::Mat MyImage::textAreasDetect(std::vector &areas, bool detectAreas) cv::dnn::blobFromImage(frame, blob, 1.0, cv::Size(inputWidth, inputHeight), - cv::Scalar(123.68, 116.78, 103.94), true, false - ); + cv::Scalar(123.68, 116.78, 103.94), true, false); this->net.setInput(blob); this->net.forward(outs, layerNames);