OpenCV batch removal of background

Viewed 92

I have a collection of 14,000 smallish coins and objects to catalog. I'm looking for a way to batch them such that I can photograph the front and back of each then create an output that 1) crops to the object (increased a bit for margin), 2) replaces the background with a transparency (some objects have cutouts), then 3) creates a .png with the masked alpha channel.

I've been able to get simple round coins to this result pretty easily using OpenCV, and I can apply the same settings across many of them. However, coins that are super shiny or with strange shapes are the issue. I really can't take the time to individually tweak the parameters for every photo as I'll be here for another year.

The smoothest background seems to be an iPad with a retina display. I've tried lots of other backgrounds to get rid of texture but using a macro lens on a DSLR tethered to the laptop means every bump and ripple is visible. I've tried lots of different lighting. I'm open to any suggestions for techniques or backgrounds to make the images easier to batch process.

Also, some coins have green that's quite similar to the background so when I apply, it gets rid of more than the background. Instead, I'd vary the background from green to gray to blue depending on the object. For this I've tried sampling the image in the top 10x10 to determine the color range of the background but even knowing that I haven't hit on the right combination of contouring and grayscale or HSV. I also tried subtracting a background image without the object, but the exposure doesn't match the exposure of the object pic so the backgrounds are different colors and won't subtract.

Further complicating the batch processing, the camera adjusts the exposure so what appears to be a bright green background in one image is suddenly a darker green. In fact, this can happen just by turning the coin over and having a brighter set of colors.

These two photos are versions representative of the issue using a green background:

Looking for any suggestions about how to accomplish this with a script, using any python libraries (i've been using OpenCV).

import numpy as np

image = cv2.imread("round_object.jpg", cv2.IMREAD_UNCHANGED)

gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray_image, 80, 255, cv2.THRESH_BINARY) # needs to be 140 for the kokopelli
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

mask = np.zeros(image.shape[:2], dtype="uint8")
for c in contours:
    cv2.drawContours(mask, [c], 0, (255), cv2.FILLED)

cv2.imshow("original", image)
cv2.imshow("gray", gray_image)
cv2.imshow("mask", mask)
cv2.waitKey()
cv2.destroyAllWindows()
# save .png with alpha channel of mask (omitted for brevity)
0 Answers
Related