I would like to find an area in about 1,5K images which are all in a similar format. They all are scans of painted or photographed images of persons. They all feature the same color card. The color cards may be placed on either side of the image (see sample image below).
The result should be an image, only containing the person's portrait.
I am able to find the color card with opencv template matching:
import cv2
import numpy as np
method = cv2.TM_SQDIFF_NORMED
# Read the images from the file
img_rgb = cv2.imread('./imgs/test_portrait.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('./portraet_color_card.png', 0)
w, h = template.shape[::-1]
result = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = .97
loc = np.where(result >= threshold)
for pt in zip(*loc[::-1]):
print("Found:", pt)
cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,255,255), 2)
cv2.imwrite('result.png',img_rgb)
Output:
Found: (17, 303)
Found: (18, 303)
Found: (17, 304)
Found: (18, 304)
With the coordinates and the image dimensions, I am able to determine if the image is left or right and can crop the image. The result is far from perfect, as the borders still are there.
Is there a better way to extract the portraits from the images? I would prefer to work with python and opencv but I am open to other suggestions on how to solve this problem for a larger number of images.