Python × 画像処理

Python/OpenCVを使って画像の切り取り、縮小、圧縮をするプログラム

2020-10-08

OpenCV切り取り、縮小、圧縮

 

画像を簡単に大きさを変えたり、圧縮する方法ってないかな〜

 

PythonのOpenCVを使えば、簡単に画像を好きなサイズに変えたり、圧縮できるよ。

 

本記事では、PythonのOpneCVというライブラリを用いて、画像を好きなサイズに切り取り、圧縮したり、圧縮するプログラムをご紹介します。

 

想定読者

・OpenCVを使って、画像のサイズに変えたり、圧縮するプログラムを作りたい。

・Pythonで自分で関数を作って、インポートして使ってみたい。

 

Python/OpenCVで画像の切り取り、縮小、圧縮をするための実行環境

今回は、以下の実行環境でプログラムを実行しています。

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

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

 

input

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

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

 

Python/OpenCVで画像の切り取り、縮小、圧縮をするプログラム

今回は、Python/OpenCVで画像を切り取り、縮小、圧縮するプログラムを1つのpyファイルで書き、それをJupyterNotebookで利用することを想定しています。

pyファイルの名前は、「image_edit.py」とし、pyファイルを実行するNotebookファイルは、「image_edit_run.ipynb」とします。

今回、実行するフォルダは、下図の通りとなります。

 

実行フォルダ1

 

ちなみに、画像の切り取りと縮小の違いについては、次のページを見ればイメージがつきます。

参考画像の切り取りと縮小のイメージ

 

Python/OpenCVで画像を切り取るプログラム

それでは、画像を切り取るプログラムをから見ていきます。

cut関数として作成します。

ここでは、画像の中央部分で切り取る仕様としています。デフォルトでは、1200×675のサイズで切り取られます。

関数の引数に、対象の画像ファイル名、加工後のファイル名、そして任意で切り取りたい幅と高さを指定します。

 

import os
import cv2
    
def cut(input_filename, output_filename, width=1200, height=675):
    """
    インプット画像を指定の大きさに(デフォルト:1200×675)に切り取りする。
    
    Parameter
    -------------------
        img : インプット画像のファイル名
        filename : 生成する画像のファイル名
        width : 変更したい画像の幅
        height : 変更したい画像の高さ

    Return
    -------------------
        なし
    """
    
    #画像の読み込み
    img = cv2.imread(input_filename) 

    #インプット画像のサイズを変数に入れる
    i_height = img.shape[0]
    i_width = img.shape[1]

    #切り取る部分の左上の頂点を決める
    i = int((i_height-height)/2)
    j = int((i_width-width)/2)

    #頂点から指定のサイズでスライスし、画像を書き出す
    img2 = img[i:i+height, j:j+width]
    cv2.imwrite(output_filename, img2)

 

Python/OpenCVで画像を縮小するプログラム

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

shrink関数として作成します。

引数は、切り取りのcut関数と同様としています。

def shrink(input_filename, output_filename, width=1200, height=675):
    """
    インプット画像を指定の大きさに(デフォルト:1200×675)に縮小する。
    
    Parameter
    -------------------
        img: インプット画像のファイル名
        filename: 生成する画像のファイル名
        width : 変更したい画像の幅
        height : 変更したい画像の高さ

    Return
    -------------------
        なし
    """
    
    #画像の読み込み
    img = cv2.imread(input_filename) 
    #指定のサイズに画像をリサイズし、書き出す
    img2 = cv2.resize(img , (width, height))
    cv2.imwrite(output_filename, img2)

 

Python/OpenCVで画像を圧縮するプログラム

最後に画像を圧縮するプログラムです。

今回は、to_100kb関数として100KB以下に圧縮するプログラムを書いています。

下のプログラムの100000の部分を、好きなバイト数に変更できます。

引数は、対象の画像ファイル名、加工後のファイル名です。

 

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

    Return
    -------------------
        なし
    """
    
    #インプット画像の拡張子を取得
    extension = input_filename.split('.')[-1]

    #画像の読み込み
    img = cv2.imread(input_filename) 
 
    #圧縮率を10%から95%まで5%刻みの値のリストを作る
    comp_ratio_list = [i*5 for i in range(2, 20)]
    #リストの初期化
    output_size_list = []
    tmp_list = []
    #一時ファイルのファイル名
    tmp_filename = "tmp." + extension
    
    #100KB以下になる最大の圧縮率を探す
    for comp_ratio in comp_ratio_list:
        #画像imgを圧縮率comp_ratioで書き出し
        cv2.imwrite(tmp_filename, img, [cv2.IMWRITE_JPEG_QUALITY, comp_ratio])
        #圧縮率comp_rateごとに書き出した画像ファイルの容量を、output_size_listに追加
        output_size = os.path.getsize(tmp_filename)
        output_size_list.append(output_size)
        #容量あ100KB以下の場合は、tmp_listに追加
        if output_size <= 100000:
            tmp_list.append(comp_ratio)
    #一時ファイルを削除する
    os.remove(tmp_filename)

    # 100KB以下になる最大の圧縮率(tem_listの最大値)で圧縮し画像を書き出し
    cv2.imwrite(output_filename, img, [cv2.IMWRITE_JPEG_QUALITY, max(tmp_list)])

 

 

実際にOpenCVのプログラムを実行してみる

それでは、「image_edit_run.ipynb」で上記のプログラムを実行してみたいと思います。

1行目では、pyファイル名を記載します。

それ以降は、image.関数名として処理を実行します。

3行目と5行目では、画像のサイズを指定して、切り取り・縮小を行っています。

 

python実行画面

 

2行目〜5行目で切り取り・縮小された画像は次の通りとなります。

python実行結果

 

そして、6行目の処理で、正常に100KB以下に圧縮されたことがわかります。

python opencv圧縮結果

 

 

これで今回は以上となります。

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

PythonのOpenCVを用いることで、画像の切り取り、縮小、圧縮を手軽にできそうですよね。

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

 

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

よく読まれている記事

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