Matthew Liu
Matthew Liu

Reputation: 53

How to recognize multiple photos on a white background using openCV-python?

Basically, I have scanned in many old photos using our printer. About four photos fit on each page of the scan (around the four corners of the page), and the white space isn't always completely white. I want to use openCV to automatically crop them into individual photos. Need suggestions for a way to tackle this problem, thanks!

I thought about detecting the shape of the four rectangles on the page to get the coordinate or using opencv grabCut... I don't know

I've tried to use PIL, but couldn't crop the photos correctly since some photos also had the same color as the background which would cause the crop to end prematurely.

This is a rough sketch of what it looks like

This is a rough sketch of what it looks like (except they would be actual photos of people)

Upvotes: 4

Views: 2186

Answers (1)

nathancy
nathancy

Reputation: 46680

Here's an approach based on the assumption that the photos will not be intersecting each other

  • Convert to grayscale and Gaussian blur
  • Threshold image
  • Find contours and obtain bounding box contours
  • Extract ROI

Threshold image

enter image description here

Next we obtain the contours using cv2.findContours() and grab the bounding boxes using cv2.boundingRect(). We can then extract the ROIs with

x,y,w,h = cv2.boundingRect(c)
ROI = original[y:y+h, x:x+w]

Here's the results

Photo #1

enter image description here

Photo #2

enter image description here

Photo #3

enter image description here

Photo #4

enter image description here

import cv2

image = cv2.imread('1.png')
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (3, 3), 0)
thresh = cv2.threshold(blurred, 230,255,cv2.THRESH_BINARY_INV)[1]

# Find contours
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

# Iterate thorugh contours and filter for ROI
image_number = 0
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
    ROI = original[y:y+h, x:x+w]
    cv2.imwrite("ROI_{}.png".format(image_number), ROI)
    image_number += 1

cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey(0)

Upvotes: 4

Related Questions