从具有正确边缘的png图像中获取轮廓(轮廓)
Get the contour (outline) from a png image with the correct edges
我有多个 png 文件,我正在尝试获取多边形轮廓坐标。
那是简化坐标,只有每个外角(不是凸包多边形)。
目前执行此操作的程序是python 和opencv。
但是另一个程序没问题我确实尝试使用 npm 包、imagemagick、potrace、Lua 来解决这个问题。
它将在 'build polygons from images' 进程中用作 shell 命令。
这是python下的最后一次测试。
现在的问题是下面示例中的一些边 'not' 是正确的。
我做了以下步骤
- 将 alpha 转换为黑白
- 描轮廓
- 获取坐标
- 原始png文件包含黑色线条(保留它们)。
- 转换后的黑白图像(你看不到第一行,因为这个网站是白色背景)
ret, mask = cv2.threshold(img[:, :, 3], 0, 255, cv2.THRESH_BINARY)
- 跟踪轮廓轮廓(不是我想要的输出)
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
问题是两个孔,左边1个像素和右边1个像素缺失。
- 当我在其他程序中使用该轮廓数据时,您会得到:
- 我想要这个轮廓轮廓多边形数据,所以外部程序显示这个:
# https://opensource.com/article/19/5/python-3-default-mac#what-to-do
# https://solarianprogrammer.com/2019/10/21/install-opencv-python-macos/
# https://docs.opencv.org/master/d4/d73/tutorial_py_contours_begin.html
#
# https://docs.opencv.org/3.4/dd/d49/tutorial_py_contour_features.html
#
import numpy as np
import cv2
img = cv2.imread('../temp/bord.png', cv2.IMREAD_UNCHANGED)
# make black and white
ret, mask = cv2.threshold(img[:, :, 3], 0, 255, cv2.THRESH_BINARY)
# find the external contour
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# at this point I want to have the correct contours to process them inside a other program
# print(contours)
# start debugging
#save image
cv2.imwrite('../temp/bord_converted.png',mask)
#create an empty image for contours
img_contours = np.zeros(img.shape)
# draw the contours on the empty image
cv2.drawContours(img_contours, contours, -1, (0,255,0), 1)
cv2.imwrite('../temp/bord_contour.jpg',img_contours)
编辑
我尝试的其他事情:
行进广场节目
Golang
https://github.com/zx9597446/marchingsquare/issues/1
那个给了我另一个问题,但是正确的代码
Npm
https://github.com/scottglz/image-outline
那个给了我几乎和上面一样的问题
imagemagick
正在尝试将 png 转换为黑白和 return 轮廓。
convert "$IMAGE" -matte -bordercolor none -border 1 -alpha extract -edge 1 -threshold 50% -depth 8 txt: | awk -F: '/white/{print }'
potrace
但是所有的输出都有东西,所以我不能用它。
potrace --progress -b svg --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --group --flat ../temp/bordout.bmp -o ../temp/bordout.svg
potrace --progress -b eps -c --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.eps
potrace --progress -b pdf -c --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.pdf
potrace --progress -b pdfpage --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.pdfpage
potrace --progress -b ps -c --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.ps
potrace --progress -b pgm --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.pgm
potrace --progress -b dxf --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.dxf
potrace --progress -b geojson --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.geojson
potrace --progress -b gimppath --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.gimppath
potrace --progress -b xfig --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.xfig
例如,SVG 输出看起来像图片一样正确,但我无法将其转换为 x,y 点数组多边形。
<path d="M121 132 l-121 0 0 -66 0 -66 121 0 121 0 0 66 0 66 -121 0z m0 -1
l120 0 0 -22 0 -23 -10 0 -11 0 0 -42 0 -43 -5 0 -5 0 0 43 0 42 -89 0 -89 0
0 -42 0 -43 -5 0 -5 0 0 43 0 42 -10 0 -11 0 0 23 0 22 120 0z M121 130 l-119
0 0 -21 0 -22 11 0 10 0 0 -42 0 -43 4 0 4 0 0 43 0 42 90 0 90 0 0 -42 0 -43
4 0 4 0 0 43 0 42 11 0 10 0 0 22 0 21 -119 0z"/>
</g>
例如使用https://github.com/Phrogz/svg-path-to-polygons给我
[
[
[ 121, 132 ], [ 0, 132 ],
[ 0, 66 ], [ 0, 0 ],
[ 121, 0 ], [ 242, 0 ],
[ 242, 66 ], [ 242, 132 ],
[ 121, 132 ], [ 121, 132 ],
closed: true
],
[
[ 121, 131 ], [ 241, 131 ], [ 241, 109 ],
[ 241, 86 ], [ 231, 86 ], [ 220, 86 ],
[ 220, 44 ], [ 220, 1 ], [ 215, 1 ],
[ 210, 1 ], [ 210, 44 ], [ 210, 86 ],
[ 121, 86 ], [ 32, 86 ], [ 32, 44 ],
[ 32, 1 ], [ 27, 1 ], [ 22, 1 ],
[ 22, 44 ], [ 22, 86 ], [ 12, 86 ],
[ 1, 86 ], [ 1, 109 ], [ 1, 131 ],
[ 121, 131 ], [ 121, 131 ], closed: true
],
[
[ 121, 130 ], [ 2, 130 ], [ 2, 109 ],
[ 2, 87 ], [ 13, 87 ], [ 23, 87 ],
[ 23, 45 ], [ 23, 2 ], [ 27, 2 ],
[ 31, 2 ], [ 31, 45 ], [ 31, 87 ],
[ 121, 87 ], [ 211, 87 ], [ 211, 45 ],
[ 211, 2 ], [ 215, 2 ], [ 219, 2 ],
[ 219, 45 ], [ 219, 87 ], [ 230, 87 ],
[ 240, 87 ], [ 240, 109 ], [ 240, 130 ],
[ 121, 130 ], [ 121, 130 ], closed: true
]
]
编辑 2
当我使用 SVG 解决方案时,输出现在给我一个可读的点列表
<polygon fill="none" points="0,0 0,44 20,44 21,45 21,129 30,129 30,45 31,44 208,44 209,45 209,129 218,129 218,45 219,44 239,44 239,0" stroke="black" stroke-linecap="round" stroke-linejoin="miter" />
但是当我使用那个坐标列表时它不是 100% 正确的。
边角还是不对
Firefox 的输出(放大)将显示为:
以及我将在其中使用坐标列表(不是 SVG)的程序
love.graphics.polygon("line",0,0,0,44,20,44,21,45,21,129,30,129,30,45,31,44,208,44,209,45,209,129,218,129,218,45,219,44,239,44,239,0)
将输出:
编辑 3
使用最后一个 python 脚本不生成多边形。
所需输出:矢量图形
矢量图中的点、线和曲线可以按比例放大或缩小到任何分辨率,而不会出现锯齿。因此,您不会看到破角。假设输出是 SVG 格式的矢量图。通过将每个轮廓转换为 SVG 多边形,可以很好地可视化角落。您可以参考here 三种渲染角的选择。我还添加了一个功能add_pixel_fillers
来调整足够接近的点。
import cv2
import svgwrite
img = cv2.imread("WFVso.png", cv2.IMREAD_UNCHANGED)
ret, mask = cv2.threshold(img[:, :, 3], 0, 255, cv2.THRESH_BINARY)
def add_pixel_fillers(img, cnt):
n_points = len(cnt)
for idx in range(n_points):
prev_pt = cnt[(idx+n_points+1) % n_points]
next_pt = cnt[(idx+1) % n_points]
if abs(cnt[idx][0]-next_pt[0])==1 and abs(cnt[idx][1]-next_pt[1])==1:
temp_x, temp_y = max(cnt[idx][0], next_pt[0]), min(cnt[idx][1], next_pt[1])
if img[temp_y, temp_x] == 255:
cnt[idx][0] = temp_x
cnt[idx][1] = temp_y
else:
temp_x, temp_y = min(cnt[idx][0], next_pt[0]), max(cnt[idx][1], next_pt[1])
if img[temp_y, temp_x] == 255:
cnt[idx][0] = temp_x
cnt[idx][1] = temp_y
return cnt
contours, hierarchy = cv2.findContours(mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
h, w = width=img.shape[0], img.shape[1]
dwg = svgwrite.Drawing('test.svg', height=h, width=w, viewBox=(f'-10 -10 {h} {w}'))
for cnt in contours:
cnt = add_pixel_fillers(mask, cnt.squeeze().tolist())
dwg.add(dwg.polygon(
points=cnt,
stroke_linecap='round',
stroke='black',
fill='none',
stroke_linejoin='miter'
))
dwg.save()
示例输入的 SVG 输出为
<?xml version="1.0" encoding="utf-8" ?>
<svg baseProfile="full" height="100%" version="1.1" viewBox="-10 -10 130 240" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs />
<polygon fill="none" points="0,0 0,44 21,44 21,45 21,129 30,129 31,44 31,44 209,44 209,45 209,129 218,129 219,44 219,44 239,44 239,0" stroke="black" stroke-linecap="round" stroke-linejoin="miter" />
</svg>
所需输出:光栅图形
如何填充角落缺失的像素点?假设在给定的情况下您只需要处理 90 度角,那么您想要填充缺失像素的像素模式数量有限。鉴于这些模式,您可以使用 scipy 包中的 ndimage.correlate
函数来找出填充像素的位置。
示例代码
import numpy as np
from scipy import ndimage
# Assume this is the contour you obtained in step 3
img = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 1, 1, 1],
[0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 1, 0, 0, 0]])
# You can add the patterns here
patterns = [
np.array([[0,0,0,0,0],
[0,0,0,0,0],
[1,1,0,0,0],
[0,0,1,0,0],
[0,0,1,0,0]]),
np.array([[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,1,1],
[0,0,1,0,0],
[0,0,1,0,0]])]
missing_corners = np.zeros_like(img) #Result will be stored here
for patt in patterns:
result = ndimage.correlate(img, patt, mode="constant")
corners = np.floor(result/np.sum(patt)).astype(int)
missing_corners = (missing_corners + corners) % 2 #Can use binary OR
查看结果
print(missing_corners)
将显示缺失角的位置:
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
对于更复杂的形状,我建议您在导出轮廓时使用 drawSvg
等包生成矢量图(例如 SVG)。
我有多个 png 文件,我正在尝试获取多边形轮廓坐标。 那是简化坐标,只有每个外角(不是凸包多边形)。
目前执行此操作的程序是python 和opencv。 但是另一个程序没问题我确实尝试使用 npm 包、imagemagick、potrace、Lua 来解决这个问题。 它将在 'build polygons from images' 进程中用作 shell 命令。
这是python下的最后一次测试。
现在的问题是下面示例中的一些边 'not' 是正确的。
我做了以下步骤
- 将 alpha 转换为黑白
- 描轮廓
- 获取坐标
- 原始png文件包含黑色线条(保留它们)。
- 转换后的黑白图像(你看不到第一行,因为这个网站是白色背景)
ret, mask = cv2.threshold(img[:, :, 3], 0, 255, cv2.THRESH_BINARY)
- 跟踪轮廓轮廓(不是我想要的输出)
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
问题是两个孔,左边1个像素和右边1个像素缺失。
- 当我在其他程序中使用该轮廓数据时,您会得到:
- 我想要这个轮廓轮廓多边形数据,所以外部程序显示这个:
# https://opensource.com/article/19/5/python-3-default-mac#what-to-do
# https://solarianprogrammer.com/2019/10/21/install-opencv-python-macos/
# https://docs.opencv.org/master/d4/d73/tutorial_py_contours_begin.html
#
# https://docs.opencv.org/3.4/dd/d49/tutorial_py_contour_features.html
#
import numpy as np
import cv2
img = cv2.imread('../temp/bord.png', cv2.IMREAD_UNCHANGED)
# make black and white
ret, mask = cv2.threshold(img[:, :, 3], 0, 255, cv2.THRESH_BINARY)
# find the external contour
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# at this point I want to have the correct contours to process them inside a other program
# print(contours)
# start debugging
#save image
cv2.imwrite('../temp/bord_converted.png',mask)
#create an empty image for contours
img_contours = np.zeros(img.shape)
# draw the contours on the empty image
cv2.drawContours(img_contours, contours, -1, (0,255,0), 1)
cv2.imwrite('../temp/bord_contour.jpg',img_contours)
编辑
我尝试的其他事情:
行进广场节目
Golang
https://github.com/zx9597446/marchingsquare/issues/1 那个给了我另一个问题,但是正确的代码
Npm https://github.com/scottglz/image-outline 那个给了我几乎和上面一样的问题
imagemagick
正在尝试将 png 转换为黑白和 return 轮廓。
convert "$IMAGE" -matte -bordercolor none -border 1 -alpha extract -edge 1 -threshold 50% -depth 8 txt: | awk -F: '/white/{print }'
potrace
但是所有的输出都有东西,所以我不能用它。
potrace --progress -b svg --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --group --flat ../temp/bordout.bmp -o ../temp/bordout.svg
potrace --progress -b eps -c --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.eps
potrace --progress -b pdf -c --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.pdf
potrace --progress -b pdfpage --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.pdfpage
potrace --progress -b ps -c --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.ps
potrace --progress -b pgm --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.pgm
potrace --progress -b dxf --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.dxf
potrace --progress -b geojson --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.geojson
potrace --progress -b gimppath --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.gimppath
potrace --progress -b xfig --blacklevel 0 --turdsize 0 --longcurve --opttolerance 0 --unit 1 --turnpolicy white --alphamax 0 --scale 1 --flat ../temp/bordout.bmp -o ../temp/bordout.xfig
例如,SVG 输出看起来像图片一样正确,但我无法将其转换为 x,y 点数组多边形。
<path d="M121 132 l-121 0 0 -66 0 -66 121 0 121 0 0 66 0 66 -121 0z m0 -1
l120 0 0 -22 0 -23 -10 0 -11 0 0 -42 0 -43 -5 0 -5 0 0 43 0 42 -89 0 -89 0
0 -42 0 -43 -5 0 -5 0 0 43 0 42 -10 0 -11 0 0 23 0 22 120 0z M121 130 l-119
0 0 -21 0 -22 11 0 10 0 0 -42 0 -43 4 0 4 0 0 43 0 42 90 0 90 0 0 -42 0 -43
4 0 4 0 0 43 0 42 11 0 10 0 0 22 0 21 -119 0z"/>
</g>
例如使用https://github.com/Phrogz/svg-path-to-polygons给我
[
[
[ 121, 132 ], [ 0, 132 ],
[ 0, 66 ], [ 0, 0 ],
[ 121, 0 ], [ 242, 0 ],
[ 242, 66 ], [ 242, 132 ],
[ 121, 132 ], [ 121, 132 ],
closed: true
],
[
[ 121, 131 ], [ 241, 131 ], [ 241, 109 ],
[ 241, 86 ], [ 231, 86 ], [ 220, 86 ],
[ 220, 44 ], [ 220, 1 ], [ 215, 1 ],
[ 210, 1 ], [ 210, 44 ], [ 210, 86 ],
[ 121, 86 ], [ 32, 86 ], [ 32, 44 ],
[ 32, 1 ], [ 27, 1 ], [ 22, 1 ],
[ 22, 44 ], [ 22, 86 ], [ 12, 86 ],
[ 1, 86 ], [ 1, 109 ], [ 1, 131 ],
[ 121, 131 ], [ 121, 131 ], closed: true
],
[
[ 121, 130 ], [ 2, 130 ], [ 2, 109 ],
[ 2, 87 ], [ 13, 87 ], [ 23, 87 ],
[ 23, 45 ], [ 23, 2 ], [ 27, 2 ],
[ 31, 2 ], [ 31, 45 ], [ 31, 87 ],
[ 121, 87 ], [ 211, 87 ], [ 211, 45 ],
[ 211, 2 ], [ 215, 2 ], [ 219, 2 ],
[ 219, 45 ], [ 219, 87 ], [ 230, 87 ],
[ 240, 87 ], [ 240, 109 ], [ 240, 130 ],
[ 121, 130 ], [ 121, 130 ], closed: true
]
]
编辑 2
当我使用 SVG 解决方案时,输出现在给我一个可读的点列表
<polygon fill="none" points="0,0 0,44 20,44 21,45 21,129 30,129 30,45 31,44 208,44 209,45 209,129 218,129 218,45 219,44 239,44 239,0" stroke="black" stroke-linecap="round" stroke-linejoin="miter" />
但是当我使用那个坐标列表时它不是 100% 正确的。 边角还是不对
Firefox 的输出(放大)将显示为:
以及我将在其中使用坐标列表(不是 SVG)的程序
love.graphics.polygon("line",0,0,0,44,20,44,21,45,21,129,30,129,30,45,31,44,208,44,209,45,209,129,218,129,218,45,219,44,239,44,239,0)
将输出:
编辑 3
使用最后一个 python 脚本不生成多边形。
所需输出:矢量图形
矢量图中的点、线和曲线可以按比例放大或缩小到任何分辨率,而不会出现锯齿。因此,您不会看到破角。假设输出是 SVG 格式的矢量图。通过将每个轮廓转换为 SVG 多边形,可以很好地可视化角落。您可以参考here 三种渲染角的选择。我还添加了一个功能add_pixel_fillers
来调整足够接近的点。
import cv2
import svgwrite
img = cv2.imread("WFVso.png", cv2.IMREAD_UNCHANGED)
ret, mask = cv2.threshold(img[:, :, 3], 0, 255, cv2.THRESH_BINARY)
def add_pixel_fillers(img, cnt):
n_points = len(cnt)
for idx in range(n_points):
prev_pt = cnt[(idx+n_points+1) % n_points]
next_pt = cnt[(idx+1) % n_points]
if abs(cnt[idx][0]-next_pt[0])==1 and abs(cnt[idx][1]-next_pt[1])==1:
temp_x, temp_y = max(cnt[idx][0], next_pt[0]), min(cnt[idx][1], next_pt[1])
if img[temp_y, temp_x] == 255:
cnt[idx][0] = temp_x
cnt[idx][1] = temp_y
else:
temp_x, temp_y = min(cnt[idx][0], next_pt[0]), max(cnt[idx][1], next_pt[1])
if img[temp_y, temp_x] == 255:
cnt[idx][0] = temp_x
cnt[idx][1] = temp_y
return cnt
contours, hierarchy = cv2.findContours(mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
h, w = width=img.shape[0], img.shape[1]
dwg = svgwrite.Drawing('test.svg', height=h, width=w, viewBox=(f'-10 -10 {h} {w}'))
for cnt in contours:
cnt = add_pixel_fillers(mask, cnt.squeeze().tolist())
dwg.add(dwg.polygon(
points=cnt,
stroke_linecap='round',
stroke='black',
fill='none',
stroke_linejoin='miter'
))
dwg.save()
示例输入的 SVG 输出为
<?xml version="1.0" encoding="utf-8" ?>
<svg baseProfile="full" height="100%" version="1.1" viewBox="-10 -10 130 240" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs />
<polygon fill="none" points="0,0 0,44 21,44 21,45 21,129 30,129 31,44 31,44 209,44 209,45 209,129 218,129 219,44 219,44 239,44 239,0" stroke="black" stroke-linecap="round" stroke-linejoin="miter" />
</svg>
所需输出:光栅图形
如何填充角落缺失的像素点?假设在给定的情况下您只需要处理 90 度角,那么您想要填充缺失像素的像素模式数量有限。鉴于这些模式,您可以使用 scipy 包中的 ndimage.correlate
函数来找出填充像素的位置。
示例代码
import numpy as np
from scipy import ndimage
# Assume this is the contour you obtained in step 3
img = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 1, 1, 1],
[0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 1, 0, 0, 0]])
# You can add the patterns here
patterns = [
np.array([[0,0,0,0,0],
[0,0,0,0,0],
[1,1,0,0,0],
[0,0,1,0,0],
[0,0,1,0,0]]),
np.array([[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,1,1],
[0,0,1,0,0],
[0,0,1,0,0]])]
missing_corners = np.zeros_like(img) #Result will be stored here
for patt in patterns:
result = ndimage.correlate(img, patt, mode="constant")
corners = np.floor(result/np.sum(patt)).astype(int)
missing_corners = (missing_corners + corners) % 2 #Can use binary OR
查看结果
print(missing_corners)
将显示缺失角的位置:
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
对于更复杂的形状,我建议您在导出轮廓时使用 drawSvg
等包生成矢量图(例如 SVG)。