I'm scanning a bunch of baseball cards in protective sleeves. I'd like to crop just the card or slightly more then the exact edge of the card. I've been using Python for the past few years and would like some guidance how how best to do this. Here is a sample image.
I've reviewed some articles on OpenCV and Pillow but none are similar enough to help.
You have not said whether you want to include the blue border or just the card inside the blue border. Here is one way to do the latter in Python/OpenCV.
Input:
import cv2
import numpy as np
# read the input image
img = cv2.imread('baseball_card.jpg')
# threshold on white
lower = (210,210,210)
upper = (235,235,235)
thresh = cv2.inRange(img, lower, upper)
# apply morphology
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)
# get largest contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
# get rotated rectangle
rotrect = cv2.minAreaRect(big_contour)
(center), (width,height), angle = rotrect
box = cv2.boxPoints(rotrect)
boxpts = np.intp(box)
# draw rotated rectangle on copy of image
rotrect_img = img.copy()
cv2.drawContours(rotrect_img,[boxpts],0,(0,0,255),2)
# create mask
mask = np.zeros_like(img, dtype=np.uint8)
cv2.drawContours(mask,[boxpts],0,(255,255,255),-1)
# apply mask to input
result = cv2.bitwise_and(img, mask)
# ADDITION:
# get bounding box of rotated rectangle box
x,y,w,h = cv2.boundingRect(boxpts)
# crop image to bounding box
crop = img[y:y+h, x:x+w]
# save images
cv2.imwrite('baseball_card_thresh.jpg', thresh)
cv2.imwrite('baseball_card_morph.jpg', morph)
cv2.imwrite('baseball_card_rot_rect.jpg', rotrect_img)
cv2.imwrite('baseball_card_mask.jpg', mask)
cv2.imwrite('baseball_card_result.jpg', result)
cv2.imwrite('baseball_card_crop.jpg', crop)
# show results
cv2.imshow('thresh', thresh)
cv2.imshow('morph', morph)
cv2.imshow('rotated rectangle', rotrect_img)
cv2.imshow('mask', mask)
cv2.imshow('result', result)
cv2.imshow('crop', crop)
cv2.waitKey(0)
Threshold Image:
Morphology Cleaned Image:
Rotated Rectangle Image:
Mask Image:
Result Image:
Cropped Image: