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以及各种博客为您提供了各种语言的算法的详细信息,因此我将不详细介绍。不过,让我给您一些实用的建议:
- 遍历列表,并通过指定不同的值或值对相应的像素着色
- 创建以选择矩阵的各个部分,并指定对应于不同颜色(例如绿色或红色)的值
我建议在图像中添加一个人工边界。这有两个优点: 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=