Jpeg画像をEXIFの位置に合わせて保存する

PIL(pillow)ライブラリでjpegの表示向きとデータ方向を合わせる

前置き

携帯電話等で撮影した電子データを表示するとき、向きがあってなくて困ることがあります。専用のビューアソフトを使えば向きを合わせてくれることもあります。しかし、対応してない場合撮影した写真が縦長なのか横長なのか判別してくれません。そもそも、撮影機器自身はイメージセンサの並びで決まった方向にしか出力しません。試しに、携帯電話(カメラ)を縦にして撮影、横にして撮影、寝転がって天井にを横になって撮影、縦に撮影すればビューアソフトが最近はやりのAIを使って画像識別を行って縦横判定してないことがわかります(最新機器は知りませんが)。たいていの場合手振れ防止等でも使用しているジャイロセンサを使って機器が横に向いているのか縦に向いているのかを判断してその情報をEXIFメタデータとしてjpegファイル等に書き出しているにすぎないのです(だったら、水平角データを記録してくれれば連続撮影の時にマッチングしやすいのにね)。

内容

pythonのPILライブラリを使ってjpegEXIFデータを読み取り、jpeg画像の方向を合わせ保存する

コマンド1: exifデータに合わせて画像を変換する

python jpeg_conv.py input.jpg output.jpg

コマンド2: 画像をcommandに合わせて変換する

python jpeg_conv.py input.jpg output.jpg [1-8]

コマンド番号

  1. オリジナル
  2. 左右反転
  3. 180度回転
  4. 上下反転
  5. SCREEN座標(左上原点)で縦横入れ替え
  6. 90度回転
  7. XY座標でXY入れ替え
  8. 270度回転
# -*- coding: utf-8 -*-
"""
Created on Thu May  2 15:55:03 2019
@author: cyiyoh
"""
import sys
from PIL import Image
def exif_orientation(im,param, op=False):
    """
    im : イメージオブジェクト
    param : orientationのパラメータ
    """
    orient = {1:None,  # 360度回転(オリジナルなまま)
              2:Image.FLIP_LEFT_RIGHT,  # 左右反転、X軸反転
              3:Image.ROTATE_180, # 180度回転、X軸反転+Y軸反転
              4:Image.FLIP_TOP_BOTTOM, # 上下反転、Y軸反転
              5:Image.TRANSPOSE, # SCREEN座標で縦横入れ替え
              6:Image.ROTATE_90, # 90度回転
              7:Image.TRANSVERSE, # XY座標でXY入れ替え 45度(Y=X ラインで対称)
              8:Image.ROTATE_270 } # 270度回転
    # 状態を元に戻す
    conv = {1:1, # 何もしない
            2:2, # 左右反転
            3:3, # 180度回転
            4:4, # 上下反転
            5:5, # SCREEN座標で縦横入れ替え
            6:8, # 90°進んでいるので -90°進めて戻す
            7:7, # XY座標でXY入れ替え
            8:6 } # -90°進んでいるので 90°進めて戻す

    if param == 1 :
        return im.copy()

    elif op == True :
        return im.transpose(orient[param])

    else:
        return im.transpose(orient[conv[param]])

if __name__ == '__main__' :
    """
    python jpeg_conv input.jpg output.jpg
    exifデータは方向変換したときに抜け落ちるがそれはそれで問題なし
    """
    print(len(sys.argv))
    print(sys.argv)
    if len(sys.argv) ==1 :
        print("Convert using exif")
        print("   uage:python jpeg_conv.py input.jpg output.jpg")
        print("Convert using command")
        print("   uage:python jpeg_conv.py input.jpg output.jpg command")
        print("command")
        print(''' 1 :None 360度回転(オリジナルなまま)
 2 :Image.FLIP_LEFT_RIGHT 左右反転、X軸反転
 3 :Image.ROTATE_180 180度回転、X軸反転+Y軸反転
 4 :Image.FLIP_TOP_BOTTOM 上下反転、Y軸反転
 5 :Image.TRANSPOSE SCREEN座標で縦横入れ替え
 6 :Image.ROTATE_90 90度回転
 7 :Image.TRANSVERSE XY座標でXY入れ替え 45度(Y=X ラインで対称)
 8 :Image.ROTATE_270 270度回転''')
    else:
        im = Image.open(sys.argv[1])
        if len(sys.argv) > 3 :
            im_out = exif_orientation(im,int(sys.argv[3]),op=True)
        else:
            im_out = exif_orientation(im,im._getexif()[274])
        im_out.save(sys.argv[2])

簡単にできるんだね