3

Given a series of photos that are watermarked, I want to isolate the watermark, and generate a mask.

I'm using Python and numpy.

I've added the pictures on top of each other:

def compare_n_img(array_of_img_paths):

img_float_array = []

for path in array_of_img_paths:
    img_float_array.append(load_img_as_float(path))

additionF = sum(img_float_array)/len(img_float_array)

addition = additionF.astype('uint8')

return addition

This, convered to grayscale, gives me this composite image.

The watermark is distinctly visible in this composite. For a human, it would be easy to trace.

What I want as a result is a white image, with the shape of the watermark filled in black. So that, if I overlay one of my watermarked images with the mask, the watermark would be completely covered.

I've tried to use edge detection and thresholding on the composite image. But I've not been able to find a way to programmatically isolate the watermark content. Much less to create a clear mask.

I'd like to do this in pure numpy, or cv2, if possible.

Red
  • 26,798
  • 7
  • 36
  • 58
Leo B
  • 111
  • 5

1 Answers1

7

You can try blurring the image before using the canny edge detector. As the detected edges would be too thin, an iteration of dilation and erosion would fix the problem.

After the edges are detected, there would most likely be a lot of noise in the background, so filtering out the contours with a small area would be effective.

Here is how it might go:

import cv2

def process(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_blur = cv2.GaussianBlur(img_gray, (3, 3), 0)
    img_canny = cv2.Canny(img_blur, 161, 54)
    img_dilate = cv2.dilate(img_canny, None, iterations=1)
    return cv2.erode(img_dilate, None, iterations=1)

def get_watermark(img):
    contours, _ = cv2.findContours(process(img), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    img.fill(255)
    for cnt in contours:
        if cv2.contourArea(cnt) > 100:
            cv2.drawContours(img, [cnt], -1, 0, -1)

img = cv2.imread("watermark.jpg")
get_watermark(img)
cv2.imshow("Watermark", img)
cv2.waitKey(0)

Output:

enter image description here

Red
  • 26,798
  • 7
  • 36
  • 58