将黑白图像完全转换为一组线条(也称为仅使用线条进行矢量化)

2024-06-26

我有许多黑白图像,想将它们转换为一组线条,这样我就可以完全或至少接近完全地从线条重建原始图像。换句话说,我试图将图像矢量化为一组线条。

我已经看过了霍夫线变换 https://docs.opencv.org2.4/modules/imgproc/doc/feature_detection.html?highlight=houghlines#houghlines,然而,这并没有覆盖图像的每个部分,更多的是寻找图像中的线条,而不是将图像完全转换为线条表示。此外,线变换不会对线的实际宽度进行编码,让我猜测如何重建图像(我需要这样做,因为这是训练机器学习算法的预处理步骤)。

到目前为止,我使用 houghLineTransform 尝试了以下代码:

import numpy as np
import cv2

MetersPerPixel=0.1

def loadImageGray(path):
    img=(cv2.imread(path,0))
    return img

def LineTransform(img):
    edges = cv2.Canny(img,50,150,apertureSize = 3)
    minLineLength = 10
    maxLineGap = 20
    lines = cv2.HoughLines(edges,1,np.pi/180,100,minLineLength,maxLineGap)
    return lines;

def saveLines(liness):
    img=np.zeros((2000,2000,3), np.uint8)
    for lines in liness:
        for x1,y1,x2,y2 in lines:
            print(x1,y1,x2,y2)
            img=cv2.line(img,(x1,y1),(x2,y2),(0,255,0),3)
    cv2.imwrite('houghlines5.jpg',img)

def main():
    img=loadImageGray("loadtest.png")
    lines=LineTransform(img)
    saveLines(lines)

main()

However when tested using the following image

I got this image: output

正如您所看到的,它缺少未轴对齐的线,如果仔细观察,甚至检测到的线也被分成两行,它们之间有一些空间。我还必须以预设宽度绘制这些图像,而实际宽度未知。

编辑:根据@MarkSetcell的建议,我使用以下代码尝试了pypotrace,目前它很大程度上忽略了贝塞尔曲线,只是试图表现得像直线一样,我稍后会关注这个问题,但是现在的结果是' t 最优:

def TraceLines(img):
    bmp = potrace.Bitmap(bitmap(img))
    path=bmp.trace()
    lines=[]
    i=0
    for curve in path:
        for segment in curve:
            print(repr(segment))
            if segment.is_corner:
                c_x, c_y = segment.c
                c2_x ,c2_y= segment.end_point
                            lines.append([[int(c_x), int(c_y),int(c2_x) ,int(c2_y)]])

            else:
                c_x, c_y = segment.c1
                c2_x ,c2_y= segment.end_point
            i=i+1
    return lines

this results in this image image, which is an improvement, however while the problem with the circle can be addressed at a later point the missing parts of the square and the weird artefacts on the other straight lines are more problematic. Anyone know how to fix them? Any tips on how to get the line widths?

有人对如何更好地解决这个问题有任何建议吗?

edit edit: here is another test image : variable wall width, it includes multiple line widths I would like to capture.


OpenCV

使用 OpenCVfindContours https://docs.opencv.org/4.1.1/d3/dc0/group__imgproc__shape.html#gadf1ad6a0b82947fa1fe3c3d497f260e0 and drawContours https://docs.opencv.org/4.1.1/d6/d6e/group__imgproc__draw.html#ga746c0625f1781f1ffc9056259103edbc可以首先对线条进行矢量化,然后精确地重新创建原始图像:

import numpy as np

import cv2

img = cv2.imread('loadtest.png', 0)

result_fill = np.ones(img.shape, np.uint8) * 255
result_borders = np.zeros(img.shape, np.uint8)

# the '[:-1]' is used to skip the contour at the outer border of the image
contours = cv2.findContours(img, cv2.RETR_LIST,
                            cv2.CHAIN_APPROX_SIMPLE)[0][:-1]

# fill spaces between contours by setting thickness to -1
cv2.drawContours(result_fill, contours, -1, 0, -1)
cv2.drawContours(result_borders, contours, -1, 255, 1)

# xor the filled result and the borders to recreate the original image
result = result_fill ^ result_borders

# prints True: the result is now exactly the same as the original
print(np.array_equal(result, img))

cv2.imwrite('contours.png', result)

Result

Scikit-图像

使用 scikit 图像find_contours https://scikit-image.org/docs/0.16.x/api/skimage.measure.html#skimage.measure.find_contours and approximate_polygon https://scikit-image.org/docs/0.16.x/api/skimage.measure.html#skimage.measure.approximate_polygon允许您通过近似多边形来减少线数(基于这个例子 https://scikit-image.org/docs/stable/auto_examples/edges/plot_polygon.html#sphx-glr-auto-examples-edges-plot-polygon-py):

import numpy as np
from skimage.measure import approximate_polygon, find_contours

import cv2

img = cv2.imread('loadtest.png', 0)
contours = find_contours(img, 0)

result_contour = np.zeros(img.shape + (3, ), np.uint8)
result_polygon1 = np.zeros(img.shape + (3, ), np.uint8)
result_polygon2 = np.zeros(img.shape + (3, ), np.uint8)

for contour in contours:
    print('Contour shape:', contour.shape)

    # reduce the number of lines by approximating polygons
    polygon1 = approximate_polygon(contour, tolerance=2.5)
    print('Polygon 1 shape:', polygon1.shape)

    # increase tolerance to further reduce number of lines
    polygon2 = approximate_polygon(contour, tolerance=15)
    print('Polygon 2 shape:', polygon2.shape)

    contour = contour.astype(np.int).tolist()
    polygon1 = polygon1.astype(np.int).tolist()
    polygon2 = polygon2.astype(np.int).tolist()

    # draw contour lines
    for idx, coords in enumerate(contour[:-1]):
        y1, x1, y2, x2 = coords + contour[idx + 1]
        result_contour = cv2.line(result_contour, (x1, y1), (x2, y2),
                                  (0, 255, 0), 1)
    # draw polygon 1 lines
    for idx, coords in enumerate(polygon1[:-1]):
        y1, x1, y2, x2 = coords + polygon1[idx + 1]
        result_polygon1 = cv2.line(result_polygon1, (x1, y1), (x2, y2),
                                   (0, 255, 0), 1)
    # draw polygon 2 lines
    for idx, coords in enumerate(polygon2[:-1]):
        y1, x1, y2, x2 = coords + polygon2[idx + 1]
        result_polygon2 = cv2.line(result_polygon2, (x1, y1), (x2, y2),
                                   (0, 255, 0), 1)

cv2.imwrite('contour_lines.png', result_contour)
cv2.imwrite('polygon1_lines.png', result_polygon1)
cv2.imwrite('polygon2_lines.png', result_polygon2)

Results

Python输出:

Contour shape: (849, 2)
Polygon 1 shape: (28, 2)
Polygon 2 shape: (9, 2)
Contour shape: (825, 2)
Polygon 1 shape: (31, 2)
Polygon 2 shape: (9, 2)
Contour shape: (1457, 2)
Polygon 1 shape: (9, 2)
Polygon 2 shape: (8, 2)
Contour shape: (879, 2)
Polygon 1 shape: (5, 2)
Polygon 2 shape: (5, 2)
Contour shape: (973, 2)
Polygon 1 shape: (5, 2)
Polygon 2 shape: (5, 2)
Contour shape: (224, 2)
Polygon 1 shape: (4, 2)
Polygon 2 shape: (4, 2)
Contour shape: (825, 2)
Polygon 1 shape: (13, 2)
Polygon 2 shape: (13, 2)
Contour shape: (781, 2)
Polygon 1 shape: (13, 2)
Polygon 2 shape: (13, 2)

轮廓线.png:

多边形1_线.png:

多边形2_线.png:

然后可以通过将毕达哥拉斯定理应用于坐标来计算线的长度:line_length = math.sqrt(abs(x2 - x1)**2 + abs(y2 - y1)**2)。如果您想以数值形式获取线条的宽度,请查看以下答案“如何确定线的宽度?” https://stackoverflow.com/questions/22081908/how-to-determine-the-width-of-the-lines一些建议的方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将黑白图像完全转换为一组线条(也称为仅使用线条进行矢量化) 的相关文章

  • 使用 selenium 和 python 在网页网格中抓取 javascript 数据

    我的问题是我需要包含网站子域的网格中的所有数据https applipedia paloaltonetworks com https applipedia paloaltonetworks com 包含名称 类别 子类别 风险 技术的数据
  • Django CollectStatic 启动大文件上传时管道损坏

    我正在尝试使用collectstatic将静态文件上传到我的S3存储桶 但我收到一个700k javascript文件的管道损坏错误 这就是错误 Copying Users wedonia work asociados server aso
  • ValueError:字符 U+6573552f...Py2aap

    我制作了一个非常简单的程序 我正在尝试将其导出到应用程序文件 我目前正在使用 Python 3 6 和 py2app 将 py 文件转换为 app 所以我创建了安装文件 from setuptools import setup OPTION
  • 为什么 scikit-learn SVM.SVC() 非常慢?

    我尝试使用SVM分类器来训练大约10万个样本的数据 但我发现它非常慢 甚至两个小时后也没有任何反应 当数据集有大约 1k 个样本时 我可以立即得到结果 我还尝试了 SGDClassifier 和朴素贝叶斯 速度相当快 几分钟内就得到了结果
  • 为什么我的字符串中出现不需要的换行符?

    这应该很简单 这很愚蠢 但我无法让它发挥作用 我有一个在读取文件时定义的标头 if gene env in line or gene HIV2gp7 in line header line 现在这个标题看起来像 gt lcl NC 0018
  • 如何在我的 GUI 上绘图

    我正在设计一个 GUIPyQt当我单击一个按钮来绘制我创建的函数的数据图时 我需要显示一个 matplotlib pylab 窗口 它就像 Matlab 中使用的运行时 每次按下该按钮时 我都想将 matplotlib pylab 窗口保留
  • 在Python中将月份和年份的列合并为季度和年份的列

    我有一个数据框 df Month 1 8 Year 2015 2020 df pd DataFrame data df df 想要将其转变为新列 期望的输出 df Month 1 8 Year 2015 2020 Quarter Q1201
  • 如何在Python中将N毫秒添加到日期时间

    我正在设置一个日期时间变量 fulldate datetime datetime strptime date time Y m d H M S f 其中日期和时间是适合日期时间性质的字符串 如何将此日期时间增加 N 毫秒 Use timed
  • 基于 Pandas 中特殊字符分隔列中的每个项目进行聚合

    我输入的数据如下 Date Investment Type Medium 1 1 2000 Mutual Fund Stocks Fixed Deposit Real Estate Own Online Through Agent 1 2
  • 识别文本中的多个类别和相关情感

    如果您有一个文本语料库 如何识别所有类别 来自预定义类别列表 以及与之相关的情绪 正面 负面写作 我将在 Python 中执行此操作 但现阶段我不一定要寻找特定于语言的解决方案 让我们用一个例子来看看这个问题 试图澄清我的问题 如果我有一整
  • 将 gtk.DrawingArea 保存到文件

    我想使用 PIL 将 gtk DrawingArea 对象内容保存到 jpeg 文件 我特别想添加这个脚本 http pygstdocs berlios de pygst tutorial webcam viewer html制作照片的可能
  • python请求ssl握手失败

    每次我尝试这样做 requests get https url 我收到这条消息 import requests gt gt gt requests get https reviews gethuman com companies Trace
  • 如何忽略 Sentry 捕获中的某些 Python 错误

    我已将 Sentry 配置为捕获 Django Celery 应用程序中的所有错误 它工作正常 但我发现一个令人讨厌的用例是当我必须重新启动我的 Celery 工作人员 PostgreSQL 数据库或消息服务器时 这会导致数千种各种 无法访
  • 折叠 numpy 数组除前两个维度之外的所有维度

    我有一个可变维度的 numpy 数组 例如它可以具有以下形状 64 64 64 64 2 5 64 64 40 64 64 10 20 4 我想要做的是 如果维数大于 3 我想将其他所有内容折叠 堆叠到第三维中 同时保留顺序 因此 在我上面
  • 抓取 Shopee API v4

    我有一个最终项目 其中我想要检索的数据是通过在shopee上抓取数据来获取的 但是当我在隐藏的API上抓取shopee时遇到问题 当我在Insomnia脚本上尝试时 脚本会运行 但是当我尝试时在本地或 google colab 脚本上 这是
  • 如何使用 opencv python 根据检测到的物体的位置生成其热图

    我需要根据对象的位置生成其热图 示例 视频帧中检测到的绿色球 如果它长时间停留在某个位置 那么该位置应该是红色的 并且球在短时间内经过的帧中的位置必须是蓝色的 这样我就需要生成热图 提前致谢 那么你在这里可以做的是 1 首先定义一个热图作为
  • tkinter 库 treectrl 转换为 exe 安装程序时出现 cx_freeze 错误

    我使用的是 python 版本 3 7 我使用了这个名为 treectrl 的外部库 当我运行 py 文件时它工作得很好 但是当我使用 cx freeze 转换为 exe 文件时 它给了我错误 NomodulleFound 名为 tkint
  • VSCode IntelliSense 认为 Python 'function()' 类存在

    VSCode IntelliSense 正在完成一个名为的 Python 类function 这似乎不存在 例如 这似乎是有效的代码 def foo value return function value foo 0 But functio
  • print() 函数的有趣/奇怪的机制

    我正在学习Python 我目前正在学习如何定义自己的函数 并且在尝试理解返回值和打印它之间的区别时遇到了一些困难 我读到的关于这个主题的描述对我来说不太清楚 所以我开始自己尝试 我想我现在已经明白了 如果我没记错的话 区别在于你可以传递 a
  • Mac 无法安装 Tensorflow

    我检查了我的 pip3 和 python3 版本 tensorflow MacBook Pro de Hector 2 tensorflow hectoresteban pip3 V pip 10 0 1 from Users hector

随机推荐