Reputation: 11
I want to remove a watermark from a image and result looks blurry on the watermarks. I need help to fix this.
I have used the inpaint function from opencv. My code looks like this.
import cv2
import matplotlib.pyplot as plt
import numpy as np
import time
start = time.time()
IMAGE = "images/img.jpg"
MASK = "images/mask.png"
image = cv2.imread(IMAGE)
mask = cv2.imread(MASK, 0)
img = cv2.inpaint(image, mask, 0, cv2.INPAINT_NS)
cv2.imwrite("output.jpg", img)
print(time.time()-start)
Upvotes: 0
Views: 550
Reputation: 5815
There are some artifacts that the in-painting algorithm produces; it's difficult to completely get rid of them. This is my take trying to minimize the artifacts. It basically involves converting the BGR
image to LAB
, splitting the L
channel, in-painting only this channel, merging the components and then converting back to BGR
:
import cv2
# Set image path
directoryPath = "D://opencvImages//"
# Load image:
inputImage = cv2.imread(directoryPath + "GzRoc.jpg")
showImage("Input Image", inputImage)
# To LAB:
labImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2LAB)
# Split LAB Image:
L, A, B = cv2.split(labImage)
# Load mask:
maskImage = cv2.imread(directoryPath + "H5DpA.png")
showImage("Input Mask", maskImage)
# Mask to grayscale:
maskImage = cv2.cvtColor(maskImage, cv2.COLOR_BGR2GRAY)
It appears that your mask is a little bit bigger than your input image. Let’s resize
it because the in-painting algorithm needs exactly the same sizes for both images:
# Resize mask:
imageHeight, imageWidth = inputImage.shape[:2]
newSize = (imageWidth, imageHeight)
maskImage = cv2.resize(maskImage, newSize, interpolation=cv2.INTER_LINEAR)
# Threshold mask:
_, binaryMask = cv2.threshold(maskImage, 0, 255, cv2.THRESH_OTSU)
Let’s apply a little bit of morphology. Looks like a basic dilation
helps mitigating the artifacts:
# Prepare in-paint mask:
kernelSize = (3, 3)
morphoKernel = cv2.getStructuringElement(cv2.MORPH_RECT, kernelSize)
inpaintMask = cv2.morphologyEx(binaryMask, cv2.MORPH_DILATE, morphoKernel, iterations=1)
Now, let’s in-paint the L
channel, merge it with the rest of the original components and convert back to BGR
:
# In-paint the L channel:
inpaintedL = cv2.inpaint(L, inpaintMask, 0, cv2.INPAINT_NS)
# Merge LAB:
labImage = cv2.merge([inpaintedL, A, B])
# LAB to BGR:
outImage = cv2.cvtColor(labImage, cv2.COLOR_LAB2BGR)
cv2.imshow("OutImage", outImage)
cv2.waitKey(0)
This is the result:
Observation: Save your images using a lossless format such as png
, your original image is jpeg
and you can see some compression artifacts already before performing any processing.
Upvotes: 2