1

私はロボティクスプロジェクトに取り組んでいます。そこでは、壁のパターンを認識し、それに応じてロボットを配置する必要があります。私はこの画像処理コードを自分のラップトップで開発し、画像を取得し、HSVに変換し、ビットマスクを適用し、Cannyエッジ検出を使用して輪郭を発見した。私はコードをコピーしてラズベリーのパイ3に貼り付けることができたと思った。しかし、処理能力が低下するため、fpsは1未満です。私はコードをスレッドに分離しようとしています。そのため、イメージをキャプチャするスレッド、イメージをHSVに変換してフィルタするスレッド、輪郭フィッティングを行う1つのスレッド。これらが互いに通信するために、私は列を作った。ここで Python画像処理スレッディング

が私の最初のビジョンコードです:

import numpy as np 
import cv2 
import time 
import matplotlib.pyplot as plt 
import sys 

def onmouse(k, x, y, s, p): 
    global hsv 
    if k == 1: # left mouse, print pixel at x,y 
     print(hsv[y, x]) 

def distance_to_camera(Kwidth, focalLength, pixelWidth): 
    return (Kwidth * focalLength)/pixelWidth 

def contourArea(contours): 

    area = [] 
    for i in range(0,len(contours)): 
     area.append([cv2.contourArea(contours[i]),i]) 

    area.sort() 
    if(area[len(area) - 1] >= 5 * area[0]): 
     return area[len(area)-1] 

    else: return 0 

if __name__ == '__main__': 

    cap = cv2.VideoCapture(0) 

    """ 
    cap.set(3, 1920) 
    cap.set(4, 1080) 
    cap.set(5, 30) 
    time.sleep(2) 
    cap.set(15, -8.0) 
    """ 

    KNOWN_WIDTH = 18 

    # focalLength = focalLength = (rect[1][1] * 74)/18 

    focalLength = 341.7075686984592 

    distance_data = [] 

    counter1 = 0 

    numFrames = 100 
    samples = 1 
    start_time = time.time() 

    while (samples < numFrames): 
     # Capture frame-by-frame 
     ret, img = cap.read() 

     length1, width1, channels = img.shape 
     img = cv2.GaussianBlur(img, (5, 5), 0) 

     hsv = cv2.cvtColor(img.copy(), cv2.COLOR_BGR2HSV) 

     # lower_green = np.array([75, 200, 170]) 
     # lower_green = np.array([53,180,122]) 

     #lower_green = np.array([70, 120, 120]) 

     lower_green = np.array([70, 50, 120]) 

     upper_green = np.array([120, 200, 255]) 

     #upper_green = np.array([120, 200, 255]) 

     mask = cv2.inRange(hsv, lower_green, upper_green) 
     res = cv2.bitwise_and(hsv, hsv, mask=mask) 

     gray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY) 

     edged = cv2.Canny(res, 35, 125) 

     im2, contours, hierarchy = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) 

     if (len(contours) > 1): 

      area,place = contourArea(contours) 

      #print(area) 
      if(area != 0): 

       # print("Contxours: %d" % contours.size()) 
       # print("Hierarchy: %d" % hierarchy.size()) 

       c = contours[place] 

       cv2.drawContours(img, c, -1, (0, 0, 255), 3) 
       cv2.drawContours(edged,c, -1, (255, 0, 0), 3) 
       perimeter = cv2.arcLength(c, True) 

       M = cv2.moments(c) 

       cx = 0 
       cy = 0 

       if (M['m00'] != 0): 
        cx = int(M['m10']/M['m00']) # Center of MASS Coordinates 
        cy = int(M['m01']/M['m00']) 

       rect = cv2.minAreaRect(c) 
       box = cv2.boxPoints(rect) 
       box = np.int0(box) 
       cv2.drawContours(img, [box], 0, (255, 0, 0), 2) 
       cv2.circle(img, (cx, cy), 7, (0, 0, 255), -1) 

       cv2.line(img, (int(width1/2), int(length1/2)), (cx, cy), (255, 0, 0), 2) 


       if(rect[1][1] != 0): 
        inches = distance_to_camera(KNOWN_WIDTH, focalLength, rect[1][1]) 

        #print(inches) 
        distance_data.append(inches) 

       counter1+=1 
     samples+=1 
     """ 
     cv2.namedWindow("Image w Contours") 
     cv2.setMouseCallback("Image w Contours", onmouse) 
     cv2.imshow('Image w Contours', img) 

     cv2.namedWindow("HSV") 
     cv2.setMouseCallback("HSV", onmouse) 
     cv2.imshow('HSV', edged) 

     if cv2.waitKey(1) & 0xFF == ord('x'): 
      break 
     """ 

# When everything done, release the capture 

    totTime = time.time() - start_time 
    print("--- %s seconds ---" % (totTime)) 
    print('----%s fps ----' % (numFrames/totTime)) 
    cap.release() 
    cv2.destroyAllWindows() 

    --- 13.469419717788696 seconds --- 
    ----7.42422480665093 fps ---- 


    plt.plot(distance_data) 
    plt.xlabel('TimeData') 
    plt.ylabel('Distance to Target(in) ') 
    plt.title('Distance vs Time From Camera') 
    plt.show() 

これは、メインのフレームをつかみ、別のスレッドでそれをフィルタリングし、私のスレッドコード、です。私は等高線フィッティングのための別のスレッドを持っていますが、これらの2つのプロセスでも、スレッドコードは前のコードとほぼ同じFPSを持っています。また、これらの結果は私のラップトップのものであり、ラズベリーパイではありません。

import cv2 
import threading 
import datetime 
import numpy as np 
import queue 
import time 

frame = queue.Queue(0) 
canny = queue.Queue(0) 
lower_green = np.array([70, 50, 120]) 
upper_green = np.array([120, 200, 255]) 

class FilterFrames(threading.Thread): 
    def __init__(self,threadID,lock): 
     threading.Thread.__init__(self) 
     self.lock = lock 
     self.name = threadID 
     self.setDaemon(True) 
     self.start() 

    def run(self): 

     while(True): 
      img1 = frame.get() 
      img1 = cv2.GaussianBlur(img1, (5, 5), 0) 
      hsv = cv2.cvtColor(img1.copy(), cv2.COLOR_BGR2HSV) 
      mask = cv2.inRange(hsv, lower_green, upper_green) 
      res = cv2.bitwise_and(hsv, hsv, mask=mask) 
      edged = cv2.Canny(res, 35, 125) 
      canny.put(edged) 

if __name__ == '__main__': 

    lock = threading.Lock() 
    numframes = 100 
    frames = 0 

    cap = cv2.VideoCapture(0) 

    filter = FilterFrames(lock=lock, threadID='Filter') 

    start_time = time.time() 
    while(frames < numframes): 

     ret,img = cap.read() 

     frame.put(img) 

     frames+=1 

    totTime = time.time() - start_time 
    print("--- %s seconds ---" % (totTime)) 
    print('----%s fps ----' % (numframes/totTime)) 

    """ 
    Results were: 

    --- 13.590131759643555 seconds --- 
    ----7.358280388197121 fps ---- 

    """ 
    cap.release() 

私はマルチプロセッシングモジュールを使用しての代わりに、このアプリケーションのスレッド化する必要がある場合は、キューのアクセスコードを減速、およびされているかどうか、私が間違っているのものがある場合、私は思っていました。

答えて

1

cProfileモジュールを使用してコードをプロファイルできます。プログラムのどの部分がボトルネックかを教えてくれます。

CPython実装のPythonには、グローバルインタープリタロック(GIL)があります。これは、あなたのアプリがマルチスレッドであっても、あなたのCPUの1つだけを使用することを意味します。 multiprocessingモジュールを試すことができます。 JythonとIronPythonにはGILがありませんが、安定したPython3のサポートはありません。

コードにself.lockは決して使用されません。この種のエラーを捕捉するには、pylintの良いIDEを使用します。キューは独自のロックを維持します。

threading.Thread.__init__(self)は、Python2の古い構文です。代わりに使用するsuper().__init__()