功能描述:相机采集图片,同时对采集的图片进行处理
功能说明:采集和处理两个模块采用线程处理,数据使用循环队列进行存储。
- 主程序
#encoding: utf-8
'''
该文件用于控制多个相机的采集和算法调用
'''
import time
import uuid, cv2
import numpy as np
import threading
from threading import Thread
from detect_ipl import MASK
from grab_ipl import CAMERAOFFICE, CYCLEQUEUE
class CAMRECOG():
def __init__(self, ip, channel):
self.grabObj = CAMERAOFFICE(ip=ip, channel=channel)
self.maskObj = MASK() #检测是否佩戴口罩的算法
assert self.grabObj.get_flag_init() , '**cam:{} init failed**'.fromat(ip)
self.FPS = 2 #单位时间内采集和调用算法的图片数
self.tm_sleep = 1*1.0/self.FPS #采集等待时间
self.queue_buffs = CYCLEQUEUE(20) #保留20帧图片
self.grab_idx = 0
self.recog_idx = 0
pass
def grab(self): #采集程序
while True:
print('grab: {}, threadid: {}'.format(self.grab_idx, threading.current_thread()), flush=True)
self.grab_idx += 1
img = self.grabObj.grab()
# if isinstance(img, np.ndarray):
# cv2.imwrite('rst/grab_{}.jpg'.format(str(uuid.uuid4())), img)
self.queue_buffs.enqueue(img) #循环队列
time.sleep(self.tm_sleep)
def recog(self): #识别程序
while True:
print('recog: {}, threadid: {}'.format(self.recog_idx, threading.current_thread()), flush=True)
self.recog_idx += 1
if not self.queue_buffs.is_empty():
img = self.queue_buffs.dequeue()
# if isinstance(img, np.ndarray):
# print('dequeue img: {}'.format(img.shape))
# cv2.imwrite('rst/{}.jpg'.format(str(uuid.uuid4())), img)
rst = self.maskObj.recog(img)
print(rst, flush=True)
if rst['returncode'] != 0:
print('error: {}'.format(rst))
# return
continue
self.maskObj.parseObj.parse(rst['result'])
if self.maskObj.parseObj.isNoMask():
print('!!no mask!!')
else:
time.sleep(0.02) #否则该线程会一直占用GIL导致无法采集
if __name__ == '__main__':
monitorObj = CAMRECOG(ip='100.18.77.245', channel='101')
monitorObj2 = CAMRECOG(ip='100.18.10.244', channel='201') #相机初始化
threads = [] #构建线程池
t = Thread(target=monitorObj.grab, args=())
threads.append(t)
t = Thread(target=monitorObj.recog, args=())
threads.append(t)
t = Thread(target=monitorObj2.grab, args=())
threads.append(t)
t = Thread(target=monitorObj2.recog, args=())
threads.append(t)
threads[0].start() #启动线程
threads[1].start()
threads[2].start()
threads[3].start()
- 循环队列采用链表对象进行模拟。
class CYCLEQUEUE(object):
def __init__(self, maxsize):
self.maxsize = maxsize
self.reset()
def reset(self):
self.queue = [None] * self.maxsize
self.front = 0
self.rear = 0
# 如果队列未满,则在队尾插入元素,时间复杂度O(1)
def enqueue(self, data):
if (self.rear + 1) % self.maxsize == self.front:
print("The queue is full!")
self.reset() #重置队列内容
self.queue[self.rear] = data
# self.queue.insert(self.rear,data)
self.rear = (self.rear + 1) % self.maxsize
# 如果队列不为空,则删除队头的元素,时间复杂度O(1)
def dequeue(self):
if self.rear == self.front:
print("The queue is empty!")
else:
data = self.queue[self.front]
self.queue[self.front] = None
self.front = (self.front + 1) % self.maxsize
return data
# 返回当前队列的长度
def get_length(self):
return (self.rear - self.front + self.maxsize) % self.maxsize
def is_empty(self):
num = self.get_length()
return num == 0 #不考虑元素覆盖情况
# 输出队列中的元素
def get_queue(self):
for i in range(self.maxsize):
print(self.queue[i],end=',')
print(' ')
- 处理结果