from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import cv2
threshold = 200
thickness = 16
linewidth = 2
white = 255
black = 0
def fun(image):
res = np.full(image.shape, white).astype(np.uint8)
# determine contours
grayscale = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(grayscale, threshold, white, cv2.THRESH_BINARY)[1]
contours = cv2.findContours(thresh, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)[0]
# create intersection and union
intersection, union = sorted(contours, key=len)[::len(contours) - 2]
outline = np.full(res.shape, white).astype(np.uint8)
cv2.drawContours(outline, [union], -1, black, thickness, cv2.LINE_AA)
inline = np.full(res.shape, white).astype(np.uint8)
cv2.drawContours(inline, [intersection], -1, black, thickness, cv2.LINE_AA)
# determine points for line
points = np.logical_and(outline == 0, inline == 0).astype(np.uint8)[:,:,0] * white
a, b = cv2.findContours(points, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)[0]
a = np.mean(a.squeeze(), axis=0).astype(int)
b = np.mean(b.squeeze(), axis=0).astype(int)
# draw outline of union
cv2.drawContours(res, [union], -1, black, linewidth, cv2.LINE_AA)
# draw connecting line
cv2.line(res, a, b, black, linewidth)
return res
for img in ['img1.jpg', 'img2.jpg']:
orig = np.asarray(Image.open(img))
res = fun(orig)
fig, ax = plt.subplots(1, 2)
for i, img in enumerate([orig, res]):
ax[i].imshow(img, cmap='gray');
ax[i].axes.get_xaxis().set_visible(False)
ax[i].axes.get_yaxis().set_visible(False)
plt.show();
Run Code Online (Sandbox Code Playgroud)
该方法的工作原理如下:
contours。接下来,通过增加大小对轮廓进行排序,这确保交集的轮廓(要删除的部分)排在第一位,并集的轮廓(要保留的部分)排在倒数第二位(最后是图像边界的轮廓)。outline在一个图像上用黑色绘制联合轮廓,在另一个图像上用黑色绘制相交轮廓inline,然后将两个图像的黑色部分相交以获得标记新线端点的补丁。然后计算端点a并将b新线作为其各自补丁的平均值。a以及b联合的轮廓,从而得到所需的输出图像。备注:这种方法不适用于第三种情况(因为它假设形状是凸的,或者更确切地说,只有一个交点),但我的猜测是,对其进行调整以适用于这种情况应该是可行的。
| 归档时间: |
|
| 查看次数: |
561 次 |
| 最近记录: |