Python Watermarking Made Easy: A Comprehensive Comparison of OpenCV, PIL, and filestools
Watermarking images is an essential task for photographers, artists, and anyone who wants to protect their visual content from unauthorized use. In the Python world, there are many libraries that allow you to add watermarks to your images. In this article, we will compare three popular Python ways for watermarking images: OpenCV, PIL (Python Imaging Library), and filestools. For the last one you only need one line of code!
In this article, I will demo the image watermarking features using a photo that I took from Philip Island, Victoria, Australia. The original photo is here. Feel free to download it for your convenience.
OpenCV is a comprehensive computer vision library that provides extensive image processing functions, including the ability to add text watermarks to images. While OpenCV is not specifically designed for adding watermarks, it still provides the flexibility and control to do so. However, using OpenCV to add watermarks can be challenging, especially for those who are not familiar with the library. Additionally, achieving image-based watermarks with OpenCV requires some manual processing.
Anyway, let’s have a look at how OpenCV can achieve this task for us.
Before everything, make sure that you need to install the library if you haven’t. Simply use pip
as follows.
pip install opencv-python
To use OpenCV in Python code, we need to import the cv2
module. In order to create this demo easier, I also want to import matplotlib
so that I can display the image on the fly.
import cv2
import matplotlib.pyplot as plt
OpenCV makes it very easy to read an image from a local path. All you need to do is use the imread
function.
img = cv2.imread("my_photo.jpeg")
The following function is optional, I created this function to conveniently display the image in-line in a Jupyter Notebook environment. Feel free to use it if you want to check how the image object looks like.
def show_image(img, is_cv=False):
if is_cv:
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.figure(figsize=(16, 9))
plt.imshow(img)
plt.axis("off")
plt.show()
In the above function, I added is_cv
to specify if this image object is from OpenCV. We need this because we may want to reuse this function for the PIL library later on. The OpenCV image object use BGR by default instead of RGB. Therefore, we need to use the cvtColor()
function to convert the encoding method.
After that, the matplotlib
is used to display the image. In my case, I gave a specific size that fits my browser window. Also, we can turn the axis off since we are just displaying an image. The imshow()
is the key function that displays the image object.
So, we can simply display the image by calling the function we just created.
show_image(img, is_cv=True)
Now, let’s create a string which is the text that we want to add to the image as the watermark. Then, we need to configure the font. There are several OpenCV built-in font styles that can be chosen. The font_scale
will decide the size of the watermark text later on. Lastly, we can create a tuple as the colour. The (255, 255, 255)
will make the watermark text white colour.
watermark_text = "Christopher Tao @TDS"# Set the font, font scale, and color of the text
font = cv2.FONT_HERSHEY_TRIPLEX
font_scale = 5
color = (255, 255, 255)
The next thing is to decide the position of the watermark. The getTextSize()
method will help us to get the size of the text. Meanwhile, we can get the dimension of the image from its shape
attribute.
# Get the size of the text
text_size, _ = cv2.getTextSize(watermark_text, font, font_scale, thickness=20)# Calculate the position of the text
x = int((img.shape[1] - text_size[0]) / 2)
y = int((img.shape[0] + text_size[1]) / 2)
However, it is necessary to emphasize that the image is “H x W” while the text size is “W x H”. Therefore, when we calculate the coordinate, we need to use the second item (width) from the image shape to subtract the first item (width) from the text size, and vice versa.
Finally, we can use the putText()
method to add the watermark text to the image as follows, using all the parameters we defined above.
# Add the text watermark to the image
cv2.putText(img, watermark_text, (x, y), font, font_scale, color, thickness=2)
Let’s see the outcome. Succeed!
PIL (Python Imaging Library) is a popular third-party library for image processing in Python that provides a simpler and more straightforward way to add watermarks to images than OpenCV. However, it still requires some steps to achieve watermarking. PIL is a good choice for those who need a reliable and relatively simple way to add watermarks to their images, without the need for extensive computer vision capabilities.
Similarly, before using the PIL library, we need to install it as follows.
pip install pillow
For the PIL library, we need the following 3 modules.
Image
module: provides a class for representing and manipulating images in PIL.ImageDraw
module: provides a set of functions for drawing on images, including lines, rectangles, circles, and text.ImageFont
module: provides a class for loading and manipulating fonts in PIL, including setting the font size, style, and colour.
from PIL import Image, ImageDraw, ImageFont
Then, we can use the Image
module to open the image as follows. We can also reuse the show_image()
method we defined previously to display the original image.
img = Image.open('my_photo.jpeg')
show_image(img)
To manipulate the image, we need to create an ImageDraw
instance from the image object.
# Create an ImageDraw object
draw = ImageDraw.Draw(img)
The next step is a bit tricky. Unlike OpenCV has built-in font styles, PIL can only make use of a separate “.ttf” file. Although all the operating systems will have some font styles, we still need to know what are existing so that we can use them.
In this case, I would suggest the easiest way that is to use the matplotlib
to display the available fonts as follows, unless you have a specific font style to use.
import matplotlibmatplotlib.font_manager.findSystemFonts(fontpaths=None, fontext='ttf')
Below are some available fonts in my case.
Now, we can start to set the parameters.
# Prepare watermark text
font = ImageFont.truetype('Humor-Sans.ttf', size=150)# Calculate the size of the watermark text
t_width, t_height = draw.textsize(watermark_text, font)
# Calculate the x and y coordinates for the text
x = int((img.size[0] - t_width) / 2)
y = int((img.size[1] - t_height) / 2)
We can use the ImageFont.truetype
to create a font with a certain size for the watermark. After that, we can get the text size from the draw
object using the textsize()
method. after that, the way of calculating the coordinate is the same as what we did in the OpenCV demo.
Lastly, we can use the text()
method of the draw
object to add the watermark.
# Add the text as a watermark on the image
draw.text((x, y), watermark_text, font=font, fill=(255, 255, 255))
filestools
is a third-party Python library that provides a range of useful tools for file and image processing. It includes functions for displaying directory structures like the tree
command in Linux, comparing file differences like the diff
command, and adding watermarks to images using the marker
command. Additionally, filestools can be used to convert curl requests to Python request code. Although the library was created by a Chinese developer, it is still widely accessible and usable by Python developers, despite some of the logs being in Chinese.
Similarly, to use the library, we can install it as follows.
pip install filestools
Then, let’s add the watermark text to the image. we can import the add_mark()
function from the watermarker
module of the library as follows. Then, this function will do everything we need.
from watermarker.marker import add_markadd_mark(file="my_photo.jpeg",
out="watermarked",
mark=watermark_text,
size=60,
color="#ffffff",
opacity=0.5,
angle=30,
space=60)
The out
argument is a name of a directory, so the watermarked image will be output into this directory. The opacity
specifies the transparency of the watermark. We can certainly do this using OpenCV and PIL, but it requires more steps and complex logic. Apart from that, the watermark will also be rendered as a “pattern” on the image. So, we are allowed to give an angle
of the text, as well as the space
which defines the space between the text instances.
After running this function, it says “successfully saved”. Now, we can check our working directory. We should be able to find the new sub-directory with a watermarked image in it.
Here is the watermarked photo once we open it.
In this article, we compared three popular Python libraries for watermarking images: OpenCV, PIL (Python Imaging Library), and filestools. OpenCV is a comprehensive computer vision library that provides extensive image processing functions, while PIL provides a simpler and more straightforward way to add watermarks to images. However, both libraries require multiple steps and some manual processing to achieve watermarking. On the other hand, filestools provides a one-line solution for adding watermarks to images, making it the easiest and most streamlined library of the three. Overall, while OpenCV and PIL offer more advanced image processing capabilities, filestools is the clear winner in terms of ease of use for watermarking images.
If you feel my articles are helpful, please consider joining Medium Membership to support me and thousands of other writers! (Click the link above)
Unless otherwise noted all images are by the author
Python Watermarking Made Easy: A Comprehensive Comparison of OpenCV, PIL, and filestools
Watermarking images is an essential task for photographers, artists, and anyone who wants to protect their visual content from unauthorized use. In the Python world, there are many libraries that allow you to add watermarks to your images. In this article, we will compare three popular Python ways for watermarking images: OpenCV, PIL (Python Imaging Library), and filestools. For the last one you only need one line of code!
In this article, I will demo the image watermarking features using a photo that I took from Philip Island, Victoria, Australia. The original photo is here. Feel free to download it for your convenience.
OpenCV is a comprehensive computer vision library that provides extensive image processing functions, including the ability to add text watermarks to images. While OpenCV is not specifically designed for adding watermarks, it still provides the flexibility and control to do so. However, using OpenCV to add watermarks can be challenging, especially for those who are not familiar with the library. Additionally, achieving image-based watermarks with OpenCV requires some manual processing.
Anyway, let’s have a look at how OpenCV can achieve this task for us.
Before everything, make sure that you need to install the library if you haven’t. Simply use pip
as follows.
pip install opencv-python
To use OpenCV in Python code, we need to import the cv2
module. In order to create this demo easier, I also want to import matplotlib
so that I can display the image on the fly.
import cv2
import matplotlib.pyplot as plt
OpenCV makes it very easy to read an image from a local path. All you need to do is use the imread
function.
img = cv2.imread("my_photo.jpeg")
The following function is optional, I created this function to conveniently display the image in-line in a Jupyter Notebook environment. Feel free to use it if you want to check how the image object looks like.
def show_image(img, is_cv=False):
if is_cv:
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.figure(figsize=(16, 9))
plt.imshow(img)
plt.axis("off")
plt.show()
In the above function, I added is_cv
to specify if this image object is from OpenCV. We need this because we may want to reuse this function for the PIL library later on. The OpenCV image object use BGR by default instead of RGB. Therefore, we need to use the cvtColor()
function to convert the encoding method.
After that, the matplotlib
is used to display the image. In my case, I gave a specific size that fits my browser window. Also, we can turn the axis off since we are just displaying an image. The imshow()
is the key function that displays the image object.
So, we can simply display the image by calling the function we just created.
show_image(img, is_cv=True)
Now, let’s create a string which is the text that we want to add to the image as the watermark. Then, we need to configure the font. There are several OpenCV built-in font styles that can be chosen. The font_scale
will decide the size of the watermark text later on. Lastly, we can create a tuple as the colour. The (255, 255, 255)
will make the watermark text white colour.
watermark_text = "Christopher Tao @TDS"# Set the font, font scale, and color of the text
font = cv2.FONT_HERSHEY_TRIPLEX
font_scale = 5
color = (255, 255, 255)
The next thing is to decide the position of the watermark. The getTextSize()
method will help us to get the size of the text. Meanwhile, we can get the dimension of the image from its shape
attribute.
# Get the size of the text
text_size, _ = cv2.getTextSize(watermark_text, font, font_scale, thickness=20)# Calculate the position of the text
x = int((img.shape[1] - text_size[0]) / 2)
y = int((img.shape[0] + text_size[1]) / 2)
However, it is necessary to emphasize that the image is “H x W” while the text size is “W x H”. Therefore, when we calculate the coordinate, we need to use the second item (width) from the image shape to subtract the first item (width) from the text size, and vice versa.
Finally, we can use the putText()
method to add the watermark text to the image as follows, using all the parameters we defined above.
# Add the text watermark to the image
cv2.putText(img, watermark_text, (x, y), font, font_scale, color, thickness=2)
Let’s see the outcome. Succeed!
PIL (Python Imaging Library) is a popular third-party library for image processing in Python that provides a simpler and more straightforward way to add watermarks to images than OpenCV. However, it still requires some steps to achieve watermarking. PIL is a good choice for those who need a reliable and relatively simple way to add watermarks to their images, without the need for extensive computer vision capabilities.
Similarly, before using the PIL library, we need to install it as follows.
pip install pillow
For the PIL library, we need the following 3 modules.
Image
module: provides a class for representing and manipulating images in PIL.ImageDraw
module: provides a set of functions for drawing on images, including lines, rectangles, circles, and text.ImageFont
module: provides a class for loading and manipulating fonts in PIL, including setting the font size, style, and colour.
from PIL import Image, ImageDraw, ImageFont
Then, we can use the Image
module to open the image as follows. We can also reuse the show_image()
method we defined previously to display the original image.
img = Image.open('my_photo.jpeg')
show_image(img)
To manipulate the image, we need to create an ImageDraw
instance from the image object.
# Create an ImageDraw object
draw = ImageDraw.Draw(img)
The next step is a bit tricky. Unlike OpenCV has built-in font styles, PIL can only make use of a separate “.ttf” file. Although all the operating systems will have some font styles, we still need to know what are existing so that we can use them.
In this case, I would suggest the easiest way that is to use the matplotlib
to display the available fonts as follows, unless you have a specific font style to use.
import matplotlibmatplotlib.font_manager.findSystemFonts(fontpaths=None, fontext='ttf')
Below are some available fonts in my case.
Now, we can start to set the parameters.
# Prepare watermark text
font = ImageFont.truetype('Humor-Sans.ttf', size=150)# Calculate the size of the watermark text
t_width, t_height = draw.textsize(watermark_text, font)
# Calculate the x and y coordinates for the text
x = int((img.size[0] - t_width) / 2)
y = int((img.size[1] - t_height) / 2)
We can use the ImageFont.truetype
to create a font with a certain size for the watermark. After that, we can get the text size from the draw
object using the textsize()
method. after that, the way of calculating the coordinate is the same as what we did in the OpenCV demo.
Lastly, we can use the text()
method of the draw
object to add the watermark.
# Add the text as a watermark on the image
draw.text((x, y), watermark_text, font=font, fill=(255, 255, 255))
filestools
is a third-party Python library that provides a range of useful tools for file and image processing. It includes functions for displaying directory structures like the tree
command in Linux, comparing file differences like the diff
command, and adding watermarks to images using the marker
command. Additionally, filestools can be used to convert curl requests to Python request code. Although the library was created by a Chinese developer, it is still widely accessible and usable by Python developers, despite some of the logs being in Chinese.
Similarly, to use the library, we can install it as follows.
pip install filestools
Then, let’s add the watermark text to the image. we can import the add_mark()
function from the watermarker
module of the library as follows. Then, this function will do everything we need.
from watermarker.marker import add_markadd_mark(file="my_photo.jpeg",
out="watermarked",
mark=watermark_text,
size=60,
color="#ffffff",
opacity=0.5,
angle=30,
space=60)
The out
argument is a name of a directory, so the watermarked image will be output into this directory. The opacity
specifies the transparency of the watermark. We can certainly do this using OpenCV and PIL, but it requires more steps and complex logic. Apart from that, the watermark will also be rendered as a “pattern” on the image. So, we are allowed to give an angle
of the text, as well as the space
which defines the space between the text instances.
After running this function, it says “successfully saved”. Now, we can check our working directory. We should be able to find the new sub-directory with a watermarked image in it.
Here is the watermarked photo once we open it.
In this article, we compared three popular Python libraries for watermarking images: OpenCV, PIL (Python Imaging Library), and filestools. OpenCV is a comprehensive computer vision library that provides extensive image processing functions, while PIL provides a simpler and more straightforward way to add watermarks to images. However, both libraries require multiple steps and some manual processing to achieve watermarking. On the other hand, filestools provides a one-line solution for adding watermarks to images, making it the easiest and most streamlined library of the three. Overall, while OpenCV and PIL offer more advanced image processing capabilities, filestools is the clear winner in terms of ease of use for watermarking images.
If you feel my articles are helpful, please consider joining Medium Membership to support me and thousands of other writers! (Click the link above)
Unless otherwise noted all images are by the author