【问题标题】:Fail to automatically start an opencv program on raspberry pi 3无法在树莓派 3 上自动启动 opencv 程序
【发布时间】:2019-01-15 04:08:51
【问题描述】:

在我的树莓派 B+ 上自动启动我的 C++ 脚本时遇到问题。我为这个项目使用树莓派相机。我的脚本在第一阶段涉及面部检测,在第二阶段使用 openCv 库进行视频录制。我把视频录制阶段放到了一个线程中。我按照这篇文章的说明自动启动我的程序: https://www.raspberrypi.org/forums/viewtopic.php?t=138861 并且程序确实可以工作,直到它到达我从 systemctl 状态日志中收到此错误的视频录制阶段:

raspberrypi RASPCAMERA[2720]:无法初始化服务器:无法连接:连接被拒绝。 raspberrypi RASPCAMERA [2720]:(my_detection:2720):Gtk-WARNING **:无法打开显示: raspberrypi 系统 [1]:startCam.service:主进程退出,代码退出,状态 1/FAILURE raspberrypi system[1] 单元 startCam.service 进入失败状态。

尽管人脸检测阶段有效,但它的响应速度很慢。我也尝试过 rc.local 或 init.d 方法,但它们都不起作用。感谢您的帮助。

这是我的系统单元:

[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

这是我的 C++ 代码脚本:

// 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);


  }
  return 0;

}

int displayAndDetect(Mat frame)
{
   //.....Face Detection Function......//
}


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();
  return NULL;
}

【问题讨论】:

    标签: c++ opencv raspberry-pi


    【解决方案1】:

    systemd 和它的前辈一样,可以启动后台服务。这实际上是正常功能。后台服务,顾名思义,没有窗口。如果您将前台应用程序配置为后台服务,则在前台应用程序尝试顶部打开其窗口时,您会立即收到一条错误消息 - 正是您所看到的。

    如果您想运行带有可见窗口的应用程序,则必须有一个登录用户。如果您有一个登录用户,那么该用户的登录脚本必须已经运行。这为您提供了启动前台应用程序的明显位置:在该登录脚本中。 Raspberry Pi 支持多种不同的 Linux 发行版,因此请检查您正在运行的内容,以便了解要搜索的内容。

    【讨论】:

      猜你喜欢
      • 2021-06-08
      • 2022-12-05
      • 1970-01-01
      • 2022-11-27
      • 1970-01-01
      • 2017-02-27
      • 2015-06-13
      • 2019-08-08
      • 1970-01-01
      相关资源
      最近更新 更多