从类似斑点的图像的(内部和外部)边缘创建路径
Create path from (inner and outer) edges of a blob-like image
我正在寻找一种方法来从二进制图像(仅黑白像素)创建类似于 svg 的路径。图像本身将是一个形状不规则的斑点,其中可能有洞。
没有孔,我只需要一个边界路径来重新创建 blob 的边界。当 blob 中有漏洞时,我可以使用其他路径(我猜,因为单独一条路径无法重新创建它)。最后我只需要知道哪条路是外路,哪条路是洞。
我已经找到了这些:
- How to add stroke/outline to transparent PNG image in JavaScript canvas
- Creating a path from the edge of an image
- How can I find hole in a 2D matrix?
另外我需要检测漏洞。结果是多边形还是路径对我来说并不重要。我只需要足够高的精度使曲线保持弯曲的点:)
如果有人有想法或什至一些进一步的来源,那就太好了。
PS:如果这有什么不同的话,我正在使用 canvas 和 javascript (fabricJS)。
最佳选择
如果您使用代码绘制 Blob,那么最简单和最好的方法是将每个 blob(和子 blob)分解成它的组件贝塞尔曲线。 FabricJS 是开源的,因此您可以看到它们如何创建曲线——以及如何分解曲线。结果将是十几个易于重新绘制或导航的贝塞尔曲线。如果您在浏览贝塞尔曲线方面需要帮助,请参阅涵盖 Navigating along a Path.
的教程
其他选项
您将需要获取像素信息,因此您需要将 Fabric Blob context.drawImage
放到原生 canvas 上并使用 context.getImagedata
获取像素信息。
假设:
- 所有像素不是白色就是黑色。
- blob 是黑色的:rgba(0,0,0,255)
- blob 外面是白色的:rgba(255,255,255,255)
- blob 中的孔是白色的:rgba(255,255,255,255)
寻找斑点和洞路径的计划:
加载图像数据:context.getImageData(0,0,canvas.width,canvas.height)
在图像的周边找到一个白色像素。
使用 FloodFill 算法 (FFA) 用透明度替换外层白色。
使用移动方块算法 (MSA) 找到最外层的 blob 周长并保存该 blob 路径。
使用 Floodfill 算法以透明方式填充您在 #4 中发现的 blob。这使得外部 blob "invisible" 进入下一轮 MSA。此时你只有白洞——其他一切都是透明的。
使用移动方块算法 (MSA) 找到下一个白洞的周长并保存该洞路径。
使用 Floodfill 算法用透明度填充 #6 中的白洞。这使得这个洞对下一轮MSA不可见。
重复#6 和#7 找到每个剩余的白洞。
如果 MSA 报告没有像素,您就大功告成了。
为了提高效率,您可以在后续步骤中重复使用Step#1中的imageData。您可以在完成所有步骤后放弃图像数据。
由于斑点是曲线,您会发现斑点路径包含很多点。您可以使用路径点缩减算法将这些点简化为更少的点。
最后我成功地使用了 markE 描述的另一个选项(虽然它有点修改)。我正在使用 Marching Squares Algorithm (MSA)
和 Floodfill Algorithm (FFA)
来实现这一点。通过 Douglas-Peucker Algorithm (DPA)
.
简化结果点
- MAA:
- FFA:http://www.williammalone.com/articles/html5-canvas-javascript-paint-bucket-tool/
- DPA:
- (平滑:)
我把所有东西放在一起 jsFiddle。
步骤:
- 用户自由绘制完成后获取路径对象
- 通过 base64 dataURL 从路径创建图像
- 转换为二值图像(只有 0 和 255 像素,没有透明度)
- 在位置 0,0 上应用
FFA
随机颜色,保存颜色
- 转到下一个像素
- 如果像素具有已知的填充颜色或路径颜色(黑色),则继续下一步
- 否则用新的随机颜色填充,保存颜色
- 移动所有像素,重复 5.-7.
- 删除索引 1 上保存的颜色(它是围绕路径轮廓(填充)的颜色,因此它既不是路径也不是洞)
- 对于所有其他颜色应用
MSA
并简化结果点(使用 DPA
)
- 从简化的点创建多边形或者...
- ...平滑点并创建路径
- 添加到 canvas,删除输入路径
- 完成:)
为了更简单的代码,我目前的随机颜色只会产生灰色阴影。 R=G=B 和 A=255 允许更简单的检查。另一方面,此解决方案将轮廓限制为最大值。 254 个孔(256 种灰色阴影 - 路径颜色 (0) - 填充颜色(无孔))。如果需要更多,可以扩展代码为 R、G、B 甚至 A 创建随机值。不要忘记相应地采用颜色检查 ;)
整个算法可能没有针对性能进行优化,但老实说,我认为目前没有必要这样做。它对我的用例来说足够快了。无论如何,如果有人有关于优化的提示,我很高兴 hear/read 关于 :)
我正在寻找一种方法来从二进制图像(仅黑白像素)创建类似于 svg 的路径。图像本身将是一个形状不规则的斑点,其中可能有洞。
没有孔,我只需要一个边界路径来重新创建 blob 的边界。当 blob 中有漏洞时,我可以使用其他路径(我猜,因为单独一条路径无法重新创建它)。最后我只需要知道哪条路是外路,哪条路是洞。
我已经找到了这些:
- How to add stroke/outline to transparent PNG image in JavaScript canvas
- Creating a path from the edge of an image
- How can I find hole in a 2D matrix?
另外我需要检测漏洞。结果是多边形还是路径对我来说并不重要。我只需要足够高的精度使曲线保持弯曲的点:)
如果有人有想法或什至一些进一步的来源,那就太好了。
PS:如果这有什么不同的话,我正在使用 canvas 和 javascript (fabricJS)。
最佳选择
如果您使用代码绘制 Blob,那么最简单和最好的方法是将每个 blob(和子 blob)分解成它的组件贝塞尔曲线。 FabricJS 是开源的,因此您可以看到它们如何创建曲线——以及如何分解曲线。结果将是十几个易于重新绘制或导航的贝塞尔曲线。如果您在浏览贝塞尔曲线方面需要帮助,请参阅涵盖 Navigating along a Path.
的教程其他选项
您将需要获取像素信息,因此您需要将 Fabric Blob context.drawImage
放到原生 canvas 上并使用 context.getImagedata
获取像素信息。
假设:
- 所有像素不是白色就是黑色。
- blob 是黑色的:rgba(0,0,0,255)
- blob 外面是白色的:rgba(255,255,255,255)
- blob 中的孔是白色的:rgba(255,255,255,255)
寻找斑点和洞路径的计划:
加载图像数据:
context.getImageData(0,0,canvas.width,canvas.height)
在图像的周边找到一个白色像素。
使用 FloodFill 算法 (FFA) 用透明度替换外层白色。
使用移动方块算法 (MSA) 找到最外层的 blob 周长并保存该 blob 路径。
使用 Floodfill 算法以透明方式填充您在 #4 中发现的 blob。这使得外部 blob "invisible" 进入下一轮 MSA。此时你只有白洞——其他一切都是透明的。
使用移动方块算法 (MSA) 找到下一个白洞的周长并保存该洞路径。
使用 Floodfill 算法用透明度填充 #6 中的白洞。这使得这个洞对下一轮MSA不可见。
重复#6 和#7 找到每个剩余的白洞。
如果 MSA 报告没有像素,您就大功告成了。
为了提高效率,您可以在后续步骤中重复使用Step#1中的imageData。您可以在完成所有步骤后放弃图像数据。
由于斑点是曲线,您会发现斑点路径包含很多点。您可以使用路径点缩减算法将这些点简化为更少的点。
最后我成功地使用了 markE 描述的另一个选项(虽然它有点修改)。我正在使用 Marching Squares Algorithm (MSA)
和 Floodfill Algorithm (FFA)
来实现这一点。通过 Douglas-Peucker Algorithm (DPA)
.
- MAA:
- FFA:http://www.williammalone.com/articles/html5-canvas-javascript-paint-bucket-tool/
- DPA:
- (平滑:)
我把所有东西放在一起 jsFiddle。
步骤:
- 用户自由绘制完成后获取路径对象
- 通过 base64 dataURL 从路径创建图像
- 转换为二值图像(只有 0 和 255 像素,没有透明度)
- 在位置 0,0 上应用
FFA
随机颜色,保存颜色 - 转到下一个像素
- 如果像素具有已知的填充颜色或路径颜色(黑色),则继续下一步
- 否则用新的随机颜色填充,保存颜色
- 移动所有像素,重复 5.-7.
- 删除索引 1 上保存的颜色(它是围绕路径轮廓(填充)的颜色,因此它既不是路径也不是洞)
- 对于所有其他颜色应用
MSA
并简化结果点(使用DPA
) - 从简化的点创建多边形或者...
- ...平滑点并创建路径
- 添加到 canvas,删除输入路径
- 完成:)
为了更简单的代码,我目前的随机颜色只会产生灰色阴影。 R=G=B 和 A=255 允许更简单的检查。另一方面,此解决方案将轮廓限制为最大值。 254 个孔(256 种灰色阴影 - 路径颜色 (0) - 填充颜色(无孔))。如果需要更多,可以扩展代码为 R、G、B 甚至 A 创建随机值。不要忘记相应地采用颜色检查 ;)
整个算法可能没有针对性能进行优化,但老实说,我认为目前没有必要这样做。它对我的用例来说足够快了。无论如何,如果有人有关于优化的提示,我很高兴 hear/read 关于 :)