import cv2
|
import time
|
import threading
|
import numpy as np
|
import os, sys
|
|
# add python path of src to sys.path
|
src_path = os.path.join(__file__, *(['..'] * 2))
|
src_path = os.path.abspath(src_path)
|
sys.path.insert(0, src_path)
|
|
from protos import aerial_pb2 as pb
|
|
class cameraController(object):
|
|
def __init__(self,IMAGE_WIDTH,IMAGE_HEIGHT,CAMERA_COUNT,device_id,queue_dict):
|
self.image_width = IMAGE_WIDTH
|
self.image_height = IMAGE_HEIGHT
|
self.camera_count = CAMERA_COUNT
|
self.device_id = device_id
|
self.queue_dict = queue_dict
|
self.device_state_queue = self.queue_dict["device_state"]
|
self.image_data_queue = self.queue_dict["image_data"]
|
self._capture_thread = None
|
|
def open_cameras(self):
|
"""
|
Test the ports and returns a tuple with the available ports and the ones that are working.
|
"""
|
self.cameras = []
|
self.working_ports = []
|
for dev_port in range(self.CAMERA_COUNT):
|
camera = cv2.VideoCapture(dev_port, cv2.CAP_DSHOW)
|
camera.set(cv2.CAP_PROP_FRAME_WIDTH, self.IMAGE_WIDTH)
|
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, self.IMAGE_HEIGHT)
|
camera.set(cv2.CAP_PROP_FPS, 1)
|
if camera.isOpened():
|
is_reading, img = camera.read()
|
w = camera.get(3)
|
h = camera.get(4)
|
if is_reading:
|
self.working_ports.append(dev_port)
|
self.cameras.append(camera)
|
msg = f"{time.asctime()} {self.device_id} camera port {dev_port} is working and reads images ({h} x {w})"
|
else:
|
msg = f"{time.asctime()} {self.device_id} camera port {dev_port} is not working"
|
|
# add msg to queue
|
self.device_state_queue.put(msg)
|
print(msg)
|
|
|
def _start_captureThread(self):
|
"""start capture thread"""
|
if self._capture_thread is None:
|
self._capture_thread = \
|
CaptureThread(self.cameras,self.image_data_queue,interval=10)
|
self._capture_thread.setDaemon(True)
|
self._capture_thread.start()
|
|
def _stop_captureThread(self):
|
"""stop capture thread"""
|
if self._capture_thread is not None:
|
self._capture_thread.stop()
|
self._capture_thread = None
|
|
|
class CaptureThread(threading.Thread):
|
"""
|
camera capture thread
|
"""
|
def __init__(self, cameras, msg_queue, interval, image_quality = 95):
|
"""init the thread"""
|
threading.Thread.__init__(self)
|
self.cameras = cameras
|
self.msg_queue = msg_queue
|
self.interval = interval
|
self.image_quality = image_quality
|
self.is_stop = False
|
|
def stop(self):
|
"""stop the thread"""
|
self.is_stop = True
|
|
def run(self):
|
print("CaptureThread started")
|
self.next_time = time.time() + self.interval
|
while not self.is_stop:
|
this_time = time.time()
|
if this_time > self.next_time:
|
data1 = pb.ImagesMessage()
|
for i in range(len(self.cameras)):
|
_, frame = self.cameras[i].read()
|
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), self.image_quality]
|
_, encimg = cv2.imencode('.jpg', frame, encode_param)
|
if frame is not None:
|
np_array = np.asarray(encimg) # frame 转换为numpy数组
|
byte_array = np_array.tobytes() # numpy数组转换为byte数组
|
if i == 0:
|
data1.image1 = byte_array
|
elif i == 1:
|
data1.image2 = byte_array
|
elif i == 2:
|
data1.image3 = byte_array
|
elif i == 3:
|
data1.image4 = byte_array
|
data1_str = data1.SerializeToString()
|
|
# create protobuf message
|
req = pb.RequestCommand()
|
req.sys_command = pb.SysCommand.FIVE_G_COMMAND
|
req.sub_command = pb.SubCommand.FIVE_G_SEND_IMAGE_SUB_COMMAND
|
req.data1.length = len(data1_str)
|
req.data1.data = data1_str
|
# add message to queue
|
self.msg_queue.put(req)
|
self.next_time += self.interval
|
time.sleep(0.1)
|
for camera in self.cameras:
|
camera.release()
|
print("CaptureThread stopped")
|