【问题标题】:YOLOV2 slow when Arduino serial comm inserted插入 Arduino 串行通讯时 YOLOV2 慢
【发布时间】:2020-04-15 21:05:15
【问题描述】:

我从事对象检测和跟踪系统已经有一段时间了。当检测到一个人时,我尝试点亮 LED,根据分辨率范围的宽度确定边界框的坐标。截至目前,当我没有插入串行通信功能时,FPS 大约为 30。但是当我插入串行通讯时,fps 会在 7-10 左右下降得太低。什么可能导致这里出现问题?

操作系统 = Windows

GPU = GTX 1070

CPU = i7

模型 = Darkflow,yolov2

物体检测代码。

import cv2
from darkflow.net.build import TFNet
import numpy as np
import time
from collections import namedtuple
import luggage_arduino

"""
Main system for running the whole script for object detection and tracking
"""
class NeuralNetwork:
def __init__(self):
    """Define model configuration and weight"""
    options = {
        'model': 'cfg/yolov2.cfg',
        'load': 'bin/yolov2.weights',
        'threshold': 0.8,  # Sets the confidence level of detecting box, range from 0 to 1
        'gpu': 0.8  # If do not want to use gpu, set to 0
    }

    """Define OpenCV configuration"""
    tfnet = TFNet(options)
    colors = [tuple(255 * np.random.rand(3)) for _ in range(10)]  # Set colors for different boxes
    capture = cv2.VideoCapture(0, cv2.CAP_DSHOW)
    capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
    capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)

    while True:  # Main loop for object detection and tracking
        stime = time.time()
        ret, frame = capture.read()
        box = cv2.rectangle(frame, (0, 0), (426, 720), (0, 0, 255), 2)  # Parameter of first segment (LEFT)
        box2 = cv2.rectangle(frame, (426, 0), (852, 720), (0, 0, 255), 2)  # Parameter of second segment (CENTER)
        box3 = cv2.rectangle(frame, (852, 0), (1280, 720), (0, 0, 255), 2)  # Parameter of third segment (RIGHT)
        if ret:
            results = tfnet.return_predict(frame)
            for color, result in zip(colors, results):
                tl = (result['topleft']['x'], result['topleft']['y'])
                br = (result['bottomright']['x'], result['bottomright']['y'])
                label = result['label']
                confidence = result['confidence']
                text = '{}: {:.0f}%'.format(label, confidence * 100)
                frame = cv2.rectangle(frame, tl, br, color, 5)
                frame = cv2.putText(frame, text, tl, cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 0), 2)
                self.center_of_box(tl, br)  # Calls the function for coordinate calculation
            cv2.imshow('frame', frame)
            print('FPS {:.1f}'.format(1 / (time.time() - stime)))
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    capture.release()
    cv2.destroyAllWindows()

def center_of_box(self, tl, br):
    self.tl = tl
    self.br = br
    center_coord = namedtuple("center_coord", ['x', 'y'])  # List of calculated center coord for each FPS
    center_x = ((tl[0] + br[0]) / 2)
    center_y = ((tl[1] + br[1]) / 2)
    center_box = center_coord(center_x, center_y)  # Save center coord of detected box in list
    print(center_box)
    self.box_tracking(center_x)  # Call function for tracking the box coord

def box_tracking(self, center_x):
    self.center_x = center_x
    while True:
        if 0 <= center_x <= 426:
            center = -1
        elif 426 < center_x <= 852:
            center = 0
        elif 852 < center_x <= 1280:
            center = 1
        else:
            center = 2
        break
    luggage_arduino.Arduino(center)  # Calls function for serial comm

pyserial 通信代码:

import serial
import time

arduino = serial.Serial("com3", 9600)


def serial_comm():  # Pass the function
    pass


"""Main class for serial comm"""


class Arduino:
    def __init__(self, center):
        self.serial_comm(center)  # Calls function of serial comm

    def serial_comm(self, center):
        if center == -1:
            time.sleep(1)
            arduino.write(b'L')  # b can be replaced with str.encode("Your string here")
            serial_comm()
        elif center == 0:
            time.sleep(1)
            arduino.write(b'C')
            serial_comm()
        elif center == 1:
            time.sleep(1)
            arduino.write(b'R')
            serial_comm()
        else:
            center = 2
            time.sleep(1)
            arduino.write(b'N')
            serial_comm()
        time.sleep(2)

【问题讨论】:

  • 运行串口通讯时你的CPU利用率是多少?
  • @hcheung 我使用 pcutils 检查速率,当它检测到盒子并点亮 LED 时,它显示 12% 和任务管理器大约 10%。
  • time.sleep()的调用? class Arduino 是否在 Thread 中使用?当您使用Serial.readline() 时,这些调用会阻塞并等待数据。请参阅stackoverflow.com/a/59472193/7919597中的速度改进部分
  • time.sleep 是秒还是毫秒?
  • @Joe 我没有使用线程,但我会学习并同时运行。谢谢!

标签: python opencv arduino object-detection darkflow


【解决方案1】:

调用time.sleep() 可能是您的函数未在线程中运行的原因。

class Arduino 是否用于Thread?如果没有,它可能应该。

当您使用Serial.readline() 时,这些调用会阻塞并等待数据。

请参阅this answer 中的速度改进部分和发布的代码here

【讨论】:

    【解决方案2】:

    对于那些有兴趣的人,我会发布我想出的答案。 解决方案是使用线程并同时运行这些类。这是代码!

    import cv2
    from darkflow.net.build import TFNet
    import numpy as np
    import time
    from collections import namedtuple
    import luggage_arduino
    import psutil
    import threading
    
    """
    Main system for running the whole script for object detection and tracking
    """
    center_of_x = []
    
    
    class NeuralNetwork():
        def __init__(self):
            self.object_detect()
    
        def object_detect(self):
            options = {
                'model': 'cfg/yolov2.cfg',
                'load': 'bin/yolov2.weights',
                'threshold': 0.8,  # Sets the confidence level of detecting box, range from 0 to 1
                'gpu': 0.8  # If do not want to use gpu, set to 0
            }
            cpu_usage = psutil.cpu_percent(interval=1)
            tfnet = TFNet(options)
            capture = cv2.VideoCapture(0, cv2.CAP_DSHOW)
            capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
            capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
            while True:  # Main loop for object detection and tracking
                stime = time.time()
                ret, frame = capture.read()
                box = cv2.rectangle(frame, (0, 0), (426, 720), (0, 0, 255), 2)  # Parameter of first segment (LEFT)
                box2 = cv2.rectangle(frame, (426, 0), (852, 720), (0, 0, 255), 2)  # Parameter of second segment (CENTER)
                box3 = cv2.rectangle(frame, (852, 0), (1280, 720), (0, 0, 255), 2)  # Parameter of third segment (RIGHT)
                if ret:
                    results = tfnet.return_predict(frame)
                    for result in results:
                        tl = (result['topleft']['x'], result['topleft']['y'])
                        br = (result['bottomright']['x'], result['bottomright']['y'])
                        label = result['label']
                        confidence = result['confidence']
                        text = '{}: {:.0f}%'.format(label, confidence * 100)
                        frame = cv2.rectangle(frame, tl, br, (255, 153, 255), 2)
                        frame = cv2.putText(frame, text, tl, cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 0), 2)
                        self.center_of_box(tl, br)
                    cv2.imshow('frame', frame)
                    print('FPS {:.1f}'.format(1 / (time.time() - stime)))
                    print(cpu_usage)
                if cv2.waitKey(1) & 0xFF == ord('q'):
                    break
    
            capture.release()
            cv2.destroyAllWindows()
    
        def center_of_box(self, tl, br):
            global center_of_x
            self.tl = tl
            self.br = br
            center_coord = namedtuple("center_coord", ['x', 'y'])  # List of calculated center coord for each FPS
            center_x = ((tl[0] + br[0]) / 2)
            center_y = ((tl[1] + br[1]) / 2)
            center_box = center_coord(center_x, center_y)  # Save center coord of detected box in list
            center_of_x.clear()
            center_of_x.append(center_x)
            print(center_box)
            return center_x
    
    
    class Ard:
        def __init__(self):
            time.sleep(7)
            while True:
                for i in center_of_x:
                    self.box_tracking(i)
    
        def box_tracking(self, center_x):
            self.center_x = center_x
            while True:
                if 0 <= center_x <= 426:
                    center = -1
                elif 426 < center_x <= 852:
                    center = 0
                elif 852 < center_x <= 1280:
                    center = 1
                else:
                    center = 2
                break
            luggage_arduino.Arduino(center)  # Calls function for serial comm
    
    
    t1 = threading.Thread(target=NeuralNetwork)
    t2 = threading.Thread(target=Ard)
    
    t1.start()
    t2.start()
    

    这是arduino代码。

    int data;
    int LED2=2;
    int LED3=3;
    int LED4=4;
    
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      pinMode(LED2, OUTPUT);
      digitalWrite (LED2, LOW);
      pinMode(LED3, OUTPUT);
      digitalWrite (LED3, LOW);
      pinMode(LED4, OUTPUT);
      digitalWrite (LED4, LOW);
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      while (Serial.available()){
        data = Serial.read();
        if(data == 'L'){
          digitalWrite(LED2, HIGH);
          delay(100);
          digitalWrite(LED2, LOW);
          digitalWrite(LED3, LOW);
          digitalWrite(LED4, LOW);
        }
        else if (data == 'C'){
          digitalWrite(LED3, HIGH);
          delay(100);
          digitalWrite(LED3, LOW);
          digitalWrite(LED2, LOW);
          digitalWrite(LED4, LOW);
        }
        else if (data == 'R'){
          digitalWrite(LED4, HIGH);
          delay(100);
          digitalWrite(LED4, LOW);
          digitalWrite(LED2, LOW);
          digitalWrite(LED3, LOW);
        }
        else if (data == 'N'){
          digitalWrite(LED2, LOW);
          digitalWrite(LED3, LOW);
          digitalWrite(LED4, LOW);
        }
      }
    }
    

    这是 pyserial 代码。

    import serial
    import time
    
    arduino = serial.Serial("com3", 9600)
    
    
    def serial_comm():  # Pass the function
        pass
    
    
    """Main class for serial comm"""
    
    
    class Arduino:
        def __init__(self, center):
            self.serial_comm(center)  # Calls function of serial comm
    
        def serial_comm(self, center):
            self.center = center
            if center == -1:
                time.sleep(1)
                arduino.write(b'L')  # b can be replaced with str.encode("Your string here")
                serial_comm()
            elif center == 0:
                time.sleep(1)
                arduino.write(b'C')
                serial_comm()
            elif center == 1:
                time.sleep(1)
                arduino.write(b'R')
                serial_comm()
            else:
                center = 2
                time.sleep(1)
                arduino.write(b'N')
                serial_comm()
            time.sleep(2)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-20
      • 1970-01-01
      相关资源
      最近更新 更多