Last active
August 13, 2022 03:41
-
-
Save ES-Alexander/1cd2f32d3bd379faffd3b881c0e3ba47 to your computer and use it in GitHub Desktop.
Clean up a drawing and add a transparent background
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
Cleans up a drawing, and creates grey, blue, and red variants. | |
Blue and red are saved with a transparent background. | |
Grey is saved as single channel. | |
Author: ES-Alexander | |
License: MIT (a.k.a. free use, but not my problem if it doesn't work for you) | |
Created in response to: | |
https://www.reddit.com/r/opencv/comments/wmyuyh/question_remove_paper_background_from_sketches/ | |
''' | |
from pathlib import Path | |
import numpy as np | |
import cv2 | |
UINT8_MAX = 2**8 - 1 | |
# must be odd - use a bigger number for larger / more rough textures, but also adds more blur | |
BACKGROUND_TEXTURE_SIZE = 3 | |
# value between 0 and 1, for the saturation of the variants | |
SATURATION = 0.7 | |
path = Path('path/to/image.jpg') | |
image = cv2.imread(str(path)) | |
grey = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) | |
blur = cv2.GaussianBlur(grey, (BACKGROUND_TEXTURE_SIZE,BACKGROUND_TEXTURE_SIZE), 0) | |
# threshold, and choose the least lossy result | |
tri, thresh_tri = cv2.threshold(blur, 0, UINT8_MAX, | |
cv2.THRESH_TRUNC+cv2.THRESH_TRIANGLE) | |
otsu, thresh_otsu = cv2.threshold(blur, 0, UINT8_MAX, | |
cv2.THRESH_TRUNC+cv2.THRESH_OTSU) | |
thresh = thresh_otsu if otsu > tri else thresh_tri | |
norm = cv2.normalize(thresh, None, 0, UINT8_MAX, cv2.NORM_MINMAX) | |
opacity = UINT8_MAX - norm | |
# light variants | |
full = np.ones_like(opacity) * UINT8_MAX | |
bright = np.uint8(full * SATURATION) | |
light_norm = np.uint8(norm * SATURATION) | |
light_blue = cv2.merge((bright, light_norm, light_norm, opacity)) | |
light_red = cv2.merge((light_norm, light_norm, bright, opacity)) | |
# dark variants | |
black = np.zeros_like(opacity) | |
dark = np.uint8(opacity * SATURATION) | |
dark_blue = cv2.merge((dark, black, black, opacity)) | |
dark_red = cv2.merge((black, black, dark, opacity)) | |
image_display = cv2.merge(list(cv2.split(image))+[full]) | |
grey_display = cv2.merge([norm]*3+[full]) | |
display = cv2.vconcat(( | |
cv2.hconcat((image_display, grey_display)), | |
cv2.hconcat((light_blue, light_red)), | |
cv2.hconcat((dark_blue, dark_red)), | |
)) | |
cv2.imshow('display', display) | |
cv2.waitKey(0) | |
cv2.imwrite('results.png', display) | |
output_path = path.with_stem(path.stem+'_processed') | |
cv2.imwrite(str(output_path.with_stem(path.stem+'_grey')), norm) | |
cv2.imwrite(str(path.with_stem(path.stem+'_light_blue').with_suffix('.png')), light_blue) | |
cv2.imwrite(str(path.with_stem(path.stem+'_light_red').with_suffix('.png')), light_red) | |
cv2.imwrite(str(path.with_stem(path.stem+'_dark_blue').with_suffix('.png')), dark_blue) | |
cv2.imwrite(str(path.with_stem(path.stem+'_dark_red').with_suffix('.png')), dark_red) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Indicative results
Good performance
OK performance (uneven lighting + large variation in pencil stroke darkness)