画像処理100本ノック完全ガイド 001:グレースケール化・二値化

Python

はじめに

画像処理は、デジタル画像を操作してその内容を解析、変換、編集する技術です。この技術は、写真編集、医療画像解析、自動運転車の視覚システムなど、さまざまな分野で利用されています。このシリーズは、実際の画像処理技術をPythonで実装することで、理論と実践を組み合わせた学習を目指しています。この記事では、最初の三つの問題に取り組みます。各問題について、解説とともにPythonコードを提供し、具体的な処理方法を理解していきましょう。この記事では、画像処理100本ノックで用意されている「imori.jpg」をダウンロードしてください。ダウンロードのURLはこちらです。

画像処理100本ノック 001. チャネルの入れ替え

画像を読み込み、BGRをRGBの順に入れ替えよ。
画像の赤成分を取り出すには、以下のコードで可能。 cv2.imread()関数ではチャネルがBGRの順になることに注意! これで変数redにimori.jpgの赤成分のみが入る。
※元の問題では「RGBをBGRの順に入れ替えよ」となっていますが、cv2.imread関数でBGRの順に読み込まれるため、簡単化として「BGRをRGBの順に入れ替えよ」としています。

画像処理100本ノック
import cv2
img = cv2.imread("imori.jpg")
red = img[:, :, 2].copy()

方針

RGBとは、赤 (Red)、緑 (Green)、青 (Blue) の三色の光の強度で色を表現する方法です。BGRはその逆順で、青 (Blue)、緑 (Green)、赤 (Red) の順番です。多くの画像処理ライブラリでは、色チャネルの順序がRGBやBGRで指定されます。この問題では、画像を読み込んだ後、RGBの順番をBGRに入れ替える操作を行います。以下は実装の手順です。

  1. 画像を読み込む:
    cv2.imread 関数で画像を読み込みます。下図のように、BGR形式で画像が読み込まれます。
  2. チャンネルを入れ替える: B、G、Rのチャンネルを個別に抽出し、R、G、Bの順にチャンネルを並び替えます。並び替える際には、numpyのstack関数を使います。np.stackは、指定した軸に沿って一連の配列を結合する関数です。例えば、B、G、Rのチャンネルをそれぞれの配列として抽出した後、それらを新しい軸に沿って結合し、1つの画像として再構成できます。詳しい使い方は公式のドキュメントを確認してみてください。
  3. 画像を表示する:
    matplotlibのimshowによって画像を表示します。

解答と実行結果

import numpy as np
import cv2
from matplotlib import pyplot as plt

# 画像を読み込む
image = cv2.imread('imori.jpg')

# 各チャンネルの抽出
blue_channel = image[:, :, 0]
green_channel = image[:, :, 1]
red_channel = image[:, :, 2]

# チャンネルの結合
output = np.stack([blue_channel, green_channel, red_channel], 2)

# 変換後の画像を表示する
plt.imshow(output)
plt.axis('off')
plt.show()

このコードを実行すると、次のような結果(右の画像)が得られます。

画像処理100本ノック 002. グレースケール化

画像をグレースケールにせよ。 グレースケールとは、画像の輝度表現方法の一種であり下式で計算される。
Y = 0.2126 R + 0.7152 G + 0.0722 B

画像処理100本ノック

方針

カラー画像からR、G、Bのチャンネルを抽出し、指定された式に基づいて輝度値を計算します。この計算により、カラー画像がグレースケール画像に変換されます。以下は実装の手順です。

  1. 画像を読み込む:
    cv2.imread 関数を使用して画像をカラーで読み込みます。
  2. RGBチャンネルを抽出する:
    画像からR、G、Bチャンネルをそれぞれ抽出します。
  3. グレースケール化の計算を行う:
    指定された式 Y=0.2126R+0.7152G+0.0722B を使用して輝度値を計算します。その際、データ型をuint8型に変換しましょう。uint8型に変換する理由は、画像データは通常0から255の範囲の整数値で表され、uint8型はこの範囲を正確に表現できるためです。これにより、メモリの使用量が最小限に抑えられ、画像処理ライブラリ(例えばOpenCVやmatplotlibなど)が正しく画像データを処理できるようになります。
  4. 画像を表示する:
    グレースケール画像を matplotlib で表示し、元の画像と比較します。plt.imshowを呼び出すときにcmap=’gray’と指定することで、グレースケールで画像を表示することができます。

解答と実行結果

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 画像を読み込む(BGR形式)
image = cv2.imread('imori.jpg')

# 各チャンネルの抽出
blue_channel = image[:, :, 0]
green_channel = image[:, :, 1]
red_channel = image[:, :, 2]

# グレースケール化の式に従って計算
gray_image_custom = 0.2126 * red_channel  + 0.7152 * green_channel  + 0.0722 * blue_channel

# グレースケール画像のデータ型をuint8に変換
gray_image_custom = np.clip(gray_image_custom, 0, 255).astype(np.uint8)

# 画像をグレースケールで表示
plt.imshow(gray_image_custom, cmap = "gray")
plt.axis('off')
plt.show()

このコードを実行すると、次のような結果(右の画像)が得られます。

画像処理100本ノック 003. 二値化

画像を二値化せよ。 二値化とは、画像を黒と白の二値で表現する方法である。 ここでは、グレースケールにおいて閾値を128に設定する。

画像処理100本ノック

方針

この問題では、画像を二値化する方法を学びます。グレースケール画像を読み込み、各ピクセルの値が指定した閾値(128)より大きいか小さいかに基づいて、ピクセルの値を0(黒)または255(白)に設定します。この処理により、画像が二値化されます。

  1. 画像をグレースケールとして読み込む: cv2.imread 関数を使用して画像をグレースケールとして読み込みます。
  2. 二値化画像のメモリの確保: 画像のサイズに対応するメモリ領域を確保します。読み込んだ画像と同じ大きさのbinary_imageを定義しましょう。
  3. 二値化を実行する: Pythonの条件分岐(if文)を使って、各ピクセルの値が閾値(128)以上かどうかを判定し、二値化処理を行います。読み込んだグレースケール画像の画素値が128以上の場合にはbinary_imageの画素値を1に、それ以外の場合にはbinary_imageの画素値を0とします。
  4. 画像を表示する: 二値化後の画像を matplotlib で表示します。

解答と実行結果

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 画像をグレースケールとして読み込む
gray_image = cv2.imread('imori.jpg', cv2.IMREAD_GRAYSCALE)

# 二値化処理を手動で実行
threshold = 128
height, width = gray_image.shape
binary_image = np.zeros((height, width), dtype=np.uint8)  # 全て0(黒)で初期化

# 各ピクセルを条件分岐で処理
for i in range(height):
    for j in range(width):
        if gray_image[i, j] >= threshold:
            binary_image[i, j] = 255  # 白
        else:
            binary_image[i, j] = 0  # 黒

# 画像をグレースケールで表示
plt.imshow(binary_image, cmap = "gray")
plt.axis('off')
plt.show()

このコードを実行すると、次のような結果(右の画像)が得られます。

最後に

この記事では、画像処理の基本的な操作として、RGBチャネルの入れ替え、グレースケール化、二値化の3つの手法について詳しく解説しました。これらの手法を理解することで、さらに高度な画像処理技術へのステップアップが可能になります。次回も引き続き、画像処理の基本を学んでいきましょう。

私の経歴などについては以下の記事から確認することができます!

ブログランキングに参加しています。ぜひクリックで応援お願いします

ブログランキング・にほんブログ村へ
「#Python」人気ブログランキング

コメント

タイトルとURLをコピーしました