contour_rect_slow 在值为 0 和 1 的像素之间的边界处绘制单线。contour_rect 是一个更紧凑的版本,将较长的线连接到一条线。
代码:
import numpy as np
k = []
for s in [2103, 1936, 2247, 2987]:
np.random.seed(s)
k.append(np.random.randint(0, 2, size=(2,6)))
arr = np.hstack([np.vstack(k)[:, :-1], np.vstack(k).T[::-1].T ])
image = np.zeros(shape=(arr.shape[0]+2, arr.shape[1]+2))
image[1:-1, 1:-1] = arr[::1]
# image[1, 1] = 1
import matplotlib.pyplot as plt
plt.imshow(image, interpolation="none", cmap="Blues")
def contour_rect_slow(im):
"""Clear version"""
pad = np.pad(im, [(1, 1), (1, 1)]) # zero padding
im0 = np.abs(np.diff(pad, n=1, axis=0))[:, 1:]
im1 = np.abs(np.diff(pad, n=1, axis=1))[1:, :]
lines = []
for ii, jj in np.ndindex(im0.shape):
if im0[ii, jj] == 1:
lines += [([ii-.5, ii-.5], [jj-.5, jj+.5])]
if im1[ii, jj] == 1:
lines += [([ii-.5, ii+.5], [jj-.5, jj-.5])]
return lines
def contour_rect(im):
"""Fast version"""
lines = []
pad = np.pad(im, [(1, 1), (1, 1)]) # zero padding
im0 = np.abs(np.diff(pad, n=1, axis=0))[:, 1:]
im1 = np.abs(np.diff(pad, n=1, axis=1))[1:, :]
im0 = np.diff(im0, n=1, axis=1)
starts = np.argwhere(im0 == 1)
ends = np.argwhere(im0 == -1)
lines += [([s[0]-.5, s[0]-.5], [s[1]+.5, e[1]+.5]) for s, e
in zip(starts, ends)]
im1 = np.diff(im1, n=1, axis=0).T
starts = np.argwhere(im1 == 1)
ends = np.argwhere(im1 == -1)
lines += [([s[1]+.5, e[1]+.5], [s[0]-.5, s[0]-.5]) for s, e
in zip(starts, ends)]
return lines
lines = contour_rect(image)
for line in lines:
plt.plot(line[1], line[0], color='r', alpha=1)
警告:这明显慢然后mpl.contour对于大图像..