使用Numpy进行边缘查找

zzlelutf  于 2022-11-10  发布在  其他
关注(0)|答案(2)|浏览(135)

使用NumPy 1D搜索在类似模具的黑白图像中查找边缘,例如

不确定如何循环一维数组以正确创建布尔掩码。查看了相当多的资源&堆栈,它们没有显式地涵盖这类基本操作。
如有任何建议,敬请指教。这是伪代码。


# Pseudocode for 1D array search.

nrows, ncols = img.shape[:2]
nrows = nrows-1     #avoid index error
ncols = ncols-1

    # i+1 pixel index wanted here
outedges_row = (img[nrows][i] == 0) & (img[nrows][i+1] == 255)  
outedges_col = (img[ncols][i] == 0) & (img[ncols][i+1] == 255)

    # i pixel index wanted here
inedges_row = (img[nrows][i] == 255) & (img[nrows][i+1] == 0)
inedges_col = (img[ncols][i] == 255) & (img[ncols][i+1] == 0)

    # display outline of shapes
edges = np.unique(outedges_row & outedges_col & inedges_col & inedges_row)
img2 = np.copy(img)
img2[edges]
cv.imshow('',img2)

即使是一个非常简单的外形轮廓,对我来说也是非常有价值的学习。
编辑:预期输出

jutyujz0

jutyujz01#

“边”像素的特征是一个简单的属性:它是黑色的,并且它的邻居中至少有一个是白色的(您可以在4个或8个相连的邻居中进行选择)。
这是相当容易实现的。在图像的侧面,可以认为“外部”像素是白色的。

qv7cva1a

qv7cva1a2#

典型的边缘检测方法是取“导数”或与“边缘检测核”(如Sobel、高斯拉普拉斯等)进行卷积。
例如,这给出了一个非常简单的水平导数:


# kernel: (-1, 1)

dx = img[:, 1:] - img[:, :-1]

二阶运算符:


# kernel: (-1, 2, -1)

dx = -img[:, 2:] + 2 * img[:, 1:-1] - img[:, :-2]

...顺便说一句,它创建了所有垂直边缘的Map。
要转换为布尔图,可以对结果进行阈值操作:

edge = dx > THRESHOLD

高斯核的典型拉普拉斯函数:

edge = (
    0 * img[:-2, :-2]  + -1 * img[:-2, 1:-1]  +  0 * img[:-2, 2:]  +
   -1 * img[1:-1, :-2] +  4 * img[1:-1, 1:-1] + -1 * img[1:-1, 2:] +
    0 * img[2:, :-2]   + -1 * img[2:, 1:-1]   +  0 * img[2:, 2:]  
)

如果你不局限于线性运算符,你甚至可以做像edges = abs(dx) + abs(dy)这样的事情。只是要小心相移。
@Yves建议的另一种“非线性”方法是使用4-连接的邻居。一种可能的实施方式:

img = (img >= 128).astype(np.uint8)
img_p = np.pad(img, 1, mode='edge')

connectivity = (
    0 * img_p[ :-2, :-2] +  1 * img_p[ :-2, 1:-1] +  0 * img_p[ :-2, 2:] +
    1 * img_p[1:-1, :-2] +  0 * img_p[1:-1, 1:-1] +  1 * img_p[1:-1, 2:] +
    0 * img_p[2:,   :-2] +  1 * img_p[2:,   1:-1] +  0 * img_p[2:,   2:]
)

edge = (img == 1) & (connectivity >= 1) & (connectivity < 4)

相关问题