如何从二值图像中提取裂纹轮廓?

问题描述 投票:0回答:1

我的图片是这样的; original images

我想像这样提取轮廓: correct crack contour

我的Python代码是:

import matplotlib.pyplot as plt
import matplotlib
matplotlib.rc("font", family='SimHei')
import numpy as np
import cv2
from matplotlib.colors import ListedColormap
im = cv2.imread(r'Desktop\file\lunwen\test\image1\1381_8.jpg', cv2.IMREAD_GRAYSCALE) im = cv2.threshold(im, 128, 1, cv2.THRESH_BINARY)[1]
result = np.zeros_like(im, dtype='uint32')
diff = np.diff(im.astype(np.int8), axis=1)
y, x_min = np.nonzero(diff == 1) 
_, x_max = np.nonzero(diff == -1)
width_list = x_max - x_min
print('max_width:', np.max(width_list))
print('min_width:', np.min(width_list))
print('mean_width:', np.mean(width_list))
for i in range(x_min.size):
    result[y[i], x_min[i]:x_max[i]] = width_list[i]
viridis = plt.cm.viridis
newcolors = viridis(np.linspace(0, 1, 256))
newcolors[0, :] = np.array([1, 1, 1, 1])
newcmp = ListedColormap(newcolors)
plt.figure(figsize=(8, 6))
plt.title('Crack Contour')
cax = plt.imshow(result, cmap=newcmp)
plt.axis('off')
cbar = plt.colorbar(cax, fraction=0.03, pad=0.06,label='Width', orientation='vertical')
plt.savefig('result_with_colorbar.png', bbox_inches='tight', pad_inches=0.1)
plt.show()

当我使用上面的“原始”图像时,它似乎不起作用。有一个错误,比如

Traceback (most recent call last):
  File "E:\Test.py", line 30, in <module>
    width_list = x_max - x_min  
ValueError: operands could not be broadcast together with shapes (797,) (800,) 
python numpy opencv
1个回答
0
投票

可能有更简单的方法,但我们要小心

assert

import numpy as np
from PIL import Image


image = np.array(
    Image.open(fp='cracked.jpg').convert(mode='1')
)

# Add an outer black boundary for sane boundary conditions
black_col = np.zeros_like(image[:, :1])
image = np.hstack((black_col, image, black_col))

diff = np.diff(a=image.astype(np.int8), axis=1)
diff_y, diff_x = diff.nonzero()

diff_y = diff_y.reshape((-1, 2))
assert np.all(diff_y[:, 0] == diff_y[:, 1]), 'Start/stop on same row'

diff_x = diff_x.reshape((-1, 2))
assert np.all(diff_x[:, 0] < diff_x[:, 1]), 'Monotonic start/stop'

assert np.all(1 == diff[diff_y[:, 0], diff_x[:, 0]]), 'Start rise'
assert np.all(-1 == diff[diff_y[:, 1], diff_x[:, 1]]), 'Stop fall'

widths = diff_x[:, 1] - diff_x[:, 0]
n_white = widths.sum()
assert n_white == np.count_nonzero(image)

width_image = np.full(shape=image.shape, fill_value=np.nan, dtype=float)
width_image[image] = np.repeat(widths, widths)

这会生成一个图像,其中非裂纹像素上具有 NaN,裂纹像素上具有宽度。

© www.soinside.com 2019 - 2024. All rights reserved.