はじめに
PILとPillowの関係
PIL (Python Imaging Library) は、Pythonで画像処理を行うための歴史あるライブラリです。しかし、PIL自体は2011年を最後に更新が止まってしまいました。
そこで登場したのが Pillow です。PillowはPILの後継プロジェクトとして開発され、現在も活発にメンテナンスされています。PillowはPILと互換性を保ちながら、新しいPythonバージョンや画像形式に対応しています。
Pillowでできること
Pillowを使うと、以下のような画像処理が可能になります。
- 画像の入出力: JPEG、PNG、GIF、BMP、TIFFなど、多様な形式に対応
- 画像の編集: リサイズ、回転、トリミング、反転
- 画像の加工: フィルター適用、明るさ調整、カラーモード変換
- 画像の生成: 新規画像の作成、図形や文字の描画
Webアプリケーションでのサムネイル生成、機械学習での画像前処理、データ分析での可視化など、幅広い場面で活用されています。
インストール方法
Pillowはpipコマンドで簡単にインストールできます。
pip install Pillow
インストール後、以下のコードで正しくインストールされたか確認できます。
from PIL import Image
print(Image.__version__)
コード内ではPILという名前でインポートしますが、これはPILとの互換性を保つための設計です。実際にインストールするのはPillowパッケージです。
Pillowの基本操作
画像の読み込みと保存
まずは画像ファイルを読み込んで、別の名前で保存してみましょう。
from PIL import Image
# 画像を読み込む
img = Image.open('sample.jpg')
# 画像を保存する
img.save('output.jpg')
Image.open()は画像ファイルを開き、画像オブジェクトを返します。このオブジェクトに対して様々な処理を行い、最後にsave()で保存します。
画像サイズの確認
画像の基本情報を確認する方法を見ていきましょう。
from PIL import Image
img = Image.open('sample.jpg')
# サイズ(幅, 高さ)
print(f"サイズ: {img.size}") # 例: (1920, 1080)
# 幅と高さを個別に取得
width, height = img.size
print(f"幅: {width}px, 高さ: {height}px")
# 画像形式
print(f"形式: {img.format}") # 例: JPEG
# カラーモード
print(f"モード: {img.mode}") # 例: RGB
カラーモードは画像の色の表現方法を示します。
-
RGB: フルカラー(赤・緑・青の3チャンネル) -
RGBA: フルカラー + 透明度 -
L: グレースケール(白黒) -
1: 二値画像(完全な白か黒)
画像形式の変換
異なる形式で保存する際は、save()の引数にファイル名を指定するだけです。拡張子から自動的に形式が判断されます。
from PIL import Image
# JPEGファイルを読み込む
img = Image.open('sample.jpg')
# PNG形式で保存
img.save('output.png')
# GIF形式で保存
img.save('output.gif')
特定の形式を明示的に指定することもできます。
# 形式を明示的に指定
img.save('output.png', format='PNG')
画像の編集
リサイズ(サイズ変更)
画像のサイズを変更する際はresize()メソッドを使います。
from PIL import Image
img = Image.open('sample.jpg')
# 新しいサイズを指定(幅, 高さ)
new_size = (800, 600)
img_resized = img.resize(new_size)
img_resized.save('resized.jpg')
高品質なリサイズを行う場合は、リサンプリングアルゴリズムを指定します。
# LANCZOSアルゴリズムで高品質リサイズ
img_resized = img.resize((800, 600), Image.Resampling.LANCZOS)
リサンプリングアルゴリズムは画像の品質を左右します。
-
LANCZOS: 最高品質(処理時間は長い) -
BICUBIC: 高品質 -
BILINEAR: 標準的な品質 -
NEAREST: 最速だが品質は低い
アスペクト比(縦横比)を保ったままリサイズする場合はthumbnail()が便利です。
# アスペクト比を保ったまま、指定サイズ内に収める
img.thumbnail((800, 600))
img.save('thumbnail.jpg')
回転
画像を回転させるにはrotate()メソッドを使います。
from PIL import Image
img = Image.open('sample.jpg')
# 反時計回りに90度回転
img_rotated = img.rotate(90)
img_rotated.save('rotated_90.jpg')
# 時計回りに90度回転(-90度指定)
img_rotated = img.rotate(-90)
img_rotated.save('rotated_minus90.jpg')
# 45度回転
img_rotated = img.rotate(45)
img_rotated.save('rotated_45.jpg')
回転時に生じる余白を透明にするにはexpandオプションを使います。
# 画像全体が収まるようにキャンバスを拡大
img_rotated = img.rotate(45, expand=True)
より簡単に90度単位で回転させるにはtranspose()が便利です。
from PIL import Image
img = Image.open('sample.jpg')
# 反時計回りに90度
img_rotated = img.transpose(Image.ROTATE_90)
# 時計回りに90度
img_rotated = img.transpose(Image.ROTATE_270)
# 180度回転
img_rotated = img.transpose(Image.ROTATE_180)
トリミング(切り抜き)
画像の一部を切り出すにはcrop()メソッドを使います。引数には切り出す範囲を(左, 上, 右, 下)の形式で指定します。
from PIL import Image
img = Image.open('sample.jpg')
# 座標(100, 100)から(500, 500)までを切り出す
# (左, 上, 右, 下)
box = (100, 100, 500, 500)
img_cropped = img.crop(box)
img_cropped.save('cropped.jpg')
画像の中央部分を切り出す例を見てみましょう。
from PIL import Image
img = Image.open('sample.jpg')
width, height = img.size
# 中央の400x400ピクセルを切り出す
crop_size = 400
left = (width - crop_size) // 2
top = (height - crop_size) // 2
right = left + crop_size
bottom = top + crop_size
img_cropped = img.crop((left, top, right, bottom))
img_cropped.save('center_cropped.jpg')
反転
画像を反転させるにはtranspose()メソッドを使います。
from PIL import Image
img = Image.open('sample.jpg')
# 左右反転
img_flipped = img.transpose(Image.FLIP_LEFT_RIGHT)
img_flipped.save('flipped_lr.jpg')
# 上下反転
img_flipped = img.transpose(Image.FLIP_TOP_BOTTOM)
img_flipped.save('flipped_tb.jpg')
画像の加工
フィルターの適用
PillowにはImageFilterモジュールが用意されており、様々なフィルターを簡単に適用できます。
from PIL import Image, ImageFilter
img = Image.open('sample.jpg')
# ぼかし
img_blur = img.filter(ImageFilter.BLUR)
img_blur.save('blur.jpg')
# 輪郭検出
img_contour = img.filter(ImageFilter.CONTOUR)
img_contour.save('contour.jpg')
# シャープ化
img_sharp = img.filter(ImageFilter.SHARPEN)
img_sharp.save('sharp.jpg')
# エッジ強調
img_edge = img.filter(ImageFilter.EDGE_ENHANCE)
img_edge.save('edge_enhance.jpg')
より強いぼかし効果を得たい場合はGaussianBlurを使います。
# ガウシアンぼかし(radius=10)
img_blur = img.filter(ImageFilter.GaussianBlur(radius=10))
主なフィルターの種類は以下の通りです。
-
BLUR: 標準的なぼかし -
GaussianBlur: ガウシアンぼかし(より自然) -
SHARPEN: シャープ化 -
SMOOTH: 滑らかに -
CONTOUR: 輪郭検出 -
EDGE_ENHANCE: エッジ強調 -
EMBOSS: エンボス効果
明るさ・コントラストの調整
画像の明るさやコントラストを調整するには、ImageEnhanceモジュールを使います。
from PIL import Image, ImageEnhance
img = Image.open('sample.jpg')
# 明るさを調整(1.0が元の明るさ)
enhancer = ImageEnhance.Brightness(img)
img_bright = enhancer.enhance(1.5) # 1.5倍明るく
img_bright.save('bright.jpg')
img_dark = enhancer.enhance(0.5) # 0.5倍暗く
img_dark.save('dark.jpg')
# コントラストを調整
enhancer = ImageEnhance.Contrast(img)
img_contrast = enhancer.enhance(2.0) # コントラストを2倍に
img_contrast.save('high_contrast.jpg')
# 彩度を調整
enhancer = ImageEnhance.Color(img)
img_saturated = enhancer.enhance(1.5) # 彩度を1.5倍に
img_saturated.save('saturated.jpg')
img_grayscale = enhancer.enhance(0.0) # 彩度0でグレースケール
img_grayscale.save('desaturated.jpg')
enhance()メソッドの引数の意味は以下の通りです。
-
1.0: 元の画像のまま -
1.0より大きい: 効果を強める -
0.0〜1.0: 効果を弱める -
0.0: 効果を完全に除去
カラーモードの変換
画像のカラーモードを変換するにはconvert()メソッドを使います。
from PIL import Image
img = Image.open('sample.jpg')
# グレースケール(白黒)に変換
img_gray = img.convert('L')
img_gray.save('gray.jpg')
# 二値画像(完全な白黒)に変換
img_bw = img.convert('1')
img_bw.save('bw.jpg')
# RGBからRGBAに変換(透明度チャンネルを追加)
img_rgba = img.convert('RGBA')
img_rgba.save('rgba.png')
主なカラーモードは以下の通りです。
-
RGB: フルカラー(24ビット) -
RGBA: フルカラー + 透明度(32ビット) -
L: グレースケール(8ビット) -
1: 二値画像(1ビット) -
CMYK: 印刷用カラー
画像の生成
新規画像の作成
Pillowでは新しい画像を一から作成することもできます。
from PIL import Image
# 800x600の赤色画像を作成
img = Image.new('RGB', (800, 600), color='red')
img.save('red_image.jpg')
# RGB値で色を指定
img = Image.new('RGB', (800, 600), color=(100, 150, 200))
img.save('custom_color.jpg')
# 透明な画像を作成
img = Image.new('RGBA', (800, 600), color=(255, 255, 255, 0))
img.save('transparent.png')
Image.new()の引数は以下の通りです。
- カラーモード(
RGB、RGBAなど) - サイズ(幅, 高さ)
- 背景色(オプション)
図形や文字の描画
画像に図形や文字を描画するには、ImageDrawモジュールを使います。
from PIL import Image, ImageDraw, ImageFont
# 白い背景の画像を作成
img = Image.new('RGB', (800, 600), color='white')
# 描画オブジェクトを作成
draw = ImageDraw.Draw(img)
# 長方形を描画
draw.rectangle((100, 100, 300, 200), fill='blue', outline='black', width=3)
# 円を描画
draw.ellipse((400, 100, 600, 300), fill='red', outline='black', width=3)
# 線を描画
draw.line((100, 400, 700, 400), fill='green', width=5)
# テキストを描画
draw.text((100, 500), 'Hello, Pillow!', fill='black')
img.save('drawing.jpg')
より大きなフォントでテキストを描画する場合は、フォントファイルを指定します。
from PIL import Image, ImageDraw, ImageFont
img = Image.new('RGB', (800, 600), color='white')
draw = ImageDraw.Draw(img)
# フォントを指定(サイズ40)
try:
font = ImageFont.truetype('arial.ttf', 40)
except:
# フォントが見つからない場合はデフォルトフォント
font = ImageFont.load_default()
draw.text((100, 100), 'Hello, Pillow!', fill='black', font=font)
img.save('text_with_font.jpg')
描画できる図形の種類は以下の通りです。
-
rectangle(): 長方形 -
ellipse(): 楕円・円 -
line(): 直線 -
polygon(): 多角形 -
arc(): 円弧 -
text(): テキスト
実践的な使用例
サムネイル画像の一括生成
複数の画像を一括でサムネイル化する例を見てみましょう。
from PIL import Image
import os
def create_thumbnails(input_dir, output_dir, size=(200, 200)):
"""
指定ディレクトリ内の全画像をサムネイル化
Args:
input_dir: 入力画像のディレクトリ
output_dir: 出力先ディレクトリ
size: サムネイルのサイズ(幅, 高さ)
"""
# 出力先ディレクトリがなければ作成
os.makedirs(output_dir, exist_ok=True)
# 対応する画像形式
extensions = ('.jpg', '.jpeg', '.png', '.gif', '.bmp')
for filename in os.listdir(input_dir):
if filename.lower().endswith(extensions):
try:
# 画像を開く
img_path = os.path.join(input_dir, filename)
img = Image.open(img_path)
# サムネイル化(アスペクト比を保持)
img.thumbnail(size, Image.Resampling.LANCZOS)
# 保存(ファイル名に_thumbを追加)
name, ext = os.path.splitext(filename)
output_path = os.path.join(output_dir, f"{name}_thumb{ext}")
img.save(output_path)
print(f"処理完了: {filename}")
except Exception as e:
print(f"エラー({filename}): {e}")
# 使用例
create_thumbnails('images', 'thumbnails', size=(200, 200))
画像に透かし(ウォーターマーク)を追加
画像に透かし文字を追加する例です。
from PIL import Image, ImageDraw, ImageFont
def add_watermark(input_path, output_path, text='© 2024'):
"""
画像に透かしテキストを追加
Args:
input_path: 入力画像のパス
output_path: 出力先のパス
text: 透かしテキスト
"""
# 画像を開く
img = Image.open(input_path).convert('RGBA')
# 透明なレイヤーを作成
txt_layer = Image.new('RGBA', img.size, (255, 255, 255, 0))
# 描画オブジェクトを作成
draw = ImageDraw.Draw(txt_layer)
# フォントを設定
try:
font = ImageFont.truetype('arial.ttf', 50)
except:
font = ImageFont.load_default()
# テキストのサイズを取得
bbox = draw.textbbox((0, 0), text, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
# 右下に配置
x = img.width - text_width - 20
y = img.height - text_height - 20
# 半透明の白文字で描画
draw.text((x, y), text, fill=(255, 255, 255, 128), font=font)
# レイヤーを合成
watermarked = Image.alpha_composite(img, txt_layer)
# RGB形式に変換して保存
watermarked = watermarked.convert('RGB')
watermarked.save(output_path)
print(f"透かし追加完了: {output_path}")
# 使用例
add_watermark('sample.jpg', 'watermarked.jpg', '© 2024 Sample')
この例では、以下のテクニックを使っています。
- 透明なレイヤーを作成してテキストを描画
-
alpha_composite()で元画像とレイヤーを合成 - テキストの透明度を調整(
fill=(255, 255, 255, 128)の128が透明度)
まとめ
Pillowは、Pythonで画像処理を行うための強力なライブラリです。この記事では以下の内容を解説しました。
基本操作
- 画像の読み込み・保存
- サイズや形式の確認
- 画像形式の変換
画像の編集
- リサイズとサムネイル化
- 回転と反転
- トリミング
画像の加工
- フィルターの適用
- 明るさ・コントラストの調整
- カラーモードの変換
画像の生成
- 新規画像の作成
- 図形やテキストの描画
実践例
- サムネイル画像の一括生成
- 透かしの追加
Pillowは直感的なAPIを持ち、少ないコードで多様な画像処理が実現できます。Webアプリケーション、データ分析、機械学習など、様々な場面で活用してみてください。
より詳しい情報は公式ドキュメントをご覧ください。