wu_xinjun
2022-03-04 6d4be793db7bfe31ad12b10c9468d4ef1a5e8f52
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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} can not work"
            else:  
                msg = f"{time.asctime()} {self.device_id} camera port {dev_port} can not found"
 
            # 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")