Python

PythonとOpenCVで画像処理をしてみる

PythonをとOpenCVを使用して画像解析を行う方法を紹介します。今回の内容は、画像をグレースケール化・2値化処理の方法を紹介します。動画処理や画像処理の基本となり、これらの前処理が重要になるため、最初にこれらの方法を紹介いたします。また、前処理の方法により、画像解析結果や、動画処理の結果が異なるため、これらの基礎を紹介したいと思います。

アイコン名を入力

Pythonで画像の処理をするための方法がわからない。画像処理ってどんなイメージなんだろう・・・

アイコン名を入力

数行コードを打てばできるから、簡単だよ。やってみたらよくわかるよ。

アイコン名を入力

プログラミングをほぼやったことがないから、何からやっていいのかよくわからないです。

アイコン名を入力

じゃあ今回は、画像処理の基礎となる、グレースケール化・2値化処理のやり方とどういった画像になるかのイメージを持ってもらうために、実際にやってみよう!また、これらを適用すると、自動車のカウントなどできるようになります。

【記事の対象者】
 ・画像の前処理のイメージがついていない人
 ・グレースケール化・2値化処理・の方法を知りたい人
 ・画像の基礎的な処理方法を知りたい人

🚀 0円で現役エンジニアから学べる【Techスクールオンライン】のお申込みをお勧めします。 このオンラインスクールでは、現役のエンジニアから直接学ぶことができ、プログラミングの基礎から高度なスキルまでを習得できます。しかも、今なら 0円 で受講できるチャンスです。 エンジニア転職を考えている方やプログラミングに興味がある方、新しいスキルを習得したい方に特におすすめです。

画像(動画)処理方法について

画像処理方法は複数ありますが、基礎的な処理方法として、グレースケール化・2値化処理などがあります。今回はこれらの処理方法を紹介します。また、2値化の処理方法にもさまざまな種類があり、これらを使うとどのような結果になるのかを紹介します。動画の2値化処理を行うとこんな感じになり、台数カウントなどがしやすくなります。これらの前処理を行うことで、自分のやりたいことができるようになります。

グレースケール化/BGR→RGB変換

グレースケール化とは白と黒とその強度で色を表現します。灰色のモノクロ写真がそれにあたります。一般的にカラー画像はRGBなどの赤緑青の3色の画像の強度から作られています。白はR:255, G:255, B:255であらわされます。PythonではOpenCVのライブラリを用いて簡単にグレースケール化を行うことができます。

また、OpenCVでは、BGR表記となっており、RGB表記と逆になるため、変換が必要になる場合があります。その際には、CV2.COLORで表記を変換することができます。

以下のコマンドを行うことでグレースケール歌を行うことができます。結果を見るとカラー画像がグレースケール変換されております。OpenCVで扱う画像はBGRで表示されているため、BGR2GRAYを使用します。

import cv2
from matplotlib import pyplot as plt
filepath='img1.png'
im = cv2.imread(filepath)#OoenCVの場合、BGR表示
im_RGB=cv2.cvtColor(im,cv2.COLOR_BGR2RGBA)
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
plt.figure(figsize=(15,8))
images=[im,im_RGB,gray]
for i in range(len(images)):
    plt.subplot(1,3,i+1),plt.imshow(images[i],'gray')
    # plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

im_RGB=cv2.cvtColor(im,cv2.COLOR_BGR2RGBA)
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)

中央が元の画像になります。(余談ですがStable diffusionを使ってAIで画像生成したスカイツリーになります)左の画像は、RGBとBGRが逆転して表示されているため、空が夕焼けになっていますね。一番右がグレースケール化した画像になります。

2値化処理

2値化処理とは閾値を設けて0と1の画像に変換するものです。グレースケール化画像は0から255の強度で表されておりこれらに閾値を設けることで0か1に変換することができます。グレースケール化画像から2値化処理を行うとこのように0と1の画像に変換できます。

<通常のしきい値処理方法>
ret,th1 = cv2.threshold(画像,しきい値,255,cv2.THRESH_BINARY)

下記の画像は閾値(しきい値)を80, 150, 200と変化させたものになります。このように、閾値200では、雲のような白い画像のみが1という値になります。単純な閾値処理は下記のプログラムで実行でき、閾値の値を変化させることで出力画像が決まってきます。

ret,th1 = cv2.threshold(gray,80,255,cv2.THRESH_BINARY)
ret,th2 = cv2.threshold(gray,150,255,cv2.THRESH_BINARY)
ret,th3 = cv2.threshold(gray,200,255,cv2.THRESH_BINARY)
plt.figure(figsize=(15,8))
images=[im_RGB,th1,th2,th3]
for i in range(len(images)):
    plt.subplot(1,4,i+1),plt.imshow(images[i],'gray')
    # plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

<適応的しきい値処理方法>cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)

2値化処理にも種類があり、状況に合わせていろいろな種類のOpenCVのメソッドを使うと良いと思います。次の方法は、適応的しきい値処理の方法で、Thresh meanと呼ばれる、近傍領域の中央値をしきい値とする方法と、近傍領域の重み付け平均値をしきい値とする、Gaussianの方法になります。これらの方法は、先ほどのようにしきい値の値を変化させることができないため、出力は1画像となります。光の影響などがある場合は、これらの平均値を使用した方法が良い場合があります。

ret,th1 = cv2.threshold(gray,80,255,cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
th3 = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
plt.figure(figsize=(15,8))
images=[im_RGB,th1,th2,th3]
for i in range(len(images)):
    plt.subplot(1,4,i+1),plt.imshow(images[i],'gray')
    # plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

下の画像はOpenCVのチュートリアルの画像ですが、やはり、こういった偏って数字が見えないようなものは、適応的しきい値処理をすることで、よく見えるようになります。

こういった処理を行うことで、最終的には、下記のような動画処理(自動車の数を数えるプログラム)を行うことができます。車線事などで数えることもできるようになります。

🚀 0円で現役エンジニアから学べる【Techスクールオンライン】のお申込みをお勧めします。 このオンラインスクールでは、現役のエンジニアから直接学ぶことができ、プログラミングの基礎から高度なスキルまでを習得できます。しかも、今なら 0円 で受講できるチャンス。
私がツナグバに登録してから、求人情報が豊富に届き、自分に合った仕事を見つけることができました。特に、第二新卒向けの求人情報が多いので、自分のスキルや経験を活かしながら新たなキャリアに挑戦することができました。転職活動は不安も多いですが、ツナグバのサポートがあれば、成功への道が明るく感じました。