touch-sp.hatenablog.com
前回はOpenCVではどうしてもうまくいかなかったと書いた。
数日間調べ続けてようやく解決策を発見した。
stackoverflow.com
import mxnet as mx import gluoncv import serial, time import cv2, queue, threading class VideoCapture: def __init__(self, name): self.cap = cv2.VideoCapture(name) self.q = queue.Queue() t = threading.Thread(target=self._reader) t.daemon = True t.start() # read frames as soon as they are available, keeping only most recent one def _reader(self): while True: ret, frame = self.cap.read() if not ret: break if not self.q.empty(): try: self.q.get_nowait() # discard previous (unprocessed) frame except queue.Empty: pass self.q.put(frame) def read(self): return self.q.get() ser =serial.Serial("COM4", 9600) time.sleep(1.5) #初期設定 servo_angle = 90 ctx = mx.gpu() # Load the model classes = ['face'] net = gluoncv.model_zoo.get_model('ssd_512_mobilenet1.0_custom', classes=classes, pretrained=False, root='./model') net.load_parameters('ssd_512_mobilenet1.0_face.params') net.collect_params().reset_ctx(ctx) # Compile the model for faster speed net.hybridize() cap = VideoCapture('rtsp://192.72.1.1:554/liveRTSP/av4/track0') time.sleep(1) while True: frame = cap.read() frame = mx.nd.array(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)).astype('uint8') rgb_nd, frame = gluoncv.data.transforms.presets.ssd.transform_test(frame, short=320) # Run frame through network class_IDs, scores, bounding_boxes = net(rgb_nd.as_in_context(ctx)) if scores[0][0] > 0.6: x_min = bounding_boxes[0][0][0] y_min = bounding_boxes[0][0][1] x_max = bounding_boxes[0][0][2] y_max = bounding_boxes[0][0][3] if x_min > 360: if x_min > 480: servo_angle += 15 else: servo_angle += 3 if x_max < 280: if x_max <160: servo_angle -= 15 else: servo_angle -= 3 servo_angle = 160 if servo_angle > 160 else servo_angle servo_angle = 20 if servo_angle < 20 else servo_angle #bufferがゼロになるまで待つ finished = False while not finished: finished = (ser.out_waiting == 0) send_data = servo_angle.to_bytes(1, 'big') ser.write(send_data) ser.write((255).to_bytes(1, 'big')) # Display the result img = gluoncv.utils.viz.cv_plot_bbox(frame, bounding_boxes[0], scores[0], class_IDs[0], class_names=net.classes, thresh=0.6) gluoncv.utils.viz.cv_plot_image(img) # escを押したら終了 if cv2.waitKey(1) == 27: break time.sleep(0.2) cv2.destroyAllWindows()
「VLC」を使うより「OpenCV」を使った方が映像転送の際のタイムラグが少ない。
「APEMAN A79」でも「iPhone」の時と同等の速度が出ている。
当初「APEMAN A79」と「iPhone」の違いが原因と思っていたが、どうやら「VLC」と「OpenCV」の違いが原因であった。