Extracting only specific color from image with scanner artifacts

Viewed 260

I have the following problem:

I want to extract only the color of a blue pen from scanned images that also contain grayscale and black printed areas on a white page background.

I'm okay with disregarding any kind of grayscale (not colored) pixel values and only keeping the blue parts, there won't be any dominant color other than blue on the images.

It sounds like a simple task, but the problem is that through the scanning process, the entire image contains colored pixels, including blue ones, even the grayscale or black parts, so I'm not sure how to go about isolating those parts and keeping only the blue ones, here is a closeup to show what I mean:

Scanned black line with RGB artifacts

Here is what an image would look like for reference:

Input image example

I would like the output to be a new image, containing only the parts drawn / written in blue pen, in this case the drawing of the hedgehog / eye.

So I've tried to isolate an HSV range for blue-ish colors in the image using this code:

img = cv.imread("./data/scan_611a720bcd70bafe7beb502d.jpg")
img_hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)

# accepted color range for blue pen
lower_blue = np.array([90, 35, 140])
upper_blue = np.array([150, 255, 255])

# preparing the mask to overlay
mask = cv.inRange(img_hsv, lower_blue, upper_blue)
inverted_mask = cv.bitwise_not(mask)
mask_blur = cv.GaussianBlur(inverted_mask, (5, 5), 0)
ret, mask_thresh = cv.threshold(mask_blur, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)

# The black region in the mask has the value of 0,
# so when multiplied with original image removes all non-blue regions
result = cv.bitwise_and(img, img, mask=mask)

cv.imshow("Result", mask_thresh)
k = cv.waitKey(0)

However the result is this:

Result image with attempted color isolation method

Many parts of the picture that are drawn in black such as the cloud image are not removed since as mentioned, they contain blue / colored pixels due to the scanning process.

Is there any method that would allow for a clean isolation of those blue parts of the image even with those artifacts present? The solution would need to work for any kind of image like this, the one given is just an example, but as mentioned the only color present would be the blue pen apart from the grey/black areas.

2 Answers

Maybe try the opposite- search for black parts first and then do some erosion around this black mask and remove all around it before you are searching for the blue. The "main" color in the cloud is still black so you can play around this.

You should realign the color planes of your scan. Then you're at least rid of those color fringes. I'd recommend scanning a sheet of graph paper to calibrate.

This is done using OpenCV's findTransformECC.

Complete examples can be found here:

And here's specific code to align the color planes of the picture given in the question:

https://gist.github.com/crackwitz/b8867b46f320eae17f4b2684416c79ea

(all it does is split the color planes, call findTransformECC and warpPerspective, merge the color planes)

before and after color plane alignment

Related