Ask Your Question

htmlboss's profile - activity

2016-06-08 13:17:48 -0600 received badge  Editor (source)
2016-06-08 13:17:13 -0600 asked a question Yet Another Assertion failed (scn == 3 || scn == 4)

I am aware that this usually means I have an empty matrix, but when I output mat.rows and mat.cols, I get the expected image dimensions (200x200). I originally had the cv::imread() function but I replaced it with QImage, with still no effect. Bad file paths have also been tested for. Relevant code:

void FaceDetector::loadCSV(const cv::String& filePath, std::vector<cv::Mat>& images, std::vector<int>& labels, char separator) {

    std::ifstream file(filePath.c_str(), std::ifstream::in);
    if(!file) {
        qDebug() << "Error: " << std::strerror(errno);
    }

    std::string line, path, classlabel;
    while(std::getline(file, line)) {

        std::stringstream liness(line);
        std::getline(liness, path, separator);
        std::getline(liness, classlabel);

        if(!path.empty() && !classlabel.empty()) {
            QImage img(QString::fromStdString(path));
            cv::Mat m = qImagetoMat(img);

            if (m.data == NULL | m.empty()) {
                qDebug() << "Empty matrix";
            }
            qDebug() << m.cols << m.rows;

            cv::cvtColor(m, m, CV_RGB2GRAY);

            images.push_back(m);
            labels.push_back(atoi(classlabel.c_str()));
        }
    }
    qDebug() << "loaded csv";
}

    //Convert QImage to cv::Mat (probably the trouble area?)
    cv::Mat FaceDetector::qImagetoMat(QImage &img, int format) {

    return cv::Mat(img.height(), img.width(), format, img.bits(), img.bytesPerLine());
}
2016-06-08 13:04:56 -0600 received badge  Scholar (source)
2016-06-08 13:04:52 -0600 answered a question QT 'emit': undeclared identifier error after <face.hpp> included

I turns out I needed to replace emit keyword with the actual macro Q_EMIT.

2016-06-06 17:01:27 -0600 received badge  Supporter (source)
2016-06-05 15:50:12 -0600 asked a question QT 'emit': undeclared identifier error after <face.hpp> included

I'm using OpenCV with QT and trying to implement facial recognition but as soon as I include <face.hpp> from the "contrib" branch, QT complains about error: C2065: 'emit': undeclared identifier. I've tried including "qobjectdefs.h" and #define emit at the top of the appropriate header file, but it does not work. Code:

Header

    #ifndef FACEDETECTOR_H
    #define FACEDETECTOR_H

    #include <QObject>
    #include <QBasicTimer>
    #include <QTimerEvent>
    #include <QDir>
    #include <QDebug>
    #include <QImage>
    #include <QString>
    #include <QResource>
    #include <QVector>
//This causes the error as soon as I uncomment it
    #include <opencv2/face.hpp>
    #include <opencv2/opencv.hpp>

    class FaceDetector : public QObject {
        Q_OBJECT

    public:
        FaceDetector(QObject *parent=0) : QObject(parent), processAll_(true) {}
        void setProcessAll(bool all);
        ~FaceDetector();

    signals:
        void image_signal(const QImage&);

    public slots:
        void processFrame(const cv::Mat& frame);
        void facecascade_filename(QString filename);

    private:
        QString facecascade_filename_;
        QString eyecascade_filename_;
        QBasicTimer timer_;
        QVector<cv::Mat> m_CSVimages;
        QVector<int> m_CSVlabels;
        cv::Mat frame_;
        bool processAll_;
        cv::CascadeClassifier faceCascade;
        cv::CascadeClassifier eyeCascade;

//I need face.hpp for this:
        //cv::Ptr<cv::face::FaceRecognizer> m_faceModel;

        void process(cv::Mat frame);
        void loadFiles(const cv::String& faceCascadeFilename, const cv::String& eyesCascadeFilename);
        static void loadCSV(const cv::String& filePath, QVector<cv::Mat>& images, QVector<int>& labels, char separator = ';');
        void queue(const cv::Mat & frame);
        void timerEvent(QTimerEvent* ev);
        static void matDeleter(void* mat);
    };

    #endif // FACEDETECTOR_H

Implementation Other functions omitted for brevity

    #include "faceDetector.h"

    void FaceDetector::process(cv::Mat frame) {
        cv::Mat grey_image;
        cv::cvtColor(frame, grey_image, CV_BGR2GRAY);
        cv::equalizeHist(grey_image, grey_image);


        std::vector<cv::Rect> faces;
        // Calculate the camera size and set the size to 1/8 of screen height
        faceCascade.detectMultiScale(grey_image, faces, 1.1, 8,  0|CV_HAAR_SCALE_IMAGE, cv::Size(frame.cols/4, frame.rows/4)); // Minimum size of obj

        //-- Draw rectangles around faces
        for( size_t i = 0; i < faces.size(); i++) {
            cv::rectangle(frame, faces[i], cv::Scalar( 255, 0, 255 ));
        }
        cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB);
        const QImage image(static_cast<const unsigned char*>(frame.data), frame.cols, frame.rows, frame.step, QImage::Format_RGB888, &matDeleter, new cv::Mat(frame));
        image.rgbSwapped();
        Q_ASSERT(image.constBits() == frame.data);

//This is the error location
        emit image_signal(image);
    }
2016-03-26 20:21:49 -0600 asked a question Minor bug + Laggy VideoCapture playback (C++)

Sorry about the gigantic post :P

First Question: The ViewLoop() member function does not output anything to the namedWindow() (simply a grey window with a loading cursor) despite the program still doing the facial rec...What is causing this?

Second Question: I've noticed this is a pretty common thing around here with non-realtime playback from a VideoCapture being routed to a namedWindow, so apologies if this appears repetitive.

I followed the tutorial for the FaceRecognizer module and despite the code being pretty terrible, the playback is far from real-time (more like 10-15 fps). From research, I've added the WINDOW_OPENGL flag to the namedWindow() as apparently it improves performance. I also came across an idea that I could split my program into 2 threads: the first takes the camera input and does the face recognition on the cv::Mat, and the second handles the imshow() function (which apparently is computationally heavy). Something about mutex's came up as well. How would I go about this?

Would this give enough of a performance boost to make the recognition real-time? If not, what else could I do?

Here is my code (with the bug I described earlier) that I have prepared to be threaded (I'm not too familiar with c++ multithreading primarily since NO ONE can explain it properly to me -_-) and any other improvements are welcome!


FaceDetect.h

#ifndef FACEDETECT_H
#define FACEDETECT_H

#include "opencv2/core.hpp"
#include "opencv2/face.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/objdetect.hpp"

#include <iostream>
#include <fstream>
#include <sstream>

#include <thread>

class FaceDetect {

public:

FaceDetect();
~FaceDetect();

static void ReadCSV(const std::string& filename, std::vector<cv::Mat>& images, std::vector<int>& labels, char separator = ';');
void init();
    // The fast loop?
void FaceDetectLoop();
   // The slow loop?
void ViewLoop();

private:

cv::VideoCapture m_cap;

int m_deviceID = 0;
int m_imgWidth, m_imgHeight;
std::string m_haarPath = "data/haarcascade_frontalface_default.xml";
std::string m_csvPath = "data/faceCSV.txt";
cv::Mat m_currFrame;
cv::Mat m_original;

std::vector<cv::Mat> m_images;
std::vector<int> m_labels;

cv::Ptr<cv::face::FaceRecognizer> m_model = cv::face::createFisherFaceRecognizer();
cv::CascadeClassifier m_haarCascade;

};

#endif // !FACEDETECT_H

FaceDetect.cpp

#include "FaceDetect.h"

using namespace std;
using namespace cv;
using namespace cv::face;


FaceDetect::FaceDetect() {
}

FaceDetect::~FaceDetect() {
}

//Read in data from CSV file (can be .txt, .csv, etc.)
void FaceDetect::ReadCSV(const std::string & filename, std::vector<cv::Mat>& images, std::vector<int>& labels, char separator) {

std::ifstream file(filename.c_str(), ifstream::in);
if (!file) {
    string error_message = "No valid input file was given, please check the given filename.";
    CV_Error(CV_StsBadArg, error_message);
}

string line, path, classlabel;

while (getline(file, line)) {
    stringstream liness(line);

    getline(liness, path, separator);
    getline(liness, classlabel);

    if (!path.empty() && !classlabel.empty()) {

        images.push_back(imread(path, 0));
        labels.push_back(atoi(classlabel.c_str()));
    }
}

return;
}

void FaceDetect::init() {

m_cap.open(0);

if (!m_cap.isOpened()) {
    cerr << "Capture Device ID " << m_deviceID << "cannot be opened." << endl;
    return;
}

// Read in the data
try {
    ReadCSV(m_csvPath, m_images, m_labels);
}
catch (cv::Exception& e) {
    cerr << "Error opening file \"" << m_csvPath << "\". Reason: " << e.msg << endl;
    exit(1);
}

//train recognizer ...
(more)