How to Watermark Images Using OpenCV and Python

If you‘re a photographer, artist, or content creator, you‘ve probably spent a lot of time and effort creating original images. But when you share those images online, there‘s always a risk that others could use them without permission or attribution. That‘s where watermarking comes in.

Adding a watermark to your images is an effective way to protect your copyright and deter unauthorized use. A watermark is simply a logo, text, or pattern overlaid onto the image, typically with some transparency. It communicates that you own the image without obscuring the main content.

While there are many watermarking tools and services available, in this tutorial we‘ll walk through how to programmatically add watermarks to images using OpenCV and Python. OpenCV is a powerful open-source computer vision library that makes it easy to manipulate and process images.

We‘ll cover:

  • Resizing images while preserving aspect ratio
  • Creating a watermark image with transparency
  • Superimposing the watermark onto the main image
  • Controlling watermark size and opacity
  • Batch processing multiple images

OpenCV supports a wide range of image formats including JPG, PNG, TIFF, and BMP. For watermarking, PNG files are ideal because they offer transparency. So we‘ll use PNG for our watermark image.

Resizing Images with OpenCV

Before we get into watermarking, let‘s review how to resize an image using OpenCV and Python. Oftentimes you‘ll be working with high resolution photos, so you may want to downscale them first to reduce processing time. It‘s important to maintain the original aspect ratio to avoid distorting the image.

Here‘s a sample code snippet to resize an image to 50% of its original size:

import cv2

img = cv2.imread(‘original.jpg‘) print(f‘Original dimensions: {img.shape[1]} x {img.shape[0]}‘)

scale_percent = 50 new_width = int(img.shape[1] scale_percent / 100) new_height = int(img.shape[0] scale_percent / 100)

resized = cv2.resize(img, (new_width, new_height), interpolation = cv2.INTER_AREA) print(f‘Resized dimensions: {resized.shape[1]} x {resized.shape[0]}‘)

cv2.imwrite(‘resized.jpg‘, resized)

The key steps are:

  1. Read the image file with cv2.imread()
  2. Calculate the new width and height based on the desired scale percentage
  3. Resize the image using cv2.resize(), specifying the new dimensions
  4. Write the resized image to disk with cv2.imwrite()

The interpolation argument determines how to fill in pixels when resizing. For downscaling, cv2.INTER_AREA tends to give the best results. Other options include cv2.INTER_LINEAR and cv2.INTER_CUBIC.

Creating a Watermark Image

Next, we need to create our watermark image. This will typically be a logo or text with a transparent background. There are many ways to generate this programmatically, but for this example let‘s assume you already have a PNG file ready to go.

The watermark should be smaller than your main image, but still legible. A good rule of thumb is to make the watermark about 10-20% of the size of the image. Too small and it won‘t be visible, too large and it will be obtrusive.

Here‘s how to read in the watermark image with OpenCV:

watermark = cv2.imread(‘watermark.png‘, cv2.IMREAD_UNCHANGED)

Using cv2.IMREAD_UNCHANGED tells OpenCV to read the alpha channel if it exists. The alpha channel controls the transparency of each pixel in the image.

Superimposing the Watermark

Now that we have our resized main image and watermark ready, it‘s time to combine them. The key function for this is cv2.addWeighted() which performs alpha compositing.

Alpha compositing is the process of layering a foreground image with transparency over a background image. Each pixel of the output is a weighted combination of the corresponding foreground and background pixels based on the foreground‘s alpha value.

The formula for alpha compositing is:

output = (foreground * alpha) + (background * (1 - alpha))  

Where alpha ranges from 0.0 (completely transparent) to 1.0 (completely opaque). So an alpha of 0.5 would give a 50/50 blend of foreground and background.

In OpenCV, cv2.addWeighted() takes care of this math for us. We just need to specify the weight (alpha) for each input image. Here‘s a code snippet to overlay a watermark at 50% opacity onto the bottom-right corner of an image:

img = cv2.imread(‘image.jpg‘)
watermark = cv2.imread(‘watermark.png‘, cv2.IMREAD_UNCHANGED)

h_img, wimg, = img.shape h_wm, wwm, = watermark.shape

offset = 10 h_start = h_img - h_wm - offset w_start = w_img - w_wm - offset

overlay = img.copy() overlay[h_start:h_start+h_wm, w_start:w_start+w_wm] = watermark

cv2.addWeighted(overlay, 0.5, img, 0.5, 0, img)

cv2.imwrite(‘watermarked.jpg‘, img)

Let‘s break this down:

  1. Read in the main image and watermark files
  2. Get the height and width of both images
  3. Calculate the position to insert the watermark (bottom-right with a 10px offset)
  4. Create an overlay by copying the main image
  5. Insert the watermark into the overlay at the calculated position
  6. Use cv2.addWeighted() to blend the overlay and original image with 50% opacity each
  7. Write the watermarked image to disk

You can adjust the watermark‘s opacity by changing the alpha values passed to cv2.addWeighted(). For example, 0.25 and 0.75 would give a more subtle 25% opacity watermark.

Batch Processing Multiple Images

To watermark a whole collection of images, we can simply wrap our code in a loop that iterates through a directory. Here‘s a full script that resizes each image to a max width of 1000px, adds a watermark at 50% opacity to the bottom-right corner, and saves the watermarked version in an output folder:

import cv2
import os

input_folder = ‘originals‘ output_folder = ‘watermarked‘ watermark_file = ‘watermark.png‘

max_width = 1000 watermark_opacity = 0.5 offset = 10

if not os.path.exists(output_folder): os.makedirs(output_folder)

watermark = cv2.imread(watermark_file, cv2.IMREAD_UNCHANGED) h_wm, wwm, = watermark.shape

for filename in os.listdir(input_folder): if not filename.endswith((‘.jpg‘, ‘.jpeg‘, ‘.png‘, ‘.bmp‘, ‘.tif‘, ‘.tiff‘)): continue

print(f‘Processing {filename}...‘)

img = cv2.imread(os.path.join(input_folder, filename))
h_img, w_img, _ = img.shape

if w_img > max_width:
    scale = max_width / w_img
    new_width = int(w_img * scale)
    new_height = int(h_img * scale)
    img = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_AREA)
    h_img, w_img, _ = img.shape

h_start = h_img - h_wm - offset
w_start = w_img - w_wm - offset

overlay = img.copy()
overlay[h_start:h_start+h_wm, w_start:w_start+w_wm] = watermark

cv2.addWeighted(overlay, watermark_opacity, img, 1-watermark_opacity, 0, img)

output_file = os.path.join(output_folder, ‘watermarked_‘ + filename)
cv2.imwrite(output_file, img)

print(‘Done.‘)

This script introduces a few new concepts:

  • Checking if an output directory exists, and creating it if not with os.makedirs()
  • Looping through files in an input directory with os.listdir()
  • Skipping non-image files by checking the file extension
  • Using os.path.join() to construct full paths to input and output files
  • Defining constants at the top for key parameters like max width and opacity

With this automated setup, you can easily watermark a large batch of images with a single command. Just drop your unwatermarked originals into the input folder and run the script. You‘ll find your watermarked copies in the output folder.

Tips and Best Practices

When adding watermarks to your images, here are a few tips to keep in mind:

Placement: The most common watermark positions are bottom-right, bottom-left, and center. Avoid putting your watermark too close to the edge where it could be easily cropped out.

Size: Make your watermark large enough to be noticed but not so large that it overpowers the image. A good balance is usually 10-20% of the image size. You can calculate this programmatically based on the dimensions of your input image.

Opacity: Typically you‘ll want your watermark to be visible but not completely opaque. An opacity between 25-50% works well in most cases. You can use cv2.addWeighted() to control this.

Color: If your watermark is text or a simple shape, consider using a white or light color with a black outline to ensure it remains legible over different background colors in your image.

Format: It‘s best to use PNG files for watermarks because they support transparency. JPG watermarks will have an opaque white box around them which doesn‘t look as clean.

Backups: Always keep an un-watermarked version of your images as a backup. Once you add a watermark, it can be very difficult to remove, so you want to be able to go back to the originals if needed.

Remember, watermarks are not foolproof protection against image theft. A determined thief could still crop, clone, or erase your watermark. But they do act as a deterrent and help communicate that the image belongs to you.

Watermarking Alternatives

OpenCV is a great choice for watermarking because it‘s powerful, flexible, and free. But it‘s not the only option. Here are a few alternatives you might consider:

Pillow: Pillow is a popular Python imaging library that makes it easy to manipulate images, including adding watermarks. It has a simpler API than OpenCV but can‘t do as many advanced operations.

ImageMagick: ImageMagick is a command-line tool that can do pretty much anything with images, including watermarking. It‘s a good choice if you‘re comfortable working in the terminal.

Watermark.ws: If you don‘t want to code your own solution, Watermark.ws is a free online service that allows you to upload images, add customizable watermarks, and download the watermarked versions. It‘s convenient but you have less control.

Ultimately, the best watermarking approach depends on your specific needs and workflow. OpenCV is a solid choice for most people because it offers a good balance of customization and automation.

Conclusion

Watermarking your images is an important step in protecting your intellectual property online. By adding a subtle logo or text overlay, you can deter casual copying and make it clear that you own the image.

In this tutorial, you learned how to programmatically add watermarks to images using OpenCV and Python. We covered key concepts like alpha compositing, resizing images while preserving aspect ratios, and batch processing a folder of images.

The sample code provided should give you a good starting point for your own watermarking projects. Feel free to adapt it to your needs by changing the watermark style, position, opacity, etc.

With a bit of upfront work to set up your watermarking pipeline, you can ensure that your images always carry your brand as they are shared across the web. It‘s a small but important step in getting the recognition you deserve for your creative work.

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Similar Posts