Reputation: 39
Here is a sample image of signature :
How to get the signature from this image without background so that I can paste it over user image. What if background is not white?
I have tried this, how to customize it for different background colors?
Upvotes: 0
Views: 8256
Reputation: 4561
It is quite a process, mainly because there are a number of steps to add an image on top of an image of a different size. I advice you to check out all intermediate steps in the code below, to understand what happens.
I used the HSV-colorspace to separate the signature from the background, this is easy to adapt if the signature or background have other colors.
I have not found python bindings for the copyTo()
-method used by @BahramdunAdil. You could use numpy.copyto()
functionality instead. For that I'll refer you to this answer.
I used a different technique: to add the image on top of another, first a subimage of the same size as the signature is created. The signature can be added to the subimage, which is then put back in the main image.
Alternatively, you can take the thresholded signature and use @renedv1's method to save an alpha image. Use the sign_masked
image for that. Because of the HSV-range you can create a cleaner result. (Note: account for the fact that sign_masked has a black background)
Code:
import numpy as np
import cv2
# load image
sign = cv2.imread("sign.jpg")
bg_img = cv2.imread("green_area.jpg")
# Convert BGR to HSV
hsv = cv2.cvtColor(sign, cv2.COLOR_BGR2HSV)
# define range of HSV-color of the signature
lower_val = np.array([0,0,0])
upper_val = np.array([179,255,150])
# Threshold the HSV image to get a mask that holds the signature area
mask = cv2.inRange(hsv, lower_val, upper_val)
# create an opposite: a mask that holds the background area
mask_inv= cv2.bitwise_not(mask)
# create an image of the signature with background excluded
sign_masked = cv2.bitwise_and(sign,sign,mask=mask)
# get the dimensions of the signature
height, width = sign.shape[:2]
# create a subimage of the area where the signature needs to go
placeToPutSign = bg_img[0:height,0:width]
# exclude signature area
placeToPutSign_masked = cv2.bitwise_and(placeToPutSign, placeToPutSign, mask=mask_inv)
# add signature to subimage
placeToPutSign_joined = cv2.add(placeToPutSign_masked, sign_masked)
# put subimage over main image
bg_img[0:height,0:width] = placeToPutSign_joined
# display image
cv2.imshow("result", bg_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Upvotes: 1
Reputation: 131
Just started with Python myself but thought I'd have a go at a solution - came up with this:
#!/usr/bin/python2
import cv2
import numpy as np
file_name = "/tmp/signature.jpg" # your signature image...
image = cv2.imread(file_name, 1)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGBA)
# note: [R,G,B,255] below, so first 3 numbers [255,255,255] are your white
# background pixels to be converted to RGBA setting of [0,0,0,0] (transparent)
image[np.all(image == [255, 255, 255, 255], axis=2)] = [0, 0, 0, 0]
cv2.imwrite("/tmp/signature-transparent.png", image)
This script will grab your signature.jpg, make a transparent background from all the white pixels it finds, then write it to signature.png.
Looks like this:
However it's not exactly clean around the edges! Anyone out there who can sort that?
Upvotes: 3
Reputation: 6079
You should consider the steps below: for example, pretend it is your user image:
Now go with these steps:
cv::namedWindow("result", cv::WINDOW_FREERATIO);
cv::Mat signatureImg = cv::imread(R"(izrMq.jpg)");
cv::Mat userImg = cv::imread(R"(user_image.jpg)");
// make a mask
cv::Mat mask;
cv::cvtColor(signatureImg, mask, cv::COLOR_BGR2GRAY);
cv::threshold(mask, mask, 150, 255, cv::THRESH_BINARY_INV);
// now copy
cv::Mat submat = userImg(cv::Rect(userImg.cols-signatureImg.cols, userImg.rows-signatureImg.rows, signatureImg.cols, signatureImg.rows));
signatureImg.copyTo(submat, mask);
cv::imshow("result", userImg);
cv::waitKey();
And it is the result:
Hope it helps!
Upvotes: 0