【问题标题】:How to paint text in an image using python如何使用python在图像中绘制文本
【发布时间】:2021-01-31 08:53:50
【问题描述】:

我有一张图片:

它有一些时间。

但我需要使用 python 将其转换为:

这个: 对此

简而言之,我需要使用 python 将该图像中的文本绘制为黑色。我认为也许 opencv 对此有用,但不确定。我需要在任何时候都在同一类型的图像中这样做(比如编辑前的图像,只是不同的数字)。 我认为我们可以使用 canny 来检测数字和点的边缘,然后将它们之间的区域涂成黑色。我不知道这样做的完美方式,但我认为它可能会奏效。希望有解决办法。提前致谢。

【问题讨论】:

  • 由于22 被触及,洪水填充将很难进行
  • 是的,但是没有其他解决方案吗?
  • 那是真实的图像吗?手指在接触,这会产生问题,通过相互接触,它们会形成封闭区域,很难检测到。如果数字 arr 稍微分开,那么您可以轻松地使用来自scikit image的floodfill
  • 另外,您可以编写自定义逻辑,例如通过 y 轴来填补空白
  • 另外,如果你知道每个数字的宽度,那么很容易,你可以分割图像,然后对单个部分应用洪水填充。

标签: python image opencv text paint


【解决方案1】:

我就是这样做的,我建议您使用形态学操作并寻找删除某些大小的 blob 以解决“22”问题的方法。您还可以调整公差值。

import cv2

imgray = cv2.imread('j3iIp.png',0)

point = (0,0)   

src = imgray.copy()

tolerance = 25
connectivity = 4
flags = connectivity
flags |= cv2.FLOODFILL_FIXED_RANGE

cv2.floodFill(src, None, point, (0, 255, 255), (tolerance,) * 3, (tolerance,) * 3, flags)

src = cv2.subtract(255, src) 

cv2.imshow('filled', src)

cv2.waitKey(0)

cv2.imwrite("result.jpg",src)

cv2.destroyAllWindows()

结果是:

【讨论】:

    【解决方案2】:

    如前所述,由于相邻的 22 会产生问题,所以过程将是这样的

    import numpy as np
    import matplotlib.pyplot as plt
    from skimage.segmentation import flood_fill
    
    img = io.imread('number.png', as_gray=True)
    
    plt.imshow(img, cmap='gray')
    

    你申请flood fill

    ff = flood_fill(img, (0,0), 125)
    ff[ff != 125] = 0
    ff[ff == 125] = 255
    
    plt.imshow(ff, cmap='gray')
    

    最后,保存图片

    io.imsave('out.png', ff)
    

    【讨论】:

      【解决方案3】:

      边框像素被打开以区分字符和背景。

      import cv2
      import numpy as np
      from matplotlib import pyplot as plt
      img = cv2.imread('j3iIp.jpg',0)
      ret,thresh2 = cv2.threshold(img,120,255,cv2.THRESH_BINARY_INV)
      cv2.imshow("result", thresh2)
      cv2.waitKey(0)
      cv2.destroyAllWindows()
      img1 = cv2.imwrite("thresh4.jpg",thresh2)
      

      【讨论】:

        【解决方案4】:

        我第一次尝试使用 cv2.findContours() 但是每个字符内部的空白和锁定在 22 之间的空白之间没有层次差异。 Epsi95 的解决方案中显示的“22 问题”无法使用轮廓解决层次结构信息。

        可以使用 cv2.floodFill() 和水平边缘检测来确定每个对象的种子点。

        import cv2
        import matplotlib.pyplot as plt
        import numpy as np
        
        # Fixed colon locations (assumed to be known constants)
        Y1, Y2 = (24, 48)
        X1, X2 = (45, 93)
        
        # Plot grayscale image
        img = np.uint8(cv2.imread("digits.png", cv2.IMREAD_GRAYSCALE) / 255)
        fig, axs = plt.subplots(2)
        axs[0].imshow(img, cmap="gray")
        
        # Horizontal edge detection at Y1 to determine the seed points (for flood filling)
        kernel = np.array([-1, -1, 1, 1], dtype=np.int8)  # bbww detector
        edge_det = np.correlate(img[Y1, :], kernel, mode="same")  # 2 @ bbWw
        edge_xloc = np.flatnonzero(edge_det == 2)
        seeds_yx = np.array(
            [
                [Y1, edge_xloc[1]],
                [Y1, edge_xloc[edge_xloc < X1][-2]],
                [Y1, X1],
                [Y1, edge_xloc[edge_xloc > X1][1]],
                [Y1, edge_xloc[edge_xloc < X2][-2]],
                [Y1, X2],
                [Y1, edge_xloc[edge_xloc > X2][1]],
                [Y1, edge_xloc[-2]],
                [Y2, X1],
                [Y2, X2],
            ]
        )
        axs[0].plot(seeds_yx[:, 1], seeds_yx[:, 0], "ro")
        
        # Flood fill at seed points
        for y, x in seeds_yx:
            cv2.floodFill(img, mask=None, seedPoint=(x, y), newVal=0)
        axs[1].imshow(img, cmap="gray")
        fig.show()
        

        此图中的代码结果

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-11-11
          • 1970-01-01
          • 2016-11-04
          • 2019-05-03
          • 2019-07-01
          • 2013-12-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多