gpt4 book ai didi

python - 如何在不影响内部轮廓的情况下从图像中去除外部空心轮廓

转载 作者:太空宇宙 更新时间:2023-11-03 21:28:52 25 4
gpt4 key购买 nike

这是 problem 的延续在不同的方法下。

我想摆脱盒子,以及它的线外的一切,并保持盒子内的一切,原样。或者至少只有盒子。

盒子:

img

我希望它在施展魔法后看起来像什么:

img

这是裁剪的地方:

img

如果您在黑色背景上查看第一张图片,您会注意到在方框区域之外仍然有一条白色带。通过获取边界框的统计数据并向其中添加填充,可以将其裁剪得更小或更大。

这是天真的方法,也是我的第一种方法。这里的问题是:

  • 它不能在不影响内部字符的情况下过多地考虑不同的线宽。比如说,你输入 -9 作为填充。它在 ~9px 线宽的盒子上工作得很好,但超过 ~9px 的任何东西都留在里面。这会导致一些剩余像素,最终影响我的应用程序的准确性。
  • 另一方面,任何线宽明显小于 9 的盒装字段也可能会破坏其中的字符。

我的第二次尝试是 removing the contour带着面具。然而,结果并没有像预期的那样。

提取轮廓的代码真的很长,所以假设 stats 包含从 contours, _ = cv2.findContours 返回的 contours/p>

# loop in each contour in stats
for i in range(len(stats)):
# get the stats of the bounding rectangle
x, y, w, h = cv2.boundingRect(stats[i])

# draw the field contour into the mask
cv2.drawContours(mask, [stats[i]], -1, 0, -1)

# remove the contour from the original image
section = cv2.bitwise_and(section, section, mask=mask)

# crop the boxed field
field = crop_by_origin(x, y, w, h, padding=p)

这是我得到的:

img

我不明白为什么它不起作用?也许是因为在网站上他的例子是黑色背景?也许它不适用于“透明”轮廓?这可能吗?

如何解决这个问题?这里还有其他可能的解决方案吗?

更新

我用@nathancy 的回答尝试了另一张图片,结果是这样的:

img

结果:

img

我尝试使用水平线内核,但没有达到预期效果,有没有办法让它更动态?

最佳答案

这个问题可以分解为两个独立的步骤。首先,我们要隔离可以使用轮廓近似+过滤来完成的矩形。然后,我们使用从 removing horizontal lines in image 中的先前答案中借用的实现删除水平线和垂直线。 .这是一个总体方法:

  • 将图像转换为灰度和高斯模糊
  • Otsu 获取二值图像的阈值
  • 寻找轮廓并使用轮廓近似来寻找矩形框

    • 如果轮廓通过此过滤器和最小阈值区域,则使用 Numpy 切片将 ROI 复制粘贴到空白的白色蒙版上
  • 去除水平线

  • 删除垂直线
  • 与输入图像进行按位与掩码以获得结果

Otsu 的阈值 -> 检测到的框 -> 绘制到掩码上的框 -> Inverted

去除水平线->去除垂直线->按位与得到结果

import cv2
import numpy as np

image = cv2.imread('1.png')
mask = np.ones(image.shape, dtype=np.uint8) * 255
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (7,7), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.05 * peri, True)
if len(approx) == 4 and area > 500:
x,y,w,h = cv2.boundingRect(approx)
mask[y:y+h, x:x+w] = image[y:y+h, x:x+w]

# Remove horizontal lines
mask = cv2.cvtColor(255 - mask, cv2.COLOR_BGR2GRAY)
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (50,2))
detect_horizontal = cv2.morphologyEx(mask, cv2.MORPH_OPEN, horizontal_kernel, iterations=1)
cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
cv2.drawContours(mask, [c], -1, (0,0,0), 6)

# Remove vertical lines
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,45))
detect_vertical = cv2.morphologyEx(mask, cv2.MORPH_OPEN, vertical_kernel, iterations=1)
cnts = cv2.findContours(detect_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
cv2.drawContours(mask, [c], -1, (0,0,0), 6)

# Bitwise mask with input image
result = cv2.bitwise_and(image, image, mask=mask)
result[mask==0] = (255,255,255)

cv2.imshow('mask', mask)
cv2.imshow('thresh', thresh)
cv2.imshow('result', result)
cv2.waitKey()

关于python - 如何在不影响内部轮廓的情况下从图像中去除外部空心轮廓,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58458378/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com