正如@Silencer所建议的那样,我使用他发布的代码here来绘制图像中数字的轮廓 . 在某些时候,使用像 0,6,8,9
这样的数字我看到他们的内部轮廓(圆圈)也被填充了 . 我怎么能阻止这个?是否有为cv2.drawContours()设置的最小/最大动作区域,所以我可以排除内部区域?
我试图传递 cv2.RETR_EXTERNAL
但是使用此参数只考虑整个外部区域 .
代码是这样的(再次,感谢Silencer . 几个月来一直在搜索...):
import numpy as np
import cv2
im = cv2.imread('imgs\\2.png')
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#contours.sort(key=lambda x: int(x.split('.')[0]))
for i, cnts in enumerate(contours):
## this contour is a 3D numpy array
cnt = contours[i]
res = cv2.drawContours(im, [cnt], 0, (255, 0, 0), 1)
cv2.imwrite("contours.png", res)
'''
## Method 1: crop the region
x,y,w,h = cv2.boundingRect(cnt)
croped = res[y:y+h, x:x+w]
cv2.imwrite("cnts\\croped{}.png".format(i), croped)
'''
## Method 2: draw on blank
# get the 0-indexed coords
offset = cnt.min(axis=0)
cnt = cnt - cnt.min(axis=0)
max_xy = cnt.max(axis=0) + 1
w, h = max_xy[0][0], max_xy[0][1]
# draw on blank
canvas = np.ones((h, w, 3), np.uint8) * 255
cv2.drawContours(canvas, [cnt], -1, (0, 0, 0), -1)
#if h > 15 and w < 60:
cv2.imwrite("cnts\\canvas{}.png".format(i), canvas)
我工作的主要形象..
谢谢
UPDATE
我在下面实现了Fiver答案,结果如下:
import cv2
import numpy as np
img = cv2.imread('img.png')
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
img_v = img_hsv[:, :, 2]
ret, thresh = cv2.threshold(~img_v, 127, 255, 0)
image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for i, c in enumerate(contours):
tmp_img = np.zeros(img_v.shape, dtype=np.uint8)
res = cv2.drawContours(tmp_img, [c], -1, 255, cv2.FILLED)
tmp_img = np.bitwise_and(tmp_img, ~img_v)
ret, inverted = cv2.threshold(tmp_img, 127, 255, cv2.THRESH_BINARY_INV)
cnt = contours[i]
x, y, w, h = cv2.boundingRect(cnt)
cropped = inverted[y:y + h, x:x + w]
cv2.imwrite("roi{}.png".format(i), cropped)
5 回答
要绘制
char
而不填充封闭的内部区域:FindContours,重新填充内部封闭区域 .
结合这个答案Copy shape to blank canvas (OpenCV, Python),做更多的步骤,也许你可以得到这个或更好的:
refill
内部封闭区域的核心代码如下:使用此图片运行此代码:
你会得到:
当然,这是两个层次结构 . 我没有测试过两次以上 . 你需要的人可以自己做测试 .
更新:
请注意,在不同的OpenCV中,
cv2.findContours
返回不同的值 . 为了保持代码可执行,我们可以使用最后两个返回值:cnts,hiers = cv2.findContours(...)[ - 2:]在OpenCV 3.4中:
在OpenCV 4.0中:
由于您已经从阈值步骤中获得了一个蒙版,因此您也可以使用它来对应绘制的轮廓
bitwise_and
:我已经倒转了图像,所以轮廓是白色的,当你已经解决了这个问题时,我省略了裁剪 . 以下是其中一个“O”字符的结果:
完整代码......
这不会对图像进行排序 .
接受任何更正 .
这将确定工作......
这在概念上类似于Fivers的答案,只是bitwise_并且发生在for循环之外,并且在性能方面可能更好 . 对于那些为这个问题寻找C答案的人来说,源代码在C中 .
在将源图像参数传递给findContours时,请记住克隆图像(对于python应该是复制),因为findContours会修改原始图像 . 我估计更高版本的opencv(也许是opencv3)不需要克隆 .