Python × 画像処理

Pythonでブログ画像を16:9に切り取り・縮小、100KB以下に圧縮する方法

2020-10-07

Python画像縮小・圧縮

 

ブログでいつも画像を切り取ったり、圧縮するのって大変だな〜

 

Pythonを使えば、自動で画像を自動で16:9にしたり、容量を100KB以下にできるよ。

 

本記事では、PythonのOpneCVというライブラリを用いて、自動で画像を指定の縦横比にしたり、圧縮する方法をご紹介します。

 

想定読者

・ブログ記事を書くとき、手動で画像のサイズを変えたり圧縮している。Pythonも少しわかる。

・Pythonを勉強していて、簡単なOpenCVの処理を使ってみたい。

 

最適なブログでの画像の容量とサイズについて

ブログ内の画像の容量が大きいと、反応速度が遅くなり、Google検索エンジンの評価にも影響すると言われています。

一般的には、画像1ファイルあたり100KB以内が1つの目安になります。

 

画像のサイズについては、Google Discover(俗に言うGoogle砲)で奨励されている画像の幅:1200pxが1つの目安になります。

(引用元:Google Discoverページ

 

Google Discover(Google砲)とは、Googleの検索窓の下に列挙されるオススメ記事(赤枠部分)をいう。

google砲

 

本記事では、画像容量が100KB以下で、画像サイズは幅:1200px、高さ:675px(16:9)の画像を自動で作成するプログラムをご紹介します。

 

 

Pythonでブログ画像を加工するための実行環境

・Linux
・Python 3.7.6
・Jupyterlab 1.2.6
・cv2:4.3.0

テスト画像としては、Pixabayからダウンロードした下の画像を使っていきます。

 

input

ファイル名は「input.jpg」とします。

ダウンロード時は、容量:395KB、サイズ:1920×1357となっております。

 

Pythonでブログ画像を16:9に切り取り・縮小、100KB以下に圧縮する方法

それでは、実際にPythonのプログラムをみていきます。

Pythonでブログ画像の加工の準備

まずは、Pythonで今回の画像加工に必要なライブラリをインポートします。

import os
import cv2
import matplotlib.pyplot as plt
%matplotlib inline #Jupyter Notebookで実行する際は必要

 

次にテスト画像を取り込んで、表示します。

img = cv2.imread('input.jpg') #numpy.ndarrayとなる
plt.imshow(img)
print('容量:{}KB'.format(int(os.path.getsize("input.jpg") /1000)))
print('サイズ:{}×{}'.format(img.shape[1], img.shape[0]))

結果は次の通りとなります。

※今回使っているOpenCVのimread()で画像ファイルを読み込むと色の順番がBGR(青、緑、赤)になるので、Jupyter Notebook上は元の画像と違った色で表示されます。
実際の画像は、色が変わることはありません。

 

python画像読み込み

 

これで画像加工の準備は終わりです。

 

Pythonでブログ画像を16:9に切り取り、縮小

次に、画像の切り取りまたは縮小を行います。

このどちらかの方法によって、画像のサイズ(縦横比)を16:9に変換します。

ここで、画像の切り取りと縮小のイメージを確認しましょう。次の図の通りとなります。

画像の切り取りと縮小

それでは、まず画像の切り取りのプログラムをみていきます。

height = img.shape[0]
width = img.shape[1]

i = int((height-675)/2)
j = int((width-1200)/2)

img2 = img[i:i+675, j:j+1200]
plt.imshow(img2)
cv2.imwrite("output2.jpg", img2)

print('容量:{}KB'.format(int(os.path.getsize("output2.jpg") /1000)))
print('サイズ:{}×{}'.format(img2.shape[1], img2.shape[0]))

画像の切り取りの結果は次のようになります。上下の端が削られているのがわかると思います。

 

python画像切り取り

 

次に画像の縮小のプログラムをみていきまます。

img3 = cv2.resize(img , (1200, 675))

plt.imshow(img3)
cv2.imwrite("output3.jpg", img3)

print('容量:{}KB'.format(int(os.path.getsize("output3.jpg") /1000)))
print('サイズ:{}×{}'.format(img3.shape[1], img3.shape[0]))

画像の縮小の結果は次のようになります。上下で縮んで円の模様が楕円になっているのがわかると思います。

 

Pythyonでの画像の縮小

 

ここまでで画像の切り取りまたは縮小で、画像のサイズを1200px:675pxに変換することができました。

ただ、画像の容量は、切り取りまたは縮小した後でも100KBを超えています。

次は画像の圧縮をみていきます。

 

Pythonでブログ画像を100KB以下に圧縮

まずは、画像を容量を100KB以下にするための圧縮率を算定する関数を作ります。

イメージとしては、次のグラフの緑の星の部分の圧縮率を見つけ出すという処理になります。

画像の圧縮率と容量

この圧縮率を算定するプログラムは次のようになります。

 

def to_100kb_ratio(img):
    """
    インプット画像のファイルサイズが100KB以下となる最大の圧縮率を返す
    
    Parameter
    -------------------
        img: インプット画像のnumpy.ndarray

    Return
    -------------------
        画像の容量が100KB以下となる最大の圧縮率
    """

    #圧縮率を10%から95%まで5%刻みで指定する。
    comp_ratio_list = [i*5 for i in range(2, 20)]
    output_size_list = []
    tmp = []
    for comp_ratio in comp_ratio_list:
        #画像imgを圧縮率comp_ratioで書き出し
        cv2.imwrite("output.jpg", img, [cv2.IMWRITE_JPEG_QUALITY, comp_ratio])
        #圧縮率comp_rateごとに書き出した画像ファイルの容量を要素に追加
        output_size = os.path.getsize("output.jpg")
        output_size_list.append(output_size)
        if output_size <= 100000:
            tmp.append(comp_ratio)
    return max(tmp)

 

この関数によって、画像の容量を100KB以下とする最適な圧縮率を算定できます。

次のこの最適な圧縮率で、実際に圧縮するプログラムを書きます。

 

def to_100kb(img, filename):
    """
    インプット画像を100KB以下にする画像を生成する。
    
    Parameter
    -------------------
        img: インプット画像のnumpy.ndarray
        filename: 生成する画像のファイル名

    Return
    -------------------
        なし
    """

    cv2.imwrite(filename, img, [cv2.IMWRITE_JPEG_QUALITY, to_100kb_ratio(img)])

 

プログラムの処理自体は、1行で書けます。

ここまでで画像の容量を100KB以下にするプログラムができました。

 

最後に、テスト画像を今回は切り取りで100KB以下の画像に加工してみましょう。

※画像の読み込みから一通り書いています。

 

########## 画像の読み込み ##########
img = cv2.imread('input.jpg') #numpy.ndarrayとなる

########## 画像の切り取り ##########
height = img.shape[0]
width = img.shape[1]

i = int((height-675)/2)
j = int((width-1200)/2)

img2 = img[i:i+675, j:j+1200]
plt.imshow(img2)
cv2.imwrite("output2.jpg", img2)

########## 画像の圧縮 ##########
to_100kb(img2, 'output2.jpg')

print('容量:{}KB'.format(int(os.path.getsize("output2.jpg") /1000)))
print('サイズ:{}×{}'.format(img2.shape[1], img2.shape[0]))

 

結果は、次の通りとなり、容量が100KB以下で、1200px × 675pxの画像を生成することができました。

python画像切り取り&圧縮

 

いかがでしたでしょうか?

Pythonを用いることで、ブログ用の画像も簡単に加工できそうですよね。

もしこうした方がいいよ〜とか、ここが分からない等ありましたら、Twitterまで連絡をお待ちしています。

 

最後まで読んでいただき、ありがとうございました。

 

今回の処理をpyファイルで実行したい

 

よく読まれている記事

se-shikaku 1

  社内SEになるには資格って必要?社内SEでキャリアップするときにおすすめの資格は? 回答としては、 社内SEは、対人スキル、実務での対応力や最新情 ...

社内SEの仕事内容 2

  社内SEってどんな仕事なんだろ~ 検索しても転職サイトの記事ばかりでよく分からない・・   確かにそうですね。。実経験を基に、社内SE( ...

side-work-trial 3

  コロナで会社の経営も不安。。個人でお金稼ぎたいな~ 今、こう考えるサラリーマン、OLの方はごまんといると思います。   僕は、本業では社 ...

adsense-pass 4

【3記事で一発合格】Google AdSense申請に合格したブログ情報 こんにちは、いなサラ(@いなサラ|田舎の情シスサラリーマン)です。 2019年10月5 ...

-Python × 画像処理

© 2020 inasala note