为了账号安全,请及时绑定邮箱和手机立即绑定

删除数独图像中的水平和垂直网格

删除数独图像中的水平和垂直网格

弑天下 2023-07-27 14:18:05
这是我的输入图像:这是一个带有网格和 81 个数字的灰度数独图像。我尝试通过参考一些网站使用opencv从该图像中删除水平和垂直网格。import cv2import mathimport numpy as npimport matplotlib.pyplot as pltgray = cv2.imread('gray.png', cv2.IMREAD_GRAYSCALE)thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 5, 5 )horizontal = np.copy(thresh)vertical = np.copy(thresh)# Specify size on horizontal axiscols = horizontal.shape[1]horizontal_size = math.ceil(cols / 20)# Create structure element for extracting horizontal lines through morphology operationshorizontalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (horizontal_size, 1))# Apply morphology operationshorizontal = cv2.erode(horizontal, horizontalStructure)horizontal = cv2.dilate(horizontal, horizontalStructure)# Show extracted horizontal linescv2.imwrite("horizontal.jpg", horizontal)# Specify size on vertical axisrows = vertical.shape[0]verticalsize = math.ceil(rows / 20)# Create structure element for extracting vertical lines through morphology operationsverticalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (1, verticalsize))# Apply morphology operationsvertical = cv2.erode(vertical, verticalStructure)vertical = cv2.dilate(vertical, verticalStructure)thresh_ = thresh - horizontal - vertical这是我当前的输出图像:我面临两个问题:并非所有水平和垂直网格都被删除。该代码还删除了数字 4 的一部分。我该如何更正我的代码?
查看完整描述

3 回答

?
交互式爱情

TA贡献1712条经验 获得超3个赞

我不知道这种方法是否适用于您的所有图像,但我注意到您想要删除网格的所有位置都有白线,并且图像的所有其余部分都是黑色的,因此它们似乎是一个有用的地方处理的目标。

我使用ImageMagick,但该方法可以轻松转换为 OpenCV。因此,步骤如下:

  • 克隆图像和阈值,使浅色线条变为白色,其余线条变为黑色

  • 将白色区域扩大为 3 个正方形,这样白线就会扩大以覆盖附近的黑色网格

  • 将白色替换为灰色(171)以匹配您的背景

  • 使黑色透明

  • 将结果合成到原始图像上,以用灰色隐藏白线和附近的黑色区域


magick sudoku.png \( +clone -threshold 80% -fill "gray(171)" -morphology dilate square:3 -opaque white -transparent black \) -composite result.png

//img1.sycdn.imooc.com//64c20c79000121f802440243.jpg


查看完整回答
反对 回复 2023-07-27
?
慕神8447489

TA贡献1780条经验 获得超1个赞


    1. 检测线路,使用fastLineDetector



    1. 设置长度阈值



    1. 绘制与背景相同的线条。


输出:

//img1.sycdn.imooc.com//64c20c8800011aef02400240.jpg

代码:


import cv2


gray = cv2.imread("gray.png", cv2.IMREAD_GRAYSCALE)

lines = cv2.ximgproc.createFastLineDetector(_length_threshold=15).detect(gray)


if lines is not None:

    for line in lines:

        (x_start, y_start, x_end, y_end) = line[0]

        cv2.line(gray, (x_start, y_start), (x_end, y_end), (172, 172, 172), thickness=4)


    cv2.imwrite("gray_result.png", gray)

    cv2.imshow("result", gray)

    cv2.waitKey(0)

    cv2.destroyAllWindows()

我们首先检查是否检测到这些行:


if lines is not None:

如果检测到线条,则获取坐标:


(x_start, y_start, x_end, y_end) = line[0]

然后画线:


cv2.line(gray, (x_start, y_start), (x_end, y_end), (172, 172, 172), thickness=4)

您可以更改线条的粗细,例如,如果将粗细设置为 10。


cv2.line(gray, (x_start, y_start), (x_end, y_end), (172, 172, 172), thickness=10)

输出:

//img1.sycdn.imooc.com//64c20ca200018c1d02430241.jpg

查看完整回答
反对 回复 2023-07-27
?
慕的地6264312

TA贡献1817条经验 获得超6个赞

有多种方法可以完成此类任务。除了其他答案之外,我还制作了另外两个示例来说明如何使用 numpy 和 OpenCV 来实现这一目标。选择正确的方式与您希望用什么来替换网格有关。


方法1:使用cv2.inpaint()函数方法2:找到白色像素并将其绘制出来


# imports

import cv2

import numpy as np


img = cv2.imread("sudoku.png")  # read image

color = img[3, 3]  # color of pixel in (3,3) coordinate

color = [int(i) for i in color]  # list of integer values of color

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # convert to grayscale

thresh = cv2.threshold(gray, 250, 255, cv2.THRESH_BINARY)[1]  # threshold image so that only white grid is left

dst = cv2.inpaint(img.copy(), thresh, 3, cv2.INPAINT_TELEA)  # Method 1: perform inpaint

coords = np.argwhere(gray==255)  # Method 2: find all coordinates of white pixels


dst2 = img.copy()  # hard copy of original image

dst3 = img.copy()  # hard copy of original image


# iterate through pixels and draw out the grid (Method 2)

for i in coords:


    cv2.circle(dst2, (i[0], i[1]), 3, color, -1)  # cirle with radius 3

    cv2.circle(dst3, (i[0], i[1]), 1, color, -1)  # circle only one pixel


# Write and display images

cv2.imwrite("dst.png", dst)

cv2.imwrite("dst2.png", dst2)

cv2.imwrite("dst3.png", dst3)

cv2.imshow("dst", dst)

cv2.imshow("dst2", dst2)

cv2.imshow("dst3", dst3)


cv2.waitKey(0)

cv2.destroyAllWindows()

结果:

//img1.sycdn.imooc.com//64c20cc20001f0f102450240.jpg.

方法一

//img1.sycdn.imooc.com//64c20cd60001622b02380244.jpg

方法2(5像素半径)


//img1.sycdn.imooc.com//64c20ce8000139e902400241.jpg

查看完整回答
反对 回复 2023-07-27
  • 3 回答
  • 0 关注
  • 139 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信