Symfoware

Symfowareについての考察blog

Python3 subprocess + ImageMagick identifyで画像のexif情報を取得する

Pythonで画像処理を行う場合、PillowやImageMagickのラッパーWandを使うことになるかと思います。
ImageMagickがインストールされた環境で、別のライブラリに依存せず
なんとかならないか考えてみました。

ImageMagickがインストール済のUbuntu 16.04 + Python 3.5で試しています。


subprocess



Python3で別のプロセスを実行するには、subprocessを使うのがよさそうです。
17.5. subprocess - サブプロセス管理

Python2の頃に比べて随分便利になりました。

subprocess.runで任意のコマンドを実行。
戻り値であるsubprocess.CompletedProcessにリターンコードが保存されています。
また、run実行時にstdout=subprocess.PIPEを指定しておけば、
戻り値のstdoutプロパティに、実行結果がバイナリで保存されています。
※universal_newlines=Trueを指定すれば文字列となる。


サンプルを実行して、ls -lの結果を表示してみます。


  1. # -*- coding:utf-8 -*-
  2. import subprocess
  3. r = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
  4. print(r.returncode)
  5. output = r.stdout.decode("utf-8")
  6. for line in output.split("\n"):
  7.     print(line)
  8. $ python3 sample.py
  9. return code:0
  10. 合計 21876
  11. -rw-r----- 1 baranche baranche 221748 Nov 6 2016 cc2.jpg
  12. -rw-r----- 1 baranche baranche 107982 Nov 6 2016 img_0.jpg
  13. -rw-r----- 1 baranche baranche    89307 Nov 6 2016 img_1.jpg
  14. -rw-rw-r-- 1 baranche baranche 20123547 Apr 17 21:31 photo3.jpg
  15. -rw-rw-r-- 1 baranche baranche     230 Aug 11 14:17 sample.py
  16. -rw-rw-r-- 1 baranche baranche 1835272 Aug 11 13:57 soku_34681.jpg



ちゃんとlsの結果が取得できたようです。






identify



exif情報の前に、画像のサイズを取得してみます。

ImageMagickは画像の変換を行う「convert」コマンドが有名ですが、
画像の情報を取得する「identify」コマンドもあるようです。
今回初めて知りました。
identify

コマンドの実行結果は以下のようになります。


$ identify cc2.jpg
cc2.jpg JPEG 1024x768 1024x768+0+0 8-bit sRGB 222KB 0.020u 0:00.030




この文字列をそのまま解析しても良いのですが、identifyにはformatオプションがあります。
https://www.imagemagick.org/script/command-line-options.php
https://www.imagemagick.org/script/escape.php

%wで幅、%hで高さのピクセル数の表示となります。


$ identify -format '%w %h' cc2.jpg
1024 768




これを利用して、画像サイズを取得するプログラムを作成してみます。


  1. # -*- coding:utf-8 -*-
  2. import subprocess
  3. r = subprocess.run(['identify', '-format', '%w %h', 'cc2.jpg'], stdout=subprocess.PIPE)
  4. print('return code:%d' % r.returncode)
  5. output = r.stdout.decode("utf-8")
  6. width, height = output.split()
  7. print('width:' + width)
  8. print('height:' + height)





狙いい通りの結果が得られました。


$ python3 sample.py
return code:0
width:1024
height:768







exif



exifの情報もidentifyコマンドに「-verbose」オプションをつければ取得できます。


$ identify -verbose photo3.jpg
Image: photo3.jpg
Format: JPEG (Joint Photographic Experts Group JFIF format)
Mime type: image/jpeg
Class: DirectClass
Geometry: 8688x5792+0+0
Resolution: 72x72
Print size: 120.667x80.4444
Units: PixelsPerInch
Type: TrueColor
Endianess: Undefined
Colorspace: sRGB
Depth: 8-bit
Channel depth:
    red: 8-bit
    green: 8-bit
    blue: 8-bit
Channel statistics:
    Pixels: 50320896
    Red:
     min: 0 (0)
     max: 255 (1)
     mean: 46.3726 (0.181853)
     standard deviation: 52.4237 (0.205583)
     kurtosis: 2.42003
     skewness: 1.74154
    Green:
     min: 0 (0)
     max: 255 (1)
     mean: 41.9346 (0.164449)
     standard deviation: 47.6014 (0.186672)
     kurtosis: 2.56682
     skewness: 1.77416
    Blue:
     min: 0 (0)
     max: 255 (1)
     mean: 30.7038 (0.120407)
     standard deviation: 43.5288 (0.170701)
     kurtosis: 4.47736
     skewness: 2.16726
Image statistics:
    Overall:
     min: 0 (0)
     max: 255 (1)
     mean: 39.6703 (0.15557)
     standard deviation: 47.9892 (0.188193)
     kurtosis: 3.29406
     skewness: 1.93119
Rendering intent: Perceptual
Gamma: 0.454545
Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
Background color: white
Border color: srgb(223,223,223)
Matte color: grey74
Transparent color: black
Interlace: None
Intensity: Undefined
Compose: Over
Page geometry: 8688x5792+0+0
Dispose: Undefined
Iterations: 0
Compression: JPEG
Quality: 98
Orientation: TopLeft
Properties:
    date:create: 2017-08-11T13:46:22+09:00
    date:modify: 2017-04-17T21:31:29+09:00
    exif:ApertureValue: 458752/65536
    exif:Artist:
    exif:ColorSpace: 1
    exif:ComponentsConfiguration: 1, 2, 3, 0
    exif:Copyright:
    exif:CustomRendered: 0
    exif:DateTime: 2014:12:12 16:52:16
    exif:DateTimeDigitized: 2014:12:12 16:52:16
    exif:DateTimeOriginal: 2014:12:12 16:52:16
    jpeg:colorspace: 2
    jpeg:sampling-factor: 2x1,1x1,1x1
    signature: 2cfa45ef3189f6b05eaac4e529fb643614be8e76d6f76afffbb278045c4e521e
    unknown: 2
    xmp:Rating: 3
Profiles:
    Profile-exif: 30078 bytes
    Profile-xmp: 2529 bytes
Artifacts:
    filename: photo3.jpg
    verbose: true
Tainted: False
Filesize: 20.12MB
Number pixels: 50.32M
Pixels per second: 86.76MB
User time: 0.570u
Elapsed time: 0:01.580
Version: ImageMagick 6.8.9-9 Q16 x86_64 2017-07-31 http://www.imagemagick.org





出力された文字列を解析しても良いのですが、欲しいexif情報だけ。
これもformatを指定することで、exif情報のみ取得できました。
https://www.imagemagick.org/script/escape.php

フォーマットに%[exif:*]を指定すればOKです。


$ identify -format '%[exif:*]' photo3.jpg
exif:ApertureValue=458752/65536
exif:Artist=
exif:ColorSpace=1
exif:ComponentsConfiguration=1, 2, 3, 0
exif:Copyright=
exif:CustomRendered=0
exif:DateTime=2014:12:12 16:52:16
exif:DateTimeDigitized=2014:12:12 16:52:16
exif:DateTimeOriginal=2014:12:12 16:52:16
exif:ExifImageLength=5792
exif:ExifImageWidth=8688
exif:ExifOffset=360
exif:ExifVersion=48, 50, 51, 48
exif:ExposureBiasValue=0/1
exif:ExposureMode=1
exif:ExposureProgram=1
exif:ExposureTime=1/15
exif:Flash=16
exif:FlashPixVersion=48, 49, 48, 48
exif:FNumber=11/1
exif:FocalLength=35/1
exif:FocalPlaneResolutionUnit=2
exif:FocalPlaneXResolution=8688000/1450
exif:FocalPlaneYResolution=5792000/965
exif:GPSInfo=10348
exif:GPSVersionID=2, 3, 0, 0
exif:InteroperabilityOffset=10120
exif:ISOSpeedRatings=400
exif:Make=Canon
exif:MeteringMode=5
exif:Model=Canon EOS 5DS R
exif:Orientation=1
exif:ResolutionUnit=2
exif:SceneCaptureType=0
exif:ShutterSpeedValue=262144/65536
exif:SubSecTime=00
exif:SubSecTimeDigitized=00
exif:SubSecTimeOriginal=00
exif:thumbnail:Compression=6
exif:thumbnail:InteroperabilityIndex=R98
exif:thumbnail:InteroperabilityVersion=48, 49, 48, 48
exif:thumbnail:JPEGInterchangeFormat=12236
exif:thumbnail:JPEGInterchangeFormatLength=17836
exif:thumbnail:ResolutionUnit=2
exif:thumbnail:XResolution=72/1
exif:thumbnail:YResolution=72/1
exif:WhiteBalance=1
exif:XResolution=72/1
exif:YCbCrPositioning=2
exif:YResolution=72/1





単一の項目のみ取得したい場合は、*ではなく項目名を指定してやります。


$ identify -format '%[exif:DateTimeOriginal]' photo3.jpg
2014:12:12 16:52:16




これ、どこかで見たことあるフォーマットだなと思ったら
PHPでImageMagickを使用する際のgetImagePropertiesの指定と同じですね。
http://php.net/manual/ja/imagick.getimageproperties.php



formatの指定によって、高さや幅、exif情報を一気に取得することもできました。


$ identify -format '%w\n%h\n%[exif:*]' photo3.jpg
8688
5792
exif:ApertureValue=458752/65536
exif:Artist=
exif:ColorSpace=1
(略)





これらを踏まえて、プログラムを書いてみます。


  1. # -*- coding:utf-8 -*-
  2. import subprocess
  3. r = subprocess.run(['identify', '-format', 'width:%w\nheight:%h\n%[exif:*]', 'photo3.jpg'], stdout=subprocess.PIPE)
  4. print('return code:%d' % r.returncode)
  5. output = r.stdout.decode("utf-8")
  6. width = 0
  7. height = 0
  8. exif = {}
  9. for line in output.split('\n'):
  10.     info = line.strip().split(':', maxsplit=1)
  11.     if len(info) < 2:
  12.         continue
  13.     
  14.     if info[0] == 'width':
  15.         width = info[1]
  16.         continue
  17.     if info[0] == 'height':
  18.         height = info[1]
  19.         continue
  20.     # exif
  21.     exif_pair = info[1].split('=', maxsplit=1)
  22.     exif[exif_pair[0]] = exif_pair[1]
  23. print('width = ' + width)
  24. print('height = ' + height)
  25. print('exif:DateTimeOriginal = ' + exif['DateTimeOriginal'])




ちゃんと画像の情報が取得できました。


$ python3 sample.py
return code:0
width = 8688
height = 5792
exif:DateTimeOriginal = 2014:12:12 16:52:16


関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2017/08/11(金) 15:10:19|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<Python3 subprocess + ImageMagick convertで画像のリサイズやトリミングを実行 | ホーム | (修正版)JavaScriptで選択されたjpgのサイズ(高さ、幅)をSOFマーカーから取得する>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/2019-bb9f3b00
この記事にトラックバックする(FC2ブログユーザー)