【问题标题】:Python Image Processing ThreadingPython图像处理线程
【发布时间】:2016-10-03 02:13:24
【问题描述】:

所以我正在做一个机器人项目,我们必须识别墙上的图案并相应地定位我们的机器人。我在我的笔记本电脑上开发了这个图像处理代码,它抓取图像,将其转换为 HSV,应用按位掩码,使用 Canny 边缘检测,并找到轮廓。我以为我可以将代码复制并粘贴到树莓派 3 上;但是,由于处理能力下降,fps小于1。我一直在尝试将代码分离到线程中,所以我可以有一个捕获图像的线程,一个将图像转换为HSV并过滤它的线程,和一根线进行轮廓拟合。为了让这些相互交流,我做了队列。

这是我最初的视觉代码:

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()

这是我的线程代码,它在主线程中抓取帧并在另一个线程中过滤它;我希望有另一个线程来进行轮廓拟合,但即使使用这两个过程,线程代码的 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()

我想知道我是否做错了什么,队列的访问是否会减慢代码的速度,以及我是否应该为这个应用程序使用多处理模块而不是线程。

【问题讨论】:

    标签: python multithreading python-3.x image-processing python-multithreading


    【解决方案1】:

    您可以使用cProfile 模块分析代码。它会告诉你程序的哪一部分是瓶颈。

    CPython 实现中的 Python 具有全局解释器锁 (GIL)。这意味着即使您的应用程序是多线程的,它也只会使用您的一个 CPU。你可以试试multiprocessing 模块。虽然 Jython 和 IronPython 没有 GIL,但它们没有或没有稳定的 Python3 支持。

    在您的代码中,self.lock 从未使用过。使用带有 pylint 的良好 IDE 来捕获此类错误。队列维护自己的锁。

    threading.Thread.__init__(self) 是来自 Python2 的过时语法。改用super().__init__()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-27
      • 2014-04-14
      • 2018-06-03
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多