Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.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_Algorithm_Numpy_Edge Detection - Fatal编程技术网

Python 矩阵存储图像的边缘检测

Python 矩阵存储图像的边缘检测,python,algorithm,numpy,edge-detection,Python,Algorithm,Numpy,Edge Detection,我以二维数组的形式表示图像。我有这张照片: 如何获得直接位于灰色区域边界上的像素并对其着色 我想分别得到绿色和红色矩阵元素的坐标。矩阵上只有白色、黑色和灰色区域。也许有更优雅的方法。。。 但是,如果您的数组是一个numpy数组,其维度(N,N)(灰度),您可以执行以下操作 import numpy as np # assuming black -> 0 and white -> 1 and grey -> 0.5 black_reg = np.where(a < 0

我以二维数组的形式表示图像。我有这张照片:

如何获得直接位于灰色区域边界上的像素并对其着色


我想分别得到绿色和红色矩阵元素的坐标。矩阵上只有白色、黑色和灰色区域。

也许有更优雅的方法。。。 但是,如果您的数组是一个
numpy
数组,其维度
(N,N)
(灰度),您可以执行以下操作

import numpy as np

# assuming black -> 0 and white -> 1 and grey -> 0.5
black_reg = np.where(a < 0.1, a, 10)
white_reg = np.where(a > 0.9, a, 10)

xx_black,yy_black = np.gradient(black_reg)
xx_white,yy_white = np.gradient(white_reg)

# getting the coordinates
coord_green = np.argwhere(xx_black**2 + yy_black**2>0.2)
coord_red   = np.argwhere(xx_white**2 + yy_white**2>0.2)
将numpy导入为np
#假设黑色->0和白色->1和灰色->0.5
黑色_reg=np.式中(a<0.1,a,10)
white_reg=np.式中(a>0.9,a,10)
xx_黑色,yy_黑色=np.梯度(黑色)
xx_白色,yy_白色=np.梯度(白色)
#获取坐标
坐标绿色=np.argwhere(xx_黑色**2+yy_黑色**2>0.2)
坐标红色=np.argwhere(xx_白色**2+yy_白色**2>0.2)

数字
0.2
只是一个阈值,需要调整。

我认为您可能正在寻找灰度图像的边缘检测方法。有很多方法可以做到这一点。也许这会有帮助。要区分白色和灰色之间的边缘以及黑色和灰色之间的边缘,请尝试使用局部平均强度。

虽然普隆塞的答案可能相当直接,但我认为它在尖锐和薄边缘时会失败。尽管如此,我建议你使用他的部分方法作为预处理。
在第二步中,您希望使用。根据的文件,它是

marching cubes算法的一个特例(Lorensen、William和 Harvey E.Cline.Marching Cubes:高分辨率3D曲面 构造算法.计算机图形学(SIGGRAPH87会议录) 1987年7月21日(4),第163-170页

甚至还有一个Python实现作为包的一部分。我已经成功地使用了这个算法(尽管是我自己的Fortran实现),用于通信工程中眼图的边缘检测

Ad 1:预处理
创建图像的副本,并使其仅为两种颜色,例如黑色/白色。坐标保持不变,但您要确保算法能够正确地做出“是/否”决策,而不受图像矩阵表示中使用的值的影响

Ad 2:边缘检测
Wikipedia以及各种博客为您提供了各种语言的算法的详细信息,因此我将不详细介绍。不过,让我给您一些实用的建议:

  • 您的图像底部有开放的边界。您可以人工添加另一行像素(黑色或灰色以绑定白色/灰色区域),而不是修改算法
  • 起始点的选择至关重要。如果要处理的图像不太多,我建议您手动选择。否则您需要定义规则。由于Marching Squares算法可以从有界区域内的任何位置开始,因此您可以选择给定颜色/值的任何像素来检测相应的边缘(它最初将开始朝一个方向行走以找到一条边)
  • 该算法返回精确的二维位置,例如(x/y)-元组
    • 遍历列表,并通过指定不同的值或值对相应的像素着色
    • 创建以选择矩阵的各个部分,并指定对应于不同颜色(例如绿色或红色)的值
  • 最后:一些后期处理
    我建议在图像中添加一个人工边界。这有两个优点: 1.行进方块算法是现成的。
    2.无需区分图像边界和图像中两个区域之间的界面。设置彩色边缘后,只需删除人工边界——这将删除图像边界处的彩色线。

    以下内容有望满足您的需要(或至少帮助)。其思想是使用基于阈值的逻辑检查将各个区域分割。然后,可以使用numpy roll在x和y方向上移动像素并进行比较以检测这些区域之间的边缘

    import matplotlib.pyplot as plt
    import numpy as np
    import scipy as sp
    from skimage.morphology import closing
    
    thresh1 = 127
    thresh2 = 254
    
    #Load image
    im = sp.misc.imread('jBD9j.png')
    
    #Get threashold mask for different regions
    gryim = np.mean(im[:,:,0:2],2)
    region1 =  (thresh1<gryim)
    region2 =  (thresh2<gryim)
    nregion1 = ~ region1
    nregion2 = ~ region2
    
    #Plot figure and two regions
    fig, axs = plt.subplots(2,2)
    axs[0,0].imshow(im)
    axs[0,1].imshow(region1)
    axs[1,0].imshow(region2)
    
    #Clean up any holes, etc (not needed for simple figures here)
    #region1 = sp.ndimage.morphology.binary_closing(region1)
    #region1 = sp.ndimage.morphology.binary_fill_holes(region1)
    #region1.astype('bool')
    #region2 = sp.ndimage.morphology.binary_closing(region2)
    #region2 = sp.ndimage.morphology.binary_fill_holes(region2)
    #region2.astype('bool')
    
    #Get location of edge by comparing array to it's 
    #inverse shifted by a few pixels
    shift = -2
    edgex1 = (region1 ^ np.roll(nregion1,shift=shift,axis=0))
    edgey1 = (region1 ^ np.roll(nregion1,shift=shift,axis=1))
    edgex2 = (region2 ^ np.roll(nregion2,shift=shift,axis=0)) 
    edgey2 = (region2 ^ np.roll(nregion2,shift=shift,axis=1))
    
    #Plot location of edge over image
    axs[1,1].imshow(im)
    axs[1,1].contour(edgex1,2,colors='r',lw=2.)
    axs[1,1].contour(edgey1,2,colors='r',lw=2.)
    axs[1,1].contour(edgex2,2,colors='g',lw=2.)
    axs[1,1].contour(edgey2,2,colors='g',lw=2.)
    plt.show()
    
    导入matplotlib.pyplot作为plt
    将numpy作为np导入
    将scipy作为sp导入
    从skimage.com导入关闭
    阈值1=127
    阈值2=254
    #加载图像
    im=sp.misc.imread('jBD9j.png')
    #获取不同区域的阈值遮罩
    gryim=np.平均值(im[:,:,0:2],2)
    
    region1=(thresh1基本上,根据pyStarter的建议,使用scikit图像中的marching square算法,可以使用以下代码提取所需的轮廓:

    import matplotlib.pyplot as plt
    import numpy as np
    import scipy as sp
    from skimage import measure
    import scipy.ndimage as ndimage
    from skimage.color import rgb2gray
    from pprint import pprint
    #Load image
    im = rgb2gray(sp.misc.imread('jBD9j.png'))
    
    n, bins_edges = np.histogram(im.flatten(),bins = 100)
    # Skip the black area, and assume two distinct regions, white and grey
    max_counts = np.sort(n[bins_edges[0:-1] > 0])[-2:]
    thresholds = np.select(
        [max_counts[i] == n for i in range(max_counts.shape[0])],
        [bins_edges[0:-1]] * max_counts.shape[0]
    )
    # filter our the non zero values
    thresholds = thresholds[thresholds > 0] 
    
    
    fig, axs = plt.subplots()
    # Display image
    axs.imshow(im, interpolation='nearest', cmap=plt.cm.gray)
    colors = ['r','g']
    for i, threshold in enumerate(thresholds):
        contours = measure.find_contours(im, threshold)
    
        # Display  all contours found for this threshold
        for n, contour in enumerate(contours):
            axs.plot(contour[:,1], contour[:,0],colors[i], lw = 4)
    
    axs.axis('image')
    axs.set_xticks([])
    axs.set_yticks([])        
    plt.show()
    
    !


    然而,从你的图像中没有明确的灰色区域,所以我在图像中取了两个最大的强度计数并对它们进行了阈值。有点令人不安的是白色区域中间的红色区域,但是我认为这可以用直方图过程中的容器数量来调整。s Ed Smith做到了。

    有一个非常简单的解决方案:根据定义,任何具有白色和灰色邻域的像素都位于“红色”边缘,而灰色和黑色邻域位于“绿色”边缘边缘。
    skimage.filters.rank
    中的最大/最小过滤器返回最亮/最暗的邻域,以及具有最亮/最暗邻域(分别为白色/灰色或灰色/黑色)的像素掩码的二进制组合生成边缘

    结果:

    有效的解决方案:

    import numpy
    import skimage.filters.rank
    import skimage.morphology
    import skimage.io
    
    # convert image to a uint8 image which only has 0, 128 and 255 values
    # the source png image provided has other levels in it so it needs to be thresholded - adjust the thresholding method for your data
    img_raw = skimage.io.imread('jBD9j.png', as_grey=True)
    img = numpy.zeros_like(img, dtype=numpy.uint8)
    img[:,:] = 128
    img[ img_raw < 0.25 ] = 0
    img[ img_raw > 0.75 ] = 255
    
    # define "next to" - this may be a square, diamond, etc
    selem = skimage.morphology.disk(1)
    
    # create masks for the two kinds of edges
    black_gray_edges = (skimage.filters.rank.minimum(img, selem) == 0) & (skimage.filters.rank.maximum(img, selem) == 128)
    gray_white_edges = (skimage.filters.rank.minimum(img, selem) == 128) & (skimage.filters.rank.maximum(img, selem) == 255)
    
    # create a color image
    img_result = numpy.dstack( [img,img,img] )
    
    # assign colors to edge masks
    img_result[ black_gray_edges, : ] = numpy.asarray( [ 0, 255, 0 ] )
    img_result[ gray_white_edges, : ] = numpy.asarray( [ 255, 0, 0 ] )
    
    imshow(img_result)
    
    导入numpy
    导入skimage.filters.rank
    进口撇渣
    导入skimage.io
    #将图像转换为只有0、128和255个值的uint8图像
    #提供的源png图像中有其他级别,因此需要对其进行阈值设置-调整数据的阈值设置方法
    img_raw=skimage.io.imread('jBD9j.png',as_grey=True)
    img=numpy.zeros_like(img,dtype=