Pillow, OpenCVで画像にwatermarkをつける

pythonでwatermark

pythonで画像にwatermarkをつける2つの方法を学習しました

  1. PIllowを使ってwatermarkをつける
  2. OpenCVでwatermarkをつける

PIllowを使ってwatermarkをつける

画像右下に「watermark」の文字を追加

最初に pip3 install pillow しておく。

PIL = Python Imaging Library

PIL の Image で元画像を開く(今回はサイズ変更不要な画像を使用)

from PIL import Image, ImageDraw, ImageFont

# Create an Image Object from an Image
im = Image.open('images/sample.jpg')
width, height = im.size

PIL の ImageDraw を使ってWatermarkの設定を行う

text 部分に、表示させたい文字を入力

font で、フォントとサイズを設定する

# Watermark Settings
draw = ImageDraw.Draw(im)
text = "watermark"                  # 好きな文字を入力
font = ImageFont.truetype('arial.ttf', 36)
textwidth, textheight = draw.textsize(text, font)

元画像のどこにwatermarkを表示させたいかを指定する

今回は右下に表示(左上の場合は、単純に x = 10, y = 10)

# Bottom Right Corner: x,y coordinates
margin = 10
x = width - textwidth - margin
y = height - textheight - margin

# Top Left Corner: x,y coordinates  画像左上に付けたい場合
# x = 10
# y = 10

watermarkを元画像に追加し、show() で表示、save() で、保存先と名称を指定する

# Add Watermark
draw.text((x, y), text, font=font)
im.show()

# Name and Save watermarked Image 任意の名前で保存
im.save('images/watermark1.jpg')

全体のコードはこちらです。

from PIL import Image, ImageDraw, ImageFont

# Create an Image Object from an Image
im = Image.open('images/sample.jpg')
width, height = im.size

# Watermark Settings
draw = ImageDraw.Draw(im)
text = "watermark"                  # 好きな文字を入力
font = ImageFont.truetype('arial.ttf', 36)
textwidth, textheight = draw.textsize(text, font)

# Bottom Right Corner: x,y coordinates
margin = 10
x = width - textwidth - margin
y = height - textheight - margin

# Top Left Corner: x,y coordinates  画像左上に付けたい場合
# x = 10
# y = 10

# Add Watermark
draw.text((x, y), text, font=font)
im.show()

# Name and Save watermarked Image 任意の名前で保存
im.save('images/watermark1.jpg')

文字ではなく、Pillow を使った、「2枚の画像の合成」は、こちらを参照


OpenCVでwatermarkをつける

画像中央に「png」保存した画像をwatermarkで表示させる

今回利用したwatermark画像:

OpenCVで合成しようとしたところ、「アルファブレンドを行う」という言葉が頻出。念のためメモ。「画像のどの部分をどの程度透明にするかを指定する」ということらしい。

2枚の画像を単純に合成する方法はこちらを参照

最初にcv2 をインポートし、元画像とwatermark画像(PNG)を読み込む

cv2.imread( ) で、ファイル名を入力

import cv2

# Read and Show Image
img = cv2.imread('images/sample.JPG')
watermark = cv2.imread("images/logo.PNG")

watermarkの画像サイズが大きすぎたので、リサイズ。

interpolation=cv2.INTER_AREA:「画像を大幅に縮小する場合、モアレを避けることができる」と記載してあるが、「モアレ」って。。。なんだ? こちらを参照

コンピュータによる画像処理においても、画像は画素とよばれる縦横に周期的に配置した点に分解して表現することから、印刷と同様なモアレが発生する可能性がある。画像処理の過程では、縦横画素数を整数分の1以外の大きさに縮小・変形した場合に発生しやすい。グラフィックソフトウェアにおいて縮小が単なる間引き処理であると、ありもしない模様が発生 (偽解像) する。

引用:Wikipedia

というわけで、サイズを大幅に縮小したので、 interpolation=cv2.INTER_AREA (モアレ防止)を使った。

# Resize Watermark Image サイズを縮小したい場合
wm_scale = 40
wm_width = int(watermark.shape[1] * wm_scale/100)
wm_height = int(watermark.shape[0] * wm_scale/100)
wm_dim = (wm_width, wm_height)
resized_wm = cv2.resize(watermark, wm_dim, interpolation=cv2.INTER_AREA)

watermark表示場所の設定。 今回は中央に表示。

# Center: x,y coordinates 中央に表示させたい場合
h_img, w_img, _ = img.shape
center_y = int(h_img/2)
center_x = int(w_img/2)
h_wm, w_wm, _ = resized_wm.shape
top_y = center_y - int(h_wm/2)
left_x = center_x - int(w_wm/2)
bottom_y = top_y + h_wm
right_x = left_x + w_wm

謎のROI 登場! 早速調べてみる:ROI (Rectangular Region of interest ) こちらを参照

ROI(Region of Interest)とは、画像データのうち、操作の対象として選ぶ領域のことです。
「対象領域」「注目領域」「関心領域」「窓画像」などといいます。

西住工房
# Get the Rectangular Region of interest (ROI) and name it ‘roi’
roi = img[top_y:bottom_y, left_x:right_x]

result = cv2.addWeighted(roi, 1, resized_wm, 0.3, 0)
img[top_y:bottom_y, left_x:right_x] = result

最後に保存先と名前を指定。

ラスト3行のうち、cv2.waitkey(0) のカッコ内をゼロにすると、キーボードが押されるまで処理を待つ。コードを実行すると、作成した画像がポップアップし、何かしらのキーを押すと、消える。ちなみに、カッコ内の数字を (1000) にすると1秒表示して消える。

# Where to Save, Name the Watermarked Image 任意のフォルダに保存
filename = 'images/watermarked_sample.jpg'
cv2.imwrite(filename, img)

cv2.imshow("Resized Input Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

上記をまとめたコードはこちら:

import cv2

# Read and Show Image
img = cv2.imread('images/sample.JPG')
watermark = cv2.imread("images/logo.PNG")

# Resize Watermark Image サイズを縮小したい場合
wm_scale = 40
wm_width = int(watermark.shape[1] * wm_scale/100)
wm_height = int(watermark.shape[0] * wm_scale/100)
wm_dim = (wm_width, wm_height)
resized_wm = cv2.resize(watermark, wm_dim, interpolation=cv2.INTER_AREA)

# Center: x,y coordinates 中央に表示させたい場合
h_img, w_img, _ = img.shape
center_y = int(h_img/2)
center_x = int(w_img/2)
h_wm, w_wm, _ = resized_wm.shape
top_y = center_y - int(h_wm/2)
left_x = center_x - int(w_wm/2)
bottom_y = top_y + h_wm
right_x = left_x + w_wm

# Get the Rectangular Region of interest (ROI) and name it ‘roi’
roi = img[top_y:bottom_y, left_x:right_x]

result = cv2.addWeighted(roi, 1, resized_wm, 0.3, 0)
img[top_y:bottom_y, left_x:right_x] = result

# Where to Save, Name the Watermarked Image 任意のフォルダに保存
filename = 'images/watermarked_sample.jpg'
cv2.imwrite(filename, img)

cv2.imshow("Resized Input Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

まとめ

python画像処理は奥が深い。。 他にもいろいろと便利そうなライブラリがたくさんある。今回の記事では紹介しなかった imutils も気になっているが、今回は2つのコードで疲れたのでここまでにします。

imutils を使ってみる

imutils で画像処理が簡単に出来る