メモ:OpenCVやPillowでの画像読み込み時の注意点


はじめに

我が家の愛犬の写真を読み込んだ際に、縦長画像の縦横が変わってしまう場合があったので、その原因のメモ。

【before】OpenCVとKerasで画像の読み込み

from keras.preprocessing import image
import cv2
%matplotlib inline
import matplotlib.pyplot as plt

# OpenCVで画像読み込み
img_cv2 = cv2.imread('img/terrier.jpg')

# Kerasで画像読み込み
img_keras = image.load_img('img/terria.jpg')
# PIL形式からnumpy配列に変換
img_keras = image.img_to_array(img_keras)

# matplotlibで可視化
fig = plt.figure()
fig.subplots_adjust(left=0, right=1, bottom=0, top=0.5, hspace=0.05, wspace=0.05)

for i in range(2):
    ax = fig.add_subplot(1, 2, i + 1)
    if i == 0:
        # OpenCVのためBGRからRGBに
        ax.imshow(cv2.cvtColor(img_cv2, cv2.COLOR_BGR2RGB))
    elif i == 1:
        # img_to_arrayでfloatになっているためintに
        ax.imshow(img_keras / 255)
plt.show()

あれ??同じ画像なのに縦横が違う!!!

【after】OpenCVとKerasで画像の読み込み

from keras.preprocessing import image
import cv2
%matplotlib inline
import matplotlib.pyplot as plt

# OpenCVで画像読み込み
# ★変えたのはココ↓
img_cv2 = cv2.imread('img/terria.jpg', cv2.IMREAD_IGNORE_ORIENTATION | cv2.IMREAD_COLOR)

# Kerasで画像読み込み
img_keras = image.load_img('img/terria.jpg')
# PIL形式からnumpy配列に変換
img_keras = image.img_to_array(img_keras)

# matplotlibで可視化
fig = plt.figure()
fig.subplots_adjust(left=0, right=1, bottom=0, top=0.5, hspace=0.05, wspace=0.05)

for i in range(2):
    ax = fig.add_subplot(1, 2, i + 1)
    if i == 0:
        # OpenCVのためBGRからRGBに
        ax.imshow(cv2.cvtColor(img_cv2, cv2.COLOR_BGR2RGB))
    elif i == 1:
        # img_to_arrayでfloatになっているためintに
        ax.imshow(img_keras / 255)
plt.show()

おお!同じになった^^

原因

この画像はiPhoneで撮影したもので、画像に埋め込まれているOrientation属性によるものでした

OpenCVの場合、当該情報を考慮するのがデフォルトのようで、
imreadにcv2.IMREAD_IGNORE_ORIENTATIONを指定することで、
この情報を無視することが出来るようです。

撮影時、iPhoneは縦だったけど、カメラとしては横であったということ、すなわちOrientation属性を考慮するか否かで、デフォルトの画像読み込みによって差が出る、ということです。これは、SNSへアップロードした際にも考慮するか否かにより、意図した向きと変わるということにも関係しています。そのあたりの詳細についてはここでは言及しません。
ちなみに、私が意図していたのは縦なので、撮影する際は注意ですね。

さいごに

撮影した画像からデータセットを作成して機械学習する際、回転を考慮すべき学習データの場合、Orientation属性を考慮するか否かが大事な場面がありそうです。
が、回転を考慮すべき文字認識などで、学習データとなる手書き文字をカメラで撮影して。。。なんてことはしないと思うので、そこまで気にする必要はないかも。

<参考>
stack overflow Image Orientation (python + openCV)
OpenCV Image file reading and writing