如果有一天有人需要做类似的事情,这就是我最终使用的代码。它效率不高,但效果很好,并且时间不是这个项目的一个因素(注意我在cv2.threshold(imgray,220,255,0) 中使用红色和绿色作为轮廓阈值。你可能想要改变它)-
def contour_to_image(con, original_image):
# Get the rect coordinates of the contour
lm, tm, rm, bm = rect_for_contour(con)
con_im = original_image.crop((lm, tm, rm, bm))
if con_im.size[0] == 0 or con_im.size[1] == 0:
return None
con_pixels = con_im.load()
for x in range(0, con_im .size[0]):
for y in range(0, con_im.size[1]):
# If the pixel is already white, don't bother checking it
if con_im.getpixel((x, y)) == (255, 255, 255):
continue
# Check if the pixel is outside the contour. If so, clear it
if cv2.pointPolygonTest(con, (x + lm, y + tm), False) < 0:
con_pixels[x, y] = (255, 255, 255)
return con_im
def findAndColorShapes(input_file, shapes_dest_path):
im = cv2.imread(input_file)
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 220, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
i = 0
for con in contours:
con_im = contour_to_image(con, Image.open(input_file))
if con_im is not None:
con_im.save(shapes_dest_path + "%d.png"%i)
i += 1
np_to_int() 和 rect_for_contour() 是 2 个简单的辅助函数 -
def np_to_int(np_val):
return np.asscalar(np.int16(np_val))
def rect_for_contour(con):
# Get coordinates of a rectangle around the contour
leftmost = tuple(con[con[:,:,0].argmin()][0])
topmost = tuple(con[con[:,:,1].argmin()][0])
bottommost = tuple(con[con[:,:,1].argmax()][0])
rightmost = tuple(con[con[:,:,0].argmax()][0])
return leftmost[0], topmost[1], rightmost[0], bottommost[1]