簡體   English   中英

為什么我不能讓 3 個網絡攝像頭與 pthreads 並行運行?

[英]Why can't I get 3 webcam to run in parallel with pthreads?


我需要一些關於 OpenCV 的幫助,使用 C++ 進行線程化。 我正在使用樹莓派 3B。 這是一個四核。 有 4 個 USB 2.0 設備、3 個 USB 2.0 網絡攝像頭和 USB 2.0 ZEE5BCED252AB77EC8D633CDAZ1。 網絡攝像頭的電纜已被拼接以自行提供電壓,因此只有數據線進入 pi。 Arduino 由 pi 供電。 現在到了這個問題。 我有 4 個線程,3 個用於網絡攝像頭,1 個用於 Arduino。 網絡攝像頭等待 Arduino 並行向網絡攝像頭發送信號。 問題是,我無法讓 3 個攝像頭同時工作。 我可以讓 2 個攝像頭的任意組合工作,但不能工作 3 個。當我嘗試 3 個網絡攝像頭時,我收到空幀錯誤。

使用的網絡攝像頭鏈接

我試過沒有成功:

sudo modprobe uvcvideo nodrop=1 timeout=5000 quirks=0x80
[ WARN:2] global /home/pi/opencv/modules/videoio/src/cap_v4l.cpp (1004) tryIoctl VIDEOIO(V4L2:/dev/video0): select() timeout.
Empty Frame
terminate called after throwing an instance of 'cv::Exception'
  what():  OpenCV(4.3.0) /home/pi/opencv/modules/imgcodecs/src/loadsave.cpp:738: error: (-215:Assertion failed) !_img.empty() in function 'imwrite'

Aborted
    #include<stdio.h>
    #include<stdlib.h>
    #include<thread>
    #include<iostream>
    #include<fstream>

    #include<opencv2/highgui/highgui.hpp>
    #include<opencv2/imgproc/imgproc.hpp>
    #include<opencv2/core/core.hpp>
    #include"pthread.h"
    #include<stdlib.h>
    #include<string>
    #include<boost/date_time/posix_time/posix_time.hpp>

    #include<mutex>
    #include<condition_variable>
    #include<atomic>


    std::mutex m;
    std::condition_variable suspend_cv;
    std::atomic<bool> enabled (false);

    struct args {
        int camNum;
        char* camName;
        int x;
        int y;
        };


    void* camSetup(void *inputs){
    cv::VideoCapture stream(((struct args*)inputs)->camNum);
    cv::Mat Frame;
    //cv::Mat resizeFrame;
    if(!stream.isOpened()){
        std::cout << "Cannot Open Camera: " + ((struct args*) inputs)->camNum + '\n';
    }
    else{
        std::cout << "Camera Open: " << ((struct args*) inputs)->camNum + '\n';
    }
    std::unique_lock<std::mutex> lock(m);
    while (true){
        stream >> Frame;
        //cv::resize(Frame, resizeFrame, cv::Size(25, 25));
        while (enabled){
            // Get current time from the clock, using microseconds resolution
            const boost::posix_time::ptime now = 
                boost::posix_time::microsec_clock::local_time();

            // Get the time offset in current day
            const boost::posix_time::time_duration td = now.time_of_day();
            const long year         = now.date().year();
            const long month        = now.date().month();
            const long day          = now.date().day();
            const long hours        = td.hours();
            const long minutes      = td.minutes();
            const long seconds      = td.seconds();
            const long milliseconds = td.total_milliseconds() -
                                      ((hours * 3600 + minutes * 60 + seconds) * 1000);

            char buf[80];
            sprintf(buf, "%02ld%02ld%02ld_%02ld%02ld%02ld__%03ld", 
                year, month, day, hours, minutes, seconds, milliseconds);
                std::string sBuf = buf;
                std::string PATH = std::string("/home/pi/Desktop/") +
                                ((struct args*)inputs)->camName + 
                                    '/' +
                                    std::string(((struct args*)inputs)->camName) +
                                    '_' +
                                    sBuf +
                                    ".jpeg";
            if (Frame.empty())
            {
                std::cout << "Empty Frame" <<std::endl;
                stream >> Frame;
                //cv::resize(Frame, resizeFrame, cv::Size(25, 25));

            }
            cv::imwrite(PATH, Frame);
            if (cv::waitKey(30) >= 0){
                break;
            }
            suspend_cv.wait(lock);
        }
    }
    return NULL;
    }


    void* ardReader(void*){
    ARDUINO STUFF HAPPENS…
    }

    int main(){
    struct args *cameraA = (struct args *)malloc(sizeof(struct args));
    struct args *cameraB = (struct args *)malloc(sizeof(struct args));
    struct args *cameraC = (struct args *)malloc(sizeof(struct args));

    cameraA->camNum = 0;
    char camA[] = "camA";
    cameraA->camName = camA;
    cameraA->x = 100;
    cameraA->y =100;

    cameraB->camNum = 2;
    char camB[] = "camB";
    cameraB->camName = camB;
    cameraB->x = 100;
    cameraB->y = 300;

    cameraC->camNum = 4;
    char camC[] = "camC";
    cameraC->camName = camC;
    cameraC->x = 100;
    cameraC->y = 500;

    pthread_t t1, t2, t3, t4;

    pthread_create(&t1, NULL, camSetup, (void *) cameraA);
    pthread_create(&t2, NULL, camSetup, (void *) cameraB);
    pthread_create(&t3, NULL, camSetup, (void *) cameraC);
    pthread_create(&t4, NULL, ardReader, NULL);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_join(t3, NULL);
    pthread_join(t4, NULL);
    return 0;
    }

似乎 20mS 的差異對線程/opencv 產生了足夠大的差異。 要回答我自己的問題以防有人再次遇到此問題,請將 waitkey 時間更改為以下...

在這種情況下線程不正確

        if (cv::waitKey(30) >= 0){
            break;
        }

在這種情況下正確線程

        if (cv::waitKey(10) == 27){
            break;
        }

我還將cv::waitKey移動到主線程。 雖然我仍然有錯誤,但有時確實證明是有效的。

我做的最后一件事是每次需要抓取圖像時打開和關閉相機。 這讓我每次都能保證得到一個幀,雖然速度較慢,但它總是有效的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM