Python 区域生长蟒蛇

Python 区域生长蟒蛇,python,opencv,Python,Opencv,我正在用python实现区域增长算法。但当我在输出上运行这段代码时,我得到了没有错误的黑色图像。对输入图像使用CV阈值函数,对于种子值,我使用鼠标单击将x、y值存储在元组中 def get8n(x, y, shape): out = [] if y-1 > 0 and x-1 > 0: out.append( (y-1, x-1) ) if y-1 > 0 : out.append( (y-1, x)) if y-

我正在用python实现区域增长算法。但当我在输出上运行这段代码时,我得到了没有错误的黑色图像。对输入图像使用CV阈值函数,对于种子值,我使用鼠标单击将x、y值存储在元组中

def get8n(x, y, shape):
    out = []
    if y-1 > 0 and x-1 > 0:
        out.append( (y-1, x-1) )
    if y-1 > 0 :
        out.append( (y-1, x))
    if y-1 > 0 and x+1 < shape[1]:
        out.append( (y-1, x+1))
    if x-1 > 0:
        out.append( (y, x-1))
    if x+1 < shape[1]:
        out.append( (y, x+1))
    if y+1 < shape[0] and x-1 > 0:
        out.append( ( y+1, x-1))
    if y+1 < shape[0] :
        out.append( (y+1, x))
    if y+1 < shape[0] and x+1 < shape[1]:
       out.append( (y+1, x+1))
    return out

def region_growing(img, seed):
    list = []
    outimg = np.zeros_like(img)

    list.append((seed[0], seed[1]))
    while(len(list)):
        pix = list[0]
        outimg[pix[0], pix[1]] = 255
        for coord in get8n(pix[0], pix[1], img.shape):
            if img[coord[0], coord[1]] > 0:
                outimg[coord[0], coord[1]] = 255
                list.append((coord[0], coord[1]))
        list.pop(0)
    return outimg

def on_mouse(event, x, y, flags, params): 
    if event == cv2.EVENT_LBUTTONDOWN: 
        print 'Seed: ' + str(x) + ', ' + str(y) 
        clicks.append((y,x)) 

clicks = []
image = cv2.imread('lena.jpg', 0) 
ret, img = cv2.threshold(image, 200, 255, cv2.THRESH_BINARY) 
cv2.namedWindow('Input') 
cv2.setMouseCallback('Input', on_mouse, 0, ) 
cv2.imshow('Input', img) 
cv2.waitKey() 
seed = clicks[-1] 
cv2.imshow('Region Growing', region_growing(img, seed)) 
cv2.waitKey() 
cv2.destroyAllWindows()
def get8n(x,y,形状): out=[] 如果y-1>0和x-1>0: out.append((y-1,x-1)) 如果y-1>0: out.append((y-1,x)) 如果y-1>0且x+1<形状[1]: out.append((y-1,x+1)) 如果x-1>0: out.append((y,x-1)) 如果x+1<形状[1]: out.append((y,x+1)) 如果y+1<形状[0]和x-1>0: out.append((y+1,x-1)) 如果y+1<形状[0]: out.append((y+1,x)) 如果y+1<形状[0]和x+1<形状[1]: out.append((y+1,x+1)) 返回 def区域_生长(img,种子): 列表=[] outimg=np.类零(img) list.append((种子[0],种子[1])) while(len(list)): pix=列表[0] outimg[pix[0],pix[1]]=255 对于get8n中的坐标(pix[0],pix[1],img.shape): 如果img[coord[0],coord[1]]>0: outimg[coord[0],coord[1]]=255 list.append((坐标[0],坐标[1])) list.pop(0) 返回 鼠标上的def(事件、x、y、标志、参数): 如果event==cv2.event\u LBUTTONDOWN: 打印“种子:'+str(x)+','+str(y) 单击。追加((y,x)) 点击次数=[] image=cv2.imread('lena.jpg',0) ret,img=cv2.threshold(图像,200255,cv2.THRESH_二进制) cv2.namedWindow(“输入”) cv2.setMouseCallback('Input',在鼠标上,0,) cv2.imshow(“输入”,img) cv2.waitKey() 种子=点击次数[-1] cv2.imshow(“区域增长”,区域增长(img,种子)) cv2.waitKey() cv2.destroyAllWindows()
我在使用get8n()函数时遇到了一些问题,所以我重写了它。我相信下面的代码符合您的要求。region_growing()函数中有两行被注释掉了。如果取消注释,它们将显示处理过程中发生的动画。这是一种可视化代码的好方法,可以让您了解失败的地方

另外,在代码中,您可以将已经处理过的像素添加到“待处理”列表中。这导致了一个无限循环。我添加了一个检查,防止已处理的像素被添加回列表中

import cv2
import numpy as np

def get8n(x, y, shape):
    out = []
    maxx = shape[1]-1
    maxy = shape[0]-1
    
    #top left
    outx = min(max(x-1,0),maxx)
    outy = min(max(y-1,0),maxy)
    out.append((outx,outy))
    
    #top center
    outx = x
    outy = min(max(y-1,0),maxy)
    out.append((outx,outy))
    
    #top right
    outx = min(max(x+1,0),maxx)
    outy = min(max(y-1,0),maxy)
    out.append((outx,outy))
    
    #left
    outx = min(max(x-1,0),maxx)
    outy = y
    out.append((outx,outy))
    
    #right
    outx = min(max(x+1,0),maxx)
    outy = y
    out.append((outx,outy))
    
    #bottom left
    outx = min(max(x-1,0),maxx)
    outy = min(max(y+1,0),maxy)
    out.append((outx,outy))
    
    #bottom center
    outx = x
    outy = min(max(y+1,0),maxy)
    out.append((outx,outy))
    
    #bottom right
    outx = min(max(x+1,0),maxx)
    outy = min(max(y+1,0),maxy)
    out.append((outx,outy))
    
    return out

def region_growing(img, seed):
    seed_points = []
    outimg = np.zeros_like(img)
    seed_points.append((seed[0], seed[1]))
    processed = []
    while(len(seed_points) > 0):
        pix = seed_points[0]
        outimg[pix[0], pix[1]] = 255
        for coord in get8n(pix[0], pix[1], img.shape):
            if img[coord[0], coord[1]] != 0:
                outimg[coord[0], coord[1]] = 255
                if not coord in processed:
                    seed_points.append(coord)
                processed.append(coord)
        seed_points.pop(0)
        #cv2.imshow("progress",outimg)
        #cv2.waitKey(1)
    return outimg

def on_mouse(event, x, y, flags, params):
    if event == cv2.EVENT_LBUTTONDOWN:
        print 'Seed: ' + str(x) + ', ' + str(y), img[y,x]
        clicks.append((y,x))
        
clicks = []
image = cv2.imread('lena.bmp', 0)
ret, img = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY)
cv2.namedWindow('Input')
cv2.setMouseCallback('Input', on_mouse, 0, )
cv2.imshow('Input', img)
cv2.waitKey()
seed = clicks[-1]
out = region_growing(img, seed)
cv2.imshow('Region Growing', out)
cv2.waitKey()
cv2.destroyAllWindows()
以下是单击她帽子左侧时的结果:


Add()用于Python3.x like:print(“Some things”)

上述解决方案在概念上是正确的,但从数值角度来看,它们包含一些严重的问题,使它们在像素数量上的顺序为N^2。如果可以将信息存储在提供随机访问的数组中,则无需搜索列表中的像素,还可以对连接功能进行cythonized。另外,如果能够提供您自己的相似性函数也会很好

因此,我建议在Jupyter noteboook中运行一个改进的、肯定更快的版本:

导入的第一个单元格:

import numpy as np
import cv2

%pylab inline 

%load_ext Cython
第二个单元格(不合并第一个单元格):

可以使用与前面相同的逻辑从另一个单元调用它:

def on_mouse(event, x, y, flags, params):
    if event == cv2.EVENT_LBUTTONDOWN:
        print( 'Seed: ' + str(x) + ', ' + str(y), img[y,x])
        clicks.append((int(y), int(x)))
        
clicks = []
image = cv2.imread('lena.bmp', 0)
ret, img = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY)
cv2.namedWindow('Input')
cv2.setMouseCallback('Input', on_mouse, 0, )
cv2.imshow('Input', img)
cv2.waitKey()
cv2.destroyAllWindows()

seed = clicks
out = region_growing(img, seed)
cv2.imshow('Region Growing', out)
cv2.waitKey()
cv2.destroyAllWindows()
有一些小的功能差异。输出中的区域由种子处原始图像的值或可选颜色贴图中的值标记。colormap需要指定给定als无符号8位整数的RGB颜色。也可以通过定制的测试功能,替换:

test = lambda seed_x, seed_y, x, y, img, outimg : img[x,y] != 0
例如:

test = lambda seed_x, seed_y, x, y, img, outimg : abs(img[x,y] - img[seed_x, seed_y]) < 4

由于您询问的是读取和显示图像的问题,您能否包括读取/操作输入图像和显示输出图像的代码?在鼠标上有输入图像
def的所有代码(事件、x、y、标志、参数):如果event==cv2.event\u LBUTTONDOWN:print'Seed:'+str(x)+','+str y)clicks.append((y,x))点击=[]图像=cv2.imread('lenna.jpg',0)ret,img=cv2.threshold(图像,200255,cv2.THRESH_BINARY)cv2.namedWindow('Input')cv2.setMouseCallback('Input',on_mouse,0,)cv2.imshow('Input',img)cv2.waitKey()seed=点击[-1]cv2.imshow('Region growth',Region_growth(img,seed))cv2.waitKey()
通过正确的格式将代码添加到问题中-这是不可读的。您希望您的代码做什么?现在,它似乎在您上次单击的位置绘制了一个带有白色像素的空白图像。如果您单击输入的白色区域,它将进入无限循环。另一方面,这意味着输出图像不是b缺少,但只有一个白色像素。我想通过种子像素的所有相邻像素(单击)将值大于0的像素设置为255。如果相邻像素大于0,则继续此操作。并将它们指定给将作为输出图像的区域谢谢您的帮助。我复制了您编写的代码,得到了与上面相同的结果,在单击的位置有白色像素。您可以显示您的输出结果吗?可能我做错了。添加了一个结果图像。如果您仍然有问题,我建议您在种子位置打印图像值,以确保您没有混淆x和y坐标。这些结果来自我发布的确切代码。为什么“img[coord[0],coord[1]!=0”包含或其功能是什么?或者为什么像素不能为黑色?区域生长函数在已设置阈值的图像上运行,这意味着值为0或255。因此,如果img[coord[0],coord[1]==255,则该行可能为
。如果img[coord[0],coord[1]==255,则为
>0
。只是检查像素是否为黑色,因为这是本例中的边界条件。我认为最好不要为候选种子点列表重载内置的
list
函数。我将建议进行编辑
test = lambda seed_x, seed_y, x, y, img, outimg : img[x,y] != 0
test = lambda seed_x, seed_y, x, y, img, outimg : abs(img[x,y] - img[seed_x, seed_y]) < 4
def get_8_connected(x, y, shape):
    xmax = shape[0]-1
    ymax = shape[1]-1
    
    connected_pixels = list()
    
    for dx in range(3):
        for dy in range(3):
            connected_pixel_x  = x + dx - 1
            connected_pixel_y = y + dy - 1
            if connected_pixel_x < 0 or connected_pixel_x > xmax or \
                connected_pixel_y < 0 or connected_pixel_y > ymax or \
                (connected_pixel_x == x and connected_pixel_y == y):
                    pass
            else:
                connected_pixels.append((connected_pixel_x,connected_pixel_y))
    return  connected_pixels```