OpenCV读取摄像头及AI模型的异步推理

文章目录

简介

  • 通过多线程的方式,将读取摄像头和深度学习模型推理分开来执行
  • 使用 PythonC++分别进行实现

Python

# -*- coding: utf-8 -*-

"""
    使用python多线程获取视频流,并异步进行模型推理
"""

import time
import copy
from threading import Thread, Lock

import cv2


frame = None  # 当前帧(摄像头所读到的帧)
flag = 0  # 当前帧的标识

lock = Lock()


def handle_frame():
    """
        线程函数,对视频帧进行推理
    """
    img = None  # 该线程中,最新推理的帧
    key = 0  # 该线程中,最新推理的帧所对应的标识,和flag不一致时,则更新img进行推理

    infer_count = 0  # 累计推理的帧的数量
    while True:
        if flag == -1:  # 标志主进程结束,此时应退出推理线程
            return
        if key != flag:
            # 当前帧已更新,需对最新的帧进行推理
            # 否则说明当前帧未更新,避免重复推理(仅出现在推理速度快的情况)
            lock.acquire()  # 对共享资源加锁

            key = flag
            img = copy.deepcopy(frame)

            lock.release()  # 释放锁

            # 此处用sleep模拟推理,后续可换成实际的推理函数
            time.sleep(3)
            infer_count += 1
            print("Infer num:", infer_count)
            print(img.shape)


def main():
    """
        主进程函数,读取摄像头的视频流
    """

    camera = cv2.VideoCapture(0)
    width = 640
    height = 480
    camera.set(cv2.CAP_PROP_FRAME_WIDTH, width)
    camera.set(cv2.CAP_PROP_FRAME_HEIGHT, height)

    # 开启模型推理线程
    t = Thread(target=handle_frame)
    t.start()

    frame_count = 0  # 累计读取的帧的数量
    while camera.isOpened():

        lock.acquire()

        # 更新当前帧
        global frame, flag
        ret, frame = camera.read()
        flag += 1

        lock.release()

        frame_count += 1
        print("Frame:", frame_count)

        # 实际项目中不需要下面这部分,可以换其他方式触发flag等于-1,从而终止推理线程
        kk = cv2.waitKey(1)
        # 按 q 键退出
        if kk == ord("q"):
            flag = -1  # 表示主进程将退出
            break
        else:
            cv2.imshow("camera", frame)

    t.join()  # 回收线程
    camera.release()
    cv2.destroyAllWindows()


if __name__ == '__main__':
    main()

C++

#include <iostream>
#include <thread>
#include <mutex>
#include <opencv2/opencv.hpp>

using namespace std;


cv::Mat frame;
volatile int flag = 0;

mutex mtx;


void handleFrame()
{
    cv::Mat img;
    int key = 0;

    int inferCount = 0;
    while (true)
    {
        if (flag == -1) return;

        if (key != flag)
        {
            mtx.lock();

            key = flag;
            img = frame.clone();

            mtx.unlock();

            this_thread::sleep_for(chrono::seconds(3));
            inferCount++;
            cout << "Infer num: " << inferCount << endl;
        }
    }
}


int main()
{
    cv::VideoCapture cap(0);
    if (!cap.isOpened())
    {
        cout << "Camera open failed." << endl;
        return -1;
    }

    int width = 640;
    int height = 480;
    cap.set(cv::CAP_PROP_FRAME_WIDTH, width);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, height);

    thread t(handleFrame);

    int frameCount = 0;
    while (true)
    {
        if (mtx.try_lock())
        {
            cap.read(frame);
            flag++;

            mtx.unlock();
        }

        frameCount++;
        cout << "Frame num: " << frameCount << endl;

        cv::imshow("Camera", frame);
        if (cv::waitKey(1) == 'q')
        {
            flag = -1;
            break;
        }
    }

    t.join();
    cap.release();
    cv::destroyAllWindows();

    return 0;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值