这是problem在不同方法下的延续。
我想摆脱盒子及其线条外的所有东西,并保持盒子内部的一切不变。或至少只有盒子。
盒子:
做一些魔术后,我希望它看起来像什么
这是它的裁剪来源:
如果您在黑色背景上查看第一张图像,您会注意到在框形字段之外还有一个白色带。可以通过获取其边界框的统计信息并在其中添加填充来将其裁剪为更大或更小。
这是天真的,也是我的第一个方法。这里的问题是:
我的第二次尝试是removing the contour,戴上面具。但是,结果没有达到预期。
提取轮廓的代码非常长,因此假设stats
包含从contours
返回的contours, _ = cv2.findContours
# 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)
这就是我得到的:
我不明白为什么它不起作用?也许是因为该站点中的示例位于黑色背景上?也许不适用于“透明”轮廓?这有可能吗?
如何解决此问题?这里还有其他可能的解决方案吗?
更新
我用@nathancy的答案尝试了另一张图片,这就是结果:
结果:
我尝试使用水平线内核,但是没有按预期进行,有没有办法使它更具动态性?
答案 0 :(得分:2)
此问题可以分为两个单独的步骤。首先,我们要隔离矩形,这可以使用轮廓逼近+滤波完成。然后,使用从removing horizontal lines in image中的上一个答案借用的实现,删除水平和垂直线。这是一种整体方法:
查找轮廓并使用轮廓逼近法找到矩形框
删除水平线
大津的阈值->
检测到的盒子->
绘制到蒙版->
上的盒子倒了
删除水平线->
删除垂直线->
按位取-并得到结果
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()