我认为你可以使用
cv.grabCut
它有点像是为了做这样的事情。
以及代码上的注释,您可以使用
cv.HoughLines
在最后阶段,找到直线而不是对你分割的额外部分敏感的轮廓。
无论如何,这是我的代码,我认为它工作得很好,但我只测试了你的一些图像。
import cv2 as cv
import numpy as np
img = cv.imread(IMAGE)
height, width, _ = img.shape
p0 = (5, int(2*height/3))
p1 = (width - 5, height - 5)
color_mask = cv.inRange(img, (15, 15, 15), (100, 100, 100))
color_mask = color_mask // 255
color_masked = img * color_mask[:, :, None]
mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (*p0, *p1)
cv.grabCut(color_masked, mask, rect, bgdModel, fgdModel, 10, cv.GC_INIT_WITH_RECT)
grab_mask = np.where((mask == 2) | (mask == 0), 0, 1).astype(np.uint8)
masked = color_masked * grab_mask[:,:, np.newaxis]
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
closing = cv.morphologyEx(masked, cv.MORPH_CLOSE, kernel, iterations=2)
opening = cv.morphologyEx(closing, cv.MORPH_OPEN, kernel, iterations=2)
canny = cv.Canny(opening, 50, 150)
lines = cv.HoughLinesP(canny, 0.5, np.pi/360, 50)
for line in lines:
line = line[0]
cv.line(img, (line[0], line[1]), (line[2], line[3]), (255, 0, 0))
box = cv.boundingRect(lines.reshape(-1, 2))
cv.rectangle(img, box, (0, 0, 255))
cv.imshow('Result', img)
cv.waitKey(0)
cv.destroyAllWindows()
大部分是你的代码,但我用过
cv.garbCut
分割字幕的一部分(而不是阈值),并在最后使用
cv.HoughLines
。
您可能需要调整一些参数,并不断测试和操作代码,以使每个图像都能正常工作。尽管您可能会考虑按照M Ciel的建议使用OCR。我认为这是一种更标准的方法。