Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何通过多处理有效地迭代分割图像?_Python_Opencv_Multiprocessing - Fatal编程技术网

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

Python 如何通过多处理有效地迭代分割图像?,python,opencv,multiprocessing,Python,Opencv,Multiprocessing,我正在学习信息系统工程,需要在我的兼职中突然使用多线程/处理,但我们在大学里从来没有教过这个,所以我对此一无所知。过去几天我只看了一些介绍。在这种帮助下,我甚至得到了一些简单的测试程序,以更好地执行,但我无法完成这项任务 我有一张图片,对象的边缘是白点(数组中的值为255)。 现在我需要知道这些点在数组中的位置 因为图像是相当大的阵列,我需要为raspberry pi优化它,我需要在编程时考虑多处理,因为在一次测试中,我在1核以上的pi上只获得了25%的CPU使用率,这还不足以进行实时视频处理

我正在学习信息系统工程,需要在我的兼职中突然使用多线程/处理,但我们在大学里从来没有教过这个,所以我对此一无所知。过去几天我只看了一些介绍。在这种帮助下,我甚至得到了一些简单的测试程序,以更好地执行,但我无法完成这项任务

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

因为图像是相当大的阵列,我需要为raspberry pi优化它,我需要在编程时考虑多处理,因为在一次测试中,我在1核以上的pi上只获得了25%的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
def搜索(图像):
ret,thresh=阈值(图像,0,255,0)
等高线,层次=已找到的等高线(阈值,重树,近似链)
对象=[]
对于等高线中的c:
对象。追加(中间(c))
任何邻居=错误
虽然不是任何_邻居:
对象,任意_近邻=组合(对象)
返回对象
def联合收割机(对象):
ret=对象
任何邻居=错误
对于对象中的o1:
对于对象中的o2:
如果是邻居(o1,o2):
重新移除(o1)
任何邻居=真
返回ret,任何邻居
def中间(轮廓):
xs=0
ys=0
尺寸=透镜(轮廓)
对于轮廓中的c:
xs+=c[0][0]
ys+=c[0][1]
xs=int(xs/size)
ys=int(ys/尺寸)
返回xs,ys
def是_邻居(p1、p2):

返回p1[0]-th该过程与程序的其他部分一样快。这就是为什么不再需要多处理的原因。

当你有了点的位置时,你打算如何处理它们?图像中还有什么,或是黑色背景上的点?请展示你的图片。背景是黑色的。我用这个位置来找出哪些点是相邻的,这样我就可以把它们组合成更大的物体。我添加的图像是我使用的测试图像。这就是边缘检测之前的样子,但它是相同的黑色背景和白色边缘。对于给定的图像,答案是有3个点,还是有29264个白色像素?作为下一个处理阶段,您打算如何处理该答案?总体答案是“a、b、c”位置有3个对象。但我想改进的任务是返回一个包含白色像素位置的元组的元组,例如white_pixels=((400312),(405316),…)这很容易,但我无法将图像分割成多个进程/核心同时进行。我怀疑您可能是在错误的树上首先查找点,然后运行
for
循环。你看过OpenCV的
findContours()