billho
Posts: 1
Joined: Sun Aug 05, 2018 12:30 am

Failed to automatically start a program with opencv.

Sun Aug 05, 2018 1:55 am

Hi!

I am having a problem with starting my C++ script automatically on my raspberry pi B+. I use a raspberry pi camera for this project. My script involves a facial detection on the first stage and a video recording on the second stage using openCv library. I put the video recording stage into a thread. I followed the instruction from this post:
viewtopic.php?t=138861 and the program does work until it reaches the video recording stage from which I get this error from the systemctl status log:

raspberrypi RASPCAMERA[2720]: Unable to init server: could not connect: connection refused.
raspberrypi RASPCAMERA[2720]: (my_detection: 2720): Gtk-WARNING **: cannot open display:
raspberrypi system[1]: startCam.service: main process exited, code-exited, status-1/FAILURE
raspberrypi system[1] Unit startCam.service entered failed state.

Even though the face detection stage works, its response was quite slow. I have also tried rc.local or init.d method but none of them worked as well. I appreciate any helps.

This is my systemd unit:

[Service]
Type=simple
WorkingDirectory= /home/pi/C_code/Raspi_Cam/build
ExecStart= /home/pi/C_code/Raspi_Cam/build/Raspi_cam
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=RASPCAMERA
User=root
Group=root
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target

This is my C++ code script:

// FaceDetection.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <pthread.h>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include "opencv2/videoio/videoio.hpp"
#include "opencv2/core/core.hpp"
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <chrono>
#include <ctime> // localtime
#include <sstream> // stringstream
#include <iomanip> // put_time
#include <string> // string

using namespace std;
using namespace cv;


int displayAndDetect(Mat);
void* threadVideoRecord(void *);
string fileNameface = "haarcascade_frontalface_alt.xml";
string fileNameeyes = "haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_class;
CascadeClassifier eye_class;
string window_name = "my_face_detection";
VideoCapture capture(0);
int FrameWidth = capture.get(CAP_PROP_FRAME_WIDTH);
int FrameHeight = capture.get(CAP_PROP_FRAME_HEIGHT);


std::string return_current_time_and_date() {
std::string s = date::format("%F %T", std::chrono::system_clock::now());
for (std::string::iterator it = s.begin(); it != s.end(); it++)
if (*it == '.')
{
*it = ',';
break;
}
else if (*it == ':')
*it = ';';
return s;
}

int main(int argc, const char** argv)
{
system("modprobe bcm2835-v4l2");
Mat frame;
int check;

if (!face_class.load(fileNameface)) { cout << "unable to load face classifier" << endl; }
if (!eye_class.load(fileNameeyes)) { cout << "unable to load eyes classifier" << endl; }
if (!capture.isOpened()) { cout << "unable to initiallize camera" << endl; }
else
{
auto start = std::chrono::steady_clock::now();
while (true)
{
capture >> frame;
if ((check = displayAndDetect(frame)) != 0)
{
cout << "hit!! " << endl;
auto duration = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - start);
if (duration.count() >= 3)
break;
}
else
{
cout << "missed" << endl;
start = std::chrono::steady_clock::now();
}
int c = waitKey(1);
if (c == 27)
{
break;
}
}
std::string outputName = return_current_time_and_date() + ".avi";
cout << outputName << endl;
VideoWriter *videoWrite = new VideoWriter(outputName, -1, 10, Size(FrameWidth, FrameHeight), true);
pthread_t id;
pthread_attr_t attr;
pthread_attr_init(&attr);

pthread_create(&id, &attr, threadVideoRecord, videoWrite);

pthread_join(id, NULL);


}
//system("ffmpeg -i output.avi -crf 20 output.mp4"); //-crf for avi extension, -q for mp4 extension
return 0;

}

int displayAndDetect(Mat frame)
{

vector<Rect> faces;
Mat frameGray;

cvtColor(frame, frameGray, CV_BGR2GRAY);
equalizeHist(frameGray, frameGray); //It is a method that improves the contrast in an image, in order to stretch out the intensity range. -> Improve contrast of the frame.
//Detect face
face_class.detectMultiScale(frame, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));

if (faces.size() < 1)
return 0;
else
{
for (size_t i = 0; i < faces.size(); i++) //std::size_t can store the maximum size of a theoretically possible object of any type (including array). it is a unsigned long long
{
Point center(faces.x + 0.5*faces.width, faces.y + 0.5*faces.height);
ellipse(frameGray, center, Size(faces.width*0.5, faces.height*0.5), 0, 0, 360, Scalar(0, 255, 0), 4, 8, 0);

Mat faceROI = frameGray(faces); //crop the faces. There is a template: template<typename _Tp > Mat(const std::vector< _Tp > &vec). This is constructor overload built in Mat.

//Eye detection
vector<Rect> eyes;
eye_class.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));

for (size_t j = 0; j < eyes.size(); j++)
{
Point center(faces.x + eyes[j].x + eyes[j].width*0.5, faces.y + eyes[j].y + eyes[j].height*0.5);
int radius = cvRound((eyes[j].width + eyes[j].height)*0.25);
circle(frameGray, center, radius, Scalar(255, 0, 0), 4, 8, 0);
}
}
}

return 1;
}

void* threadVideoRecord(void *f)
{
Mat frame,frameGray;
VideoWriter *vid = (VideoWriter *) f;
int c;
while (true)
{
capture >> frame;
c = waitKey(10);
if (c == 27)
break;
cvtColor(frame, frameGray, CV_BGR2GRAY);
equalizeHist(frameGray, frameGray);
(*vid).write(frameGray);
imshow(window_name, frameGray);
}
//videoWrite.release();
pthread_exit(NULL);
return NULL;
}

Return to “C/C++”