8.1 画像フォーマット変換

(1/1)
さまざまな画像形式
Python を使うことで、ちょっとした画像処理を自動化できる。
7.8 PC内蔵カメラを利用する」で利用した外部ライブラリ OpenCV は、カメラ映像をキャプチャするだけでなく、さまざまな画像処理機能を備えている。そこで今回は、画像ファイルのデータフォーマットを変換するプログラムを作ってみることにする。

目次

サンプル・プログラム

WebPとは

WebPロゴ
近年、ネット上に拡張子 .webp の画像ファイルが増えている。これは、Googleが2010年(平成22年)9月に仕様を公開した WebP (ウェブピー) という画像フォーマットである。
非可逆と可逆の両方の圧縮形式に対応しており、背景を透明にしたり画像を半透明にするアルファチャネルを備えている。可逆圧縮の場合はPNGより26%小さくなり、非可逆圧縮の場合はJPEG画像より30%小さくなるという。
ただ、まだ対応していないアプリがあるようなので、今回はWebP画像ファイルをPNG画像ファイルに変換し、WebP未対応アプリでも画像処理ができるようなツールを作ることにする。
また、今回作ったアプリを応用すれば、処理したあとのPNG画像ファイルをWebP画像ファイルに変換することもできる。もちろん、WebPやPNG以外の画像フォーマットの相互変換もできる。

画像フォーマット変換

WebPからPNGへの画像フォーマット変換を行うには、前回インストールした画像処理を行う外部ライブラリ OpenCV と、WebPに対応した imageio をインストールする。pipコマンドを使ってインストールしてほしい。
pip install opencv-python
pip install imageio
ファイルダイアログ - Python
インストールできたら、プログラム "webp2png.py" を実行してみてほしい。ファイルダイアログを表示するので、変換したいWebP画像ファイルを選択する。複数選択できる。
すると、自動的にファイル変換が始まり、同じフォルダ、同じファイル名で、拡張子を .png にしたPNG画像ファイルを保存する。変換保存できたら、変換元と変換先のファイル名をコンソールに出力する。もし保存するPNGファイルと同名ファイルが存在していれば、上書きしないでエラーメッセージを表示する。
webp2png.py
import os
import tkinter as tk
from tkinter import filedialog

try: import cv2 import imageio except ImportError as errmsg: print(f"外部ライブラリをインストールしてください ... {errmsg}") exit()
# 初期値 dialogTitle = "WebPファイルを選択してください" filetypes = [("WebP files", "*.webp"), ("All files", "*.*")] filenames = filedialog.askopenfilenames(title=dialogTitle, filetypes=filetypes)
# 画像フォーマット変換処理 try: for fullname in filenames: # 選択ファイルが存在するかどうか(バリデーション) if os.path.exists(fullname): # WebPファイルを読み込む webpImage = imageio.v2.imread(fullname) # pngファイル名を生成する pngFullname = fullname.replace(".webp", ".png") # 同名ファイルがあれば例外発生 if os.path.exists(pngFullname): raise FileExistsError(f"{pngFullname} が存在します") # png形式で保存する else: cv2.imwrite(pngFullname, webpImage) # 変換結果をコンソールに出力する print(f"{os.path.basename(fullname)} => {os.path.basename(pngFullname)}")
# 例外処理 except Exception as e: print(f"エラーが発生しました -- {str(e)}")
メイン・プログラムでは、標準ライブラリ tkinter を使ってファイルダイアログを表示する。tkinter は、ファイルダイアログ以外にも、テキスト入力ボックスやラジオボタン、チェックボックス、メニューなどの、基本的な入出力GUIを、OSを問わずウィンドウ表示することができる。「6.3 pywebviewを使ったGUI」で紹介したブラウザベースのGUI「pywebview」を使うほどでもないとき、標準ライブラリなのでインストールの必要もないので、tkinter が重宝する。

ファイルダイアログを呼び出すには filedialog.askopenfilenames関数を利用する。第1引数にはダイアログのタイトルを、第2引数には抽出したい拡張子タイプを渡す。拡張子タイプは、タプルをリストにしたデータ形式で、[(タイトル1, 拡張子1), (タイトル2, 拡張子2),‥‥] のように記述する。ここでは、拡張子 .webp とすべての拡張子のファイルを選べるように、[("WebP files", "*.webp"), ("All files", "*.*")] とした。もし複数の画像ファイルの拡張子で抽出したいのであれば、("Image files", "*.webp;*.jpg *.png;*.bmp") のようにセミコロン ; で拡張子を並べて書けばよい。
なお、filedialog.askopenfilenames は複数のファイルを返すことができるが、filedialog.askopenfilename は1つのファイルしか選択できない。

filedialog.askopenfilenames の戻り値はファイル名(フルパス)のリストであるので、for文 を使って1つ1つ変換していく。
ファイルダイアログで選択しているので間違いはないはずだが、念には念を入れた入力バリデーションとして、os.path.exists を使って当該画像ファイルが存在していたら変換処理を進めるようにする。

まず、imageio.v2.imread を使って変換元のWebPファイルをイメージオブジェクトとして webpImage に読み込む。
OpenCVの cv2.imread を使って読み込むことができるのだが、2024年(令和6年)9月時点で、アルファチャネルを使っていると正しく読み込めないようなので、外部ライブラリ imageio を使っている。いずれ OpenCV が対応するだろう。

次に、変換元の拡張子 .webp を .png に置換し(replace)、変換先のPNG画像ファイル名とする。
変換と保存は imwrite で行う。第1引数は保存するファイル名、第2引数はイメージオブジェクトである。imwrite はファイル名の拡張子を見て、自動的に保存する画像フォーマットを判断する。

最後に変換結果をコンソールに出力する(print)。

参考として、OpenCVで扱える画像フォーマットと拡張子の対応表を掲げる。これらのフォーマットの相互変換であれば、今回のプログラムのように、画像ファイルの読み込み、変換、保存は実質2行でできる。
OpenCVが対応している画像フォーマットと対応拡張子
画像フォーマット対応拡張子
BMP.bmp, .dib
JPEG.hpg, .jpeg, jpe
JPEG2000jp2
PNG.png
WebP.webp
AVIF.avif
Portable image format.pbm, .pgm, .ppm, .pxm, .pnm
PFM.pfm
Sun rasters.sr, .ras
TIFF.tiff, .tif
OpenEXR.exr
Radiance HDR.hdr, .pic

練習問題

次回予告

Python と外部ライブラリ OpenCV を使うことで、簡単に画像の拡大・縮小を行うことができる。次回は、ブログやSNSにデジカメで撮った写真を投稿することを想定し、縦横比を保ったまま拡大・縮小するプログラムを作っていくことにする。

コラム:ラスターデータとベクターデータ

ラスターデータ
本編で紹介した OpenCV で扱うことができる画像フォーマットは、すべてラスターデータに区分される。ラスターデータとは、点状のピクセル(ドット)を縦横方向に並べたビットマップ画像を指す。
データが連続しているため、画像の一部を切り出したり、色調や階調の変換、このあと取り上げる会の検出といった OpenCV に備わっている各種画像処理を行うのに適したデータ形式である。
ただし、データサイズが大きくなることと、拡大するとピクセルが目立って粗くなってしまうという短所がある。

これに対し、画像を点や直線、曲線で表すベクタデータという画像データ形式がある。たとえば、TruType形式のフォントデータや、Googleマップ上にプロットする経路図はベクターデータだ。
ベクターデータは、最低限必要な情報だけあれば図形を描くことができるので、データサイズを小さくすることができ、また、画像を拡大するtきにも図形を再描画するのでピクセルが目立ってしまうようなことはない。ただし、OpenCV に備わっている各種画像処理を行うことが難しい。

画像を使う目的によって、ラスターデータベクターデータを使い分ける必要がある。本章は、OpenCV に備わっている画像処理を中心に学んでいくので、ラスターデータを扱う。なお、OpenCV にも直線や長方形、円といった基本図形をベクターデータとして描く機能が備わっているので、興味がある方は利用してみてほしい。

参考サイト

(この項おわり)
header