繁体   English   中英

为什么使用 multiprocessing.pool() 运行代码比不使用它运行代码慢 100 倍?

[英]why running the code with multiprocessing.pool() is 100x slower than running the code without it?

我正在使用 Windows 8.1 核心 I4 和带有 Opencv 4.1 的 python 3.7。 我想检测帧中的黑色物体,并在它们周围显示一个绿色方块,并在它们周围显示最暗的一个红色方块。 我写了一个代码来检测图像中的黑点。 并找到最暗的一个并将其标记为目标。 当我按顺序执行代码时,它工作正常。 我需要使用Multiprocessing.pool()减少运行时间。 这是我没有多处理的原始代码(我在每个段落中添加了一个命令行来描述处理)

class Detection:
    def __init__(self):
        self.image = []
        self.image_filter_hvs = []

    def first_filter(self):
        # Blur image to remove noise
        image_filter_gaussian = cv2.GaussianBlur(self.image.copy(), (3, 3), 0)
        # Convert image from BGR to HSV
        self.image_filter_hvs = cv2.cvtColor(image_filter_gaussian, cv2.COLOR_BGR2HSV)

    def filters(self, lower, higher):
        # Set pixels to white if in color range, others to black (binary bitmap)
        image_binary_one_color = cv2.inRange(self.image_filter_hvs, lower, higher)
        # Dilate image to make white blobs larger
        binary_image = cv2.dilate(image_binary_one_color, None, iterations=2)
        return binary_image

    def find_contours(self, binary_image):
        contours = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]
        target_possible_position = []
        # remove some contours to accelerate the program
        if len(contours) > 0:
            for ContFrame in contours:  # contours' in a frame
                area = cv2.contourArea(ContFrame)
                if 200 > area > 15:
                    xx, yy, ww, hh = cv2.boundingRect(ContFrame)
                    # center of each contour
                    center = (int(xx + ww / 2), int(yy + hh / 2))
                    # temp= color of central pixel
                    temp = self.image[center[1]][center[0]][2]
                    # temp_array= [color [xx, yy, ww, hh]]
                    target_possible_position.append([temp, [xx, yy, ww, hh]])
        return target_possible_position

    def find_best_contours(self, target_position):
        if len(target_position) > 0:
            first_item = itemgetter(0)
            # sort by the color of central pixel to remove lighter contours
            target_position = sorted(target_position, key=first_item)
            # remove some contours to decrease the running time
            for i in range(round(len(target_position) / 4)):
                temp1 = target_position[i]
                xx = temp1[1][0]
                yy = temp1[1][1]
                ww = temp1[1][2]
                hh = temp1[1][3]
                # Draw a green circle around each contour
                cv2.rectangle(self.image, (xx, yy), (xx + ww, yy + hh), (0, 255, 0), 2)
            # Draw a red square around the darkest contour by center pixel
            # temp_array[1][0]=xx temp_array[1][1]=yy temp_array[1][2]=ww temp_array[1][3]=hh
            cv2.rectangle(self.image, (target_position[0][1][0], target_position[0][1][1]),
                          (target_position[0][1][0] + target_position[0][1][2],
                           target_position[0][1][1] + target_position[0][1][3]),
                          (0, 0, 255), 2)
            # return estimated value which will use in tracker
            return \
                target_position[0][1][0], \
                target_position[0][1][1], \
                target_position[0][1][2], \
                target_position[0][1][3]


# Main
target_estimated_location = []
cam = cv2.VideoCapture("data2.avi")

ob = Detection()
while True:
    ret_val, frame = cam.read()
    if not ret_val:
        print("can not open the video")
        break
    # detection
    ob.image = frame
    ob.first_filter()
    binary_image_1 = ob.filters((0, 0, 0), (255, 100, 130))
    target_position = ob.find_contours(binary_image_1)
    target_locations = ob.find_best_contours(target_position)
    Output_image = ob.image
    cv2.imshow('webcam', Output_image)
    cv2.waitKey(20)
cam.release()

我想减少运行时间。 所以我决定使用 multiprocessing 并将 For 循环更改为 multiprocessing.pool 以使用所有 CPU 能力。

class Detection:
    def __init__(self):
        self.image = []
        self.image_filter_hvs = []

    def first_filter(self):  # this part filter the frame
        # Blur image to remove noise
        image_filter_gaussian = cv2.GaussianBlur(self.image.copy(), (3, 3), 0)
        # Convert image from BGR to HSV
        self.image_filter_hvs = cv2.cvtColor(image_filter_gaussian, cv2.COLOR_BGR2HSV)

    def filters(self, lower, higher):  # put a threshold to remove some colors
        # Set pixels to white if in color range, others to black (binary bitmap)
        image_binary_one_color = cv2.inRange(self.image_filter_hvs, lower, higher)
        # Dilate image to make white blobs larger
        binary_image = cv2.dilate(image_binary_one_color, None, iterations=2)
        return binary_image

    def find_contours(self, binary_image):  # find contours in the frame
        contours = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]
        return contours

    def Green_contours(self, ContFrame):
        # remove some contours to accelerate the program
        if len(ContFrame) > 0:
            area = cv2.contourArea(ContFrame)
            if 200 > area > 15:
                xx, yy, ww, hh = cv2.boundingRect(ContFrame)
                # center of each contour
                center = (int(xx + ww / 2), int(yy + hh / 2))
                # Draw a green circle around the largest enclosed contour
                # temp= color of central pixel
                temp = self.image[center[1]][center[0]][2]
                # temp_array= [color [xx, yy, ww, hh]]
                target_possible_position = [temp, [xx, yy, ww, hh]]
                return target_possible_position

    def find_best_contours(self, target_position):
        if len(target_position) > 0:
            first_item = itemgetter(0)
            target_position = sorted(target_position, key=first_item)
            for i in range(round(len(target_position) / 4)):
                temp1 = target_position[i]
                xx = temp1[1][0]
                yy = temp1[1][1]
                ww = temp1[1][2]  # width of the target
                hh = temp1[1][3]  # hieght of the target
                cv2.rectangle(self.image, (xx, yy), (xx + ww, yy + hh), (0, 255, 0), 2)
            # temp_array[1][0]=xx temp_array[1][1]=yy temp_array[1][2]=ww temp_array[1][3]=hh
            cv2.rectangle(self.image, (target_position[0][1][0], target_position[0][1][1]),
                          (target_position[0][1][0] + target_position[0][1][2],
                           target_position[0][1][1] + target_position[0][1][3]),
                          (0, 0, 255), 2)
            # return estimated value which will use in tracker
            return \
                target_position[0][1][0], \
                target_position[0][1][1], \
                target_position[0][1][2], \
                target_position[0][1][3]


if __name__ == "__main__":
    # Main
    cam = cv2.VideoCapture("data1.mp4")
    ob = Detection()
    while True:
        ret_val, frame = cam.read()
        if not ret_val:
            print("can not open the video")
            break
        # detection
        ob.image = frame
        ob.first_filter()
        binary_image_1 = ob.filters((0, 0, 0), (255, 100, 130))
        conts = ob.find_contours(binary_image_1)
        p = Pool(processes=3)
        green_cont = p.map(ob.Green_contours, conts)        
        #to remove NONe statements
        green_cont = [x for x in green_cont if x is not None]
        target_position = green_cont
        target_locations = ob.find_best_contours(target_position)
        # Get image from camera
        Output_image = ob.image
        # Show image's windows
        cv2.imshow('webcam', Output_image)
        cv2.waitKey(1)
    cam.release()

在这段代码中,我使用了Multiprocessing.pool()而不是 for 循环。 所以我认为它应该更有效率。 但它太慢了。 它每 5 分钟更新一次每一帧。

  1. 我的代码有问题吗?
  2. 有没有办法让我的代码更快?
  3. 如何使用多处理来加速代码。
  4. 我的问题清楚吗? 因为我尝试了很多来问一个明确的问题!

谢谢

有一个已知的cv2 问题会破坏 OSX 上的多处理。 解决方法是配置要使用“spawn”而不是“fork”创建的新进程:

multiprocessing.set_start_method('spawn')

在创建多处理池之前添加上面的代码行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM