OpenCV removing the background with a mask image
You can create a transparent image by creating a 4-channel BGRA image and copying the first 3 channels from the original image and setting the alpha channel using the mask image.
transparent = np.zeros((img.shape[0], img.shape[1], 4), dtype=np.uint8)
transparent[:,:,0:3] = img
transparent[:, :, 3] = mask
Background removal from images with OpenCV in Android
The Code
import cv2
import numpy as np
def process(img):
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_canny = cv2.Canny(img_gray, 10, 20)
kernel = np.ones((13, 13))
img_dilate = cv2.dilate(img_canny, kernel, iterations=1)
return cv2.erode(img_dilate, kernel, iterations=1)
def get_mask(img):
contours, _ = cv2.findContours(process(img), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
blank = np.zeros(img.shape[:2]).astype('uint8')
for cnt in contours:
if cv2.contourArea(cnt) > 500:
peri = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, peri * 0.004, True)
cv2.drawContours(blank, [approx], -1, 255, -1)
return blank
img = cv2.imread("crystal.jpg")
img_masked = cv2.bitwise_and(img, img, mask=get_mask(img))
cv2.imshow("Masked", img_masked)
cv2.waitKey(0)
The Output
The Explanation
- Import the necessary libraries:
import cv2
import numpy as np
- Define a function to process an image to be fit for proper contour detection. In the function, first convert the image to grayscale, and then detect its edges using the canny edge detector. With the edges detected, we can dilate and erode them once to give the edges more body:
def process(img):
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_canny = cv2.Canny(img_gray, 10, 20)
kernel = np.ones((13, 13))
img_dilate = cv2.dilate(img_canny, kernel, iterations=1)
return cv2.erode(img_dilate, kernel, iterations=1)
- Define a function to generate a mask for the image. After finding the contours of the image, define a grayscale blank image with the shape of the image, and draw every contour (of area greater than
400
to filter out noise) filled in onto the blank image. I also approximated the contours to smoothen things out a bit:
def get_mask(img):
contours, _ = cv2.findContours(process(img), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
blank = np.zeros(img.shape[:2]).astype('uint8')
for cnt in contours:
if cv2.contourArea(cnt) > 500:
peri = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, peri * 0.004, True)
cv2.drawContours(blank, [approx], -1, 255, -1)
return blank
- Finally, read in the image, and mask the image using the
cv2.bitwise_and
method, along with theget_mask
function we defined, which uses theprocess
function we defined. Show the masked image in the end:
img = cv2.imread("crystal.jpg")
img_masked = cv2.bitwise_and(img, img, mask=get_mask(img))
cv2.imshow("Masked", img_masked)
cv2.waitKey(0)
Transparent Background
Instead of the cv2.bitwise_and
method, you can use the cv2.merge
method:
img = cv2.imread("crystal.jpg")
img_masked = cv2.merge(cv2.split(img) + [get_mask(img)])
cv2.imwrite("masked_crystal.png", img_masked)
Resulting image (screenshot):
Explanation:
- Keeping in mind we already imported the
cv2
module and thenumpy
module asnp
. We also defined aprocess
function and aget_mask
function, we can read in the image:
img = cv2.imread("crystal.jpg")
- The
cv2.split
method takes in an image array and returns a list of every individual channel present in the image. In our case, we only have 3 channels, and in order to make the image transparent, we need a forth channel: the alpha channel. Thecv2.merge
method does the opposite ofcv2.split
; it takes in a list of individual channels and returns an image array with the channels. So next we get the bgr channels of the image in a list, and concatenate the mask of the image as the alpha channel:
img_masked = cv2.merge(cv2.split(img) + [get_mask(img)])
- Lastly we can write the four channel image into a file:
cv2.imwrite("masked_crystal.png", img_masked)
Here are some more example of the cv2.merge
method: Python cv2.merge() Examples
Related Topics
Using SQL Server Stored Procedures from Python (Pyodbc)
I Want to Reshape 2D Array into 3D Array
How to Import a File in Python With Spaces in the Name
Finding the Max Value in a Two Dimensional Array
How to Write List Elements into a Tab-Separated File
Making a Matrix in Python 3 Without Numpy Using Inputs
Making a Dictionary from Each Line in a File
How to Read a Specific Line from a Text File in Python
Delete Every Non Utf-8 Symbols from String
Check If a Key Exists in a Bucket in S3 Using Boto3
Python How to Use Excelwriter to Write into an Existing Worksheet
How to Fix the 403:Insufficient Authentication Scopes Error from Google Analytics User Deletion API
How to Execute Two Commands in Terminal Using Python'S Subprocess Module
Using Condition to Split Pandas Column of Lists into Multiple Columns.
How to Completely Remove Python from a Windows Machine
Tkinter: How to Use Threads to Preventing Main Event Loop from "Freezing"