I am working on an image segmentation project to identify playing cards on varying backgrounds. For my use case I care most that I accurately extract all the cards in the image; false-positives are inconvenient but not fatal. I also care that I can run the segmentation without user interaction (i.e., an algorithm like grabcut does not work for me).
So far I have the following simple algorithm based on Canny edge detection and contour selection:
# Pre-processing: Convert frame to standard size, 1024x768
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.medianBlur(gray, 9)
edges = cv2.Canny(gray, 10, 25)
_, contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
area = cv2.contourArea(box)
ratio = area / size
if ratio < 0.015:
continue
# Mark box as segment
For some (many) inputs it works well enough, or even very well:
goo.gl/photos/1NgkjWfpYamy3M2L6
However for other inputs the contour detection does not successfully disambiguate cards. The contours are grouped in ways that link cards or result in undesirable bounding boxes:
goo.gl/photos/hdxD4KmsQVtL53EC6
I've tried various improvements such as altering all the parameters, adding a thresholding step, etc. but without much success. I would love to hear your suggestions on what else I should try!
For reference (or, better yet, if you want to play along at home) I have a set of example inputs and the outputs of my current algorithm:
goo.gl/photos/HCYeiFqhG5pVNWnY9
(Apologies for all the awkward links, because this is my first post I cannot post real links or photos...)