如何通过多处理有效地迭代分割后的图像?

时间:2019-06-24 15:04:00

标签: python opencv multiprocessing

enter image description here enter image description here我正在学习信息系统工程,需要在我的副业中突然使用多线程/处理,但是我们从未在大学里教过这个,所以我对此一无所知。最近几天我只读了一些介绍。有了这个帮助,我什至得到了一些简单的测试程序来提高性能,但我无法完成此任务。

我有一幅图片,其对象的边缘为白点(数组中的值为255)。 现在我需要知道这些点在阵列中的位置。

因为图像是非常大的数组,所以我需要针对树莓派对其进行优化,因此我需要在进行多处理时对此进行编程,因为在测试中,我仅在1个内核上获得了25%的CPU CPU使用率,而事实并非如此足以进行实时视频处理。

def test_multi(self):
pool = mp.Pool(processes=4)
test_prep = self.test_prep.copy()
y, x = test_prep.shape
columns = []
for i in range(4):
    c = test_prep[0:y, 0:int(x/4)*(i+1)]
    c = copy(c)
    columns.append(c)
results = [pool.apply_async(search, args=(c,)) for c in columns]
for r in results:
    print(r.get())

def search(picture):
ys, xs = picture.shape
dots = []
for x in range(xs):
    for y in range(ys):
        if picture[y][x] == 255:
            dots.append((x, y))
return dots

但是在结果列表中,我可以看到并没有真正并行完成,因为有4个条目,每个条目只是最后一个,再加上下一个图像部分的一些新点。因此,我认为流程会等待一个流程完成,并且只会添加到同一列表中,但是我希望在此之后加入4个单独的列表。而且,它所花费的时间比仅以老式方式遍历图片要长得多。那是什么问题呢?

我尝试使用多线程切换,但是有人说GIL不允许在单独的内核上进行分发。

我尝试阅读多处理文档,发现了很多可能性,例如队列,管理器,池和管道,但是现在我真的不知道它们之间的区别以及何时使用它们。

我想要在图像的4个不同列中具有点坐标的4个列表,并且我希望并行分布在4个核上的搜索功能被执行。或另一种允许搜索1920 * 1080图像的速度快于半秒的过程。

更新:

正如Mark Setchell所建议的那样,我现在正在使用cv2.findContour(),但是正如我所说的,有时它会将一个轮廓检测为多个轮廓,因此我添加了一个例程,该例程将轮廓的中间部分非常相似,如下所示:

def search(image):
    ret, thresh = threshold(image, 0, 255, 0)
    contours, hierarchy = findContours(thresh, RETR_TREE, CHAIN_APPROX_SIMPLE)
    objects = []
    for c in contours:
        objects.append(middle(c))
    any_neighbors = False
    while not any_neighbors:
        objects, any_neighbors = combine(objects)
    return objects

def combine(objects):
    ret = objects
    any_neighbors = False
    for o1 in objects:
        for o2 in objects:
            if is_neighbor(o1, o2):
                ret.remove(o1)
                any_neighbors = True
    return ret, any_neighbors

def middle(contour):
    xs = 0
    ys = 0
    size = len(contour)
    for c in contour:
        xs += c[0][0]
        ys += c[0][1]
    xs = int(xs/size)
    ys = int(ys/size)
    return xs, ys

def is_neighbor(p1, p2):
    return p1[0] - th <= p2[0] <= p1[0] + th and p1[1] - th <= p2[1] <= p1[1] + th

这可能仍然不是完美的,但是今天就完成了。我明天回来,检查性能提升是否足够还是我仍然需要

1 个答案:

答案 0 :(得分:0)

该过程已经与程序的其他部分一样快。这就是为什么不再需要多处理的原因。