我推荐以下步骤:
-
threshold()图片
-
dilate() the image - 这将删除分割顶部和底部的黑线以及下部较暗的伪影
-
findContours() 使用设置仅检索外部轮廓(RETR_EXTERNAL)并简化输出(CHAIN_APPROX_SIMPLE)
- 进一步处理轮廓
第 1 步:阈值
# threshold image
ret,thresh = cv2.threshold(img,127,255,0)
cv2.imshow('threshold ',thresh)
第 2 步:扩张
# dilate thresholded image - merges top/bottom
kernel = np.ones((3,3), np.uint8)
dilated = cv2.dilate(thresh, kernel, iterations=3)
cv2.imshow('threshold dilated',dilated)
第 3 步:寻找轮廓
# find contours
contours, hierarchy = cv2.findContours(dilated,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, 0, (255,255,255), 3)
print "contours:",len(contours)
print "largest contour has ",len(contours[0]),"points"
请注意,首先扩张,然后使用简单的外部轮廓可以得到你想要的形状,但它仍然非常复杂(包含 279 个点)
从现在开始,您可以继续process the contour features。
有几个选项可用,例如:
a:得到最小值。区域矩形
# minAreaRect
rect = cv2.minAreaRect(contours[0])
box = cv2.cv.BoxPoints(rect)
box = np.int0(box)
cv2.drawContours(img,[box],0,(255,255,255),3)
可能有用,但不完全是您所需要的。
b:凸包
# convexHull
hull = cv2.convexHull(contours[0])
cv2.drawContours(img, [hull], 0, (255,255,255), 3)
print "convex hull has ",len(hull),"points"
更好,但你还有 22 点要处理,而且还不是很紧
c:简化轮廓
# simplify contours
epsilon = 0.1*cv2.arcLength(contours[0],True)
approx = cv2.approxPolyDP(contours[0],epsilon,True)
cv2.drawContours(img, [approx], 0, (255,255,255), 3)
print "simplified contour has",len(approx),"points"
这可能就是您所追求的:只需 4 分。
如果您需要更多积分,可以使用 epsilon 值。
记住,现在你有一个四边形,但图片是扁平的:没有关于透视/3d 旋转的信息。
完整的OpenCV Python代码清单(根据需要注释/取消注释,使用参考适应c++/java/等):
import numpy as np
import cv2
img = cv2.imread('XwzWQ.png',0)
# threshold image
ret,thresh = cv2.threshold(img,127,255,0)
cv2.imshow('threshold ',thresh)
# dilate thresholded image - merges top/bottom
kernel = np.ones((3,3), np.uint8)
dilated = cv2.dilate(thresh, kernel, iterations=3)
cv2.imshow('threshold dilated',dilated)
# find contours
contours, hierarchy = cv2.findContours(dilated,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
# cv2.drawContours(img, contours, 0, (255,255,255), 3)
print "contours:",len(contours)
print "largest contour has ",len(contours[0]),"points"
# minAreaRect
# rect = cv2.minAreaRect(contours[0])
# box = cv2.cv.BoxPoints(rect)
# box = np.int0(box)
# cv2.drawContours(img,[box],0,(255,255,255),3)
# convexHull
# hull = cv2.convexHull(contours[0])
# cv2.drawContours(img, [hull], 0, (255,255,255), 3)
# print "convex hull has ",len(hull),"points"
# simplify contours
epsilon = 0.1*cv2.arcLength(contours[0],True)
approx = cv2.approxPolyDP(contours[0],epsilon,True)
cv2.drawContours(img, [approx], 0, (255,255,255), 3)
print "simplified contour has",len(approx),"points"
# display output
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()