You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过子进程实现两路视频流车辆检测结果汇总写入文件?

问题描述

我有两路视频流,需要汇总两路中检测到的所有车辆总数。目前仅能对单路视频流进行车辆检测,并将检测结果按日期写入cars.txt文件。尝试复制代码实现双路检测时脚本频繁崩溃,该方案不可行。我想尝试使用子进程方案:由第三个脚本启动两个检测脚本、提取检测数值并将汇总结果带日期写入文件。请问该方案是否可行?是否可以直接从脚本获取数值,还是需要脚本输出到控制台再由主脚本读取?

现有检测代码

import cv2
import numpy as np
import time
import datetime

net = cv2.dnn.readNet('weights','cfg')
classes = []
with open('data/obj.names','r') as f:
    classes = f.read().splitlines()
cap = cv2.VideoCapture('ipaddress')
cap2 = cv2.VideoCapture('ipaddress2')
last_time = 0
while True:
    now = time.time()
    _,img = cap.read()
    height, width, _ = img.shape
    blob = cv2.dnn.blobFromImage(img, 1/255,  (416 , 416), (0,0,0) ,swapRB=True,crop=False)
    net.setInput(blob)
    output_layer_names = net.getUnconnectedOutLayersNames()
    layerOutput = net.forward(output_layer_names)
    boxes = []
    car = 0
    confidences = []
    class_ids =[]
    for output in layerOutput:
        for detection in output:
            scores = detection[5:]
            class_id = np.argmax(scores)
            confidence = scores[class_id]
            if confidence > 0.1:
                center_x = int(detection[0]*width)
                center_y = int(detection[1]*height)
                w = int(detection[2]*width)
                h = int(detection[3]*height)
                x = int(center_x - w/2)
                y = int(center_y - h/2)
                boxes.append([x,y,w,h])
                confidences.append((float(confidence)))
                class_ids.append(class_id)
    indexes = cv2.dnn.NMSBoxes(boxes,confidences,0.5,0.4)
    font = cv2.QT_FONT_NORMAL
    colors = np.random.uniform(0,255,size=(len(boxes),3))
    for i in indexes.flatten():
        labels = str(classes[class_ids[i]])
        if(labels == 'car'):
            car+=1
    if now - last_time >= 1800:
        with open('cars.txt','a') as f:
            f.write(f'{datetime.datetime.now()}: {car}\n')
        last_time = now
    for i in indexes.flatten():
        x,y,w,h = boxes[i]
        label =str(classes[class_ids[i]])
        confidence = str(round(confidences[i],1))
        color = colors[i]
        cv2.rectangle(img,(x,y),(x+w , y+h), [0,255,0], 2)
        cv2.putText(img, 'detected cars: ' + str(car), (20, 20), font, 0.8, (0,0,0),2)
        cv2.imshow('Image',img)
        key = cv2.waitKey(1)
        if key == 10:
            break
cap.release()
cv2.destroyAllWindows()
解决方案与说明

子进程方案可行性

子进程方案完全可行,这是解决单脚本多流检测崩溃的常用方案。单脚本双路检测崩溃的核心原因是OpenCV视频捕获、DNN推理在单线程下资源占用过高(比如GPU/CPU负载拉满、内存泄漏),拆分到独立子进程后,每个进程单独处理一路流,实现资源隔离,能有效避免崩溃问题。

数值获取方式选择

两种方式都可以实现,具体根据需求选择:

方式1:检测脚本输出到控制台,主脚本读取

这是最简单易实现的方案,无需大幅修改现有代码:

  1. 修改检测脚本:将原本写入文件的车辆数改为打印到标准输出(比如print(car)),确保输出内容为纯数字或固定格式(如car:15),避免其他日志干扰。
  2. 主脚本通过subprocess.Popen启动两个检测脚本,用stdout=subprocess.PIPE捕获输出,解析出车辆数。
  3. 主脚本按原定时逻辑(每30分钟)汇总数值并写入文件。

主脚本示例片段

import subprocess
import time
import datetime

# 启动两个检测子进程
proc1 = subprocess.Popen(['python', 'detect_stream1.py'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
proc2 = subprocess.Popen(['python', 'detect_stream2.py'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

last_summary_time = 0
while True:
    now = time.time()
    if now - last_summary_time >= 1800:
        # 读取子进程输出(需处理缓冲区,避免阻塞)
        count1 = int(proc1.stdout.readline().strip())
        count2 = int(proc2.stdout.readline().strip())
        total = count1 + count2
        with open('total_cars.txt', 'a') as f:
            f.write(f'{datetime.datetime.now()}: total cars {total} (stream1: {count1}, stream2: {count2})\n')
        last_summary_time = now
    time.sleep(1)

方式2:进程间通信直接获取数值

如果需要更可靠、实时的数值传递,可采用进程间通信(IPC)方案:

  • 使用multiprocessing模块的Queue或Pipe:将检测逻辑封装为函数,主脚本用multiprocessing.Process启动两个检测进程,检测进程将车辆数放入队列,主脚本从队列取数汇总。
  • 临时文件:检测脚本定时将车辆数写入独立临时文件(如stream1_count.txt),主脚本定时读取两个文件的数值汇总。

这种方式比控制台输出更稳定,适合对数据准确性要求高的场景,以下是multiprocessing实现示例:

检测函数(抽离原脚本逻辑)

import cv2
import numpy as np
import time
from multiprocessing import Queue

def detect_stream(ip_address, queue):
    net = cv2.dnn.readNet('weights','cfg')
    classes = []
    with open('data/obj.names','r') as f:
        classes = f.read().splitlines()
    cap = cv2.VideoCapture(ip_address)
    last_time = 0
    while True:
        now = time.time()
        _,img = cap.read()
        if img is None:
            time.sleep(1)
            continue
        height, width, _ = img.shape
        blob = cv2.dnn.blobFromImage(img, 1/255,  (416 , 416), (0,0,0) ,swapRB=True,crop=False)
        net.setInput(blob)
        output_layer_names = net.getUnconnectedOutLayersNames()
        layerOutput = net.forward(output_layer_names)
        boxes = []
        car = 0
        confidences = []
        class_ids =[]
        for output in layerOutput:
            for detection in output:
                scores = detection[5:]
                class_id = np.argmax(scores)
                confidence = scores[class_id]
                if confidence > 0.1:
                    center_x = int(detection[0]*width)
                    center_y = int(detection[1]*height)
                    w = int(detection[2]*width)
                    h = int(detection[3]*height)
                    x = int(center_x - w/2)
                    y = int(center_y - h/2)
                    boxes.append([x,y,w,h])
                    confidences.append((float(confidence)))
                    class_ids.append(class_id)
        indexes = cv2.dnn.NMSBoxes(boxes,confidences,0.5,0.4)
        if len(indexes) > 0:
            for i in indexes.flatten():
                labels = str(classes[class_ids[i]])
                if labels == 'car':
                    car +=1
        if now - last_time >= 1800:
            stream_tag = 'stream1' if 'ipaddress1' in ip_address else 'stream2'
            queue.put((stream_tag, car))
            last_time = now
        # 保留显示逻辑(可选)
        font = cv2.QT_FONT_NORMAL
        cv2.putText(img, 'detected cars: ' + str(car), (20, 20), font, 0.8, (0,0,0),2)
        cv2.imshow(f'Stream {ip_address}', img)
        key = cv2.waitKey(1)
        if key == 10:
            break
    cap.release()
    cv2.destroyAllWindows()

主脚本

import multiprocessing
import time
import datetime

if __name__ == '__main__':
    queue = multiprocessing.Queue()
    # 启动两个检测进程
    p1 = multiprocessing.Process(target=detect_stream, args=('ipaddress1', queue))
    p2 = multiprocessing.Process(target=detect_stream, args=('ipaddress2', queue))
    p1.start()
    p2.start()

    last_summary_time = 0
    counts = {'stream1':0, 'stream2':0}
    while True:
        now = time.time()
        # 读取队列中的检测数据
        while not queue.empty():
            stream, count = queue.get()
            counts[stream] = count
        # 定时汇总写入文件
        if now - last_summary_time >= 1800:
            total = counts['stream1'] + counts['stream2']
            with open('total_cars.txt', 'a') as f:
                f.write(f'{datetime.datetime.now()}: total cars {total} (stream1: {counts["stream1"]}, stream2: {counts["stream2"]})\n')
            last_summary_time = now
        time.sleep(1)
    p1.join()
    p2.join()

内容的提问来源于stack exchange,提问作者Isshen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 12:35:23