デジタル画像の基礎
Digital Image Fundamentals
デジタル画像とは
デジタル画像は、2次元の格子状に配置されたピクセル(画素)の集合である。各ピクセルは位置 $(x, y)$ と輝度値(または色値)を持つ。
y 軸が下向きである理由
数学の座標系では原点が左下にあり y 軸は上向きだが、画像処理では原点が左上にあり y 軸は下向きである。 これはCRTディスプレイの時代に、電子ビームが画面の左上から右へ、上から下へとラスタ走査(raster scan)していたことに由来する。 メモリ上でも画像データは左上のピクセルから順に格納されるため、行番号が増えるほど画面の下方に対応する。 この慣習は現在のすべての画像フォーマット、ディスプレイ、画像処理ライブラリ(OpenCV, PIL など)に引き継がれている。
解像度とビット深度
解像度(Resolution)
画像のピクセル数を表す。$W \times H$ で表記され、例えば 1920×1080 は約200万画素。 テレビやディスプレイの「4K」「8K」も水平方向の画素数に由来する呼称で、4K は 3840×2160(約830万画素)、8K は 7680×4320(約3300万画素)である。
※ 民生用テレビやディスプレイでは「4K UHD」(3840×2160) が標準で、映画業界の「DCI 4K」(4096×2160) とは異なる。
ビット深度(Bit Depth)
各ピクセルの輝度値を表現するビット数:
- 1ビット: 2値画像(白黒)
- 8ビット: 256階調(0〜255)。$n$ ビットでは $0$ から $2^n - 1$ の範囲
- 16ビット: 65536階調
- 24ビット: RGB各8ビット(フルカラー)
チャンネル数
チャンネル数(Number of Channels)
各ピクセルが持つ値の個数を表す。
| チャンネル数 | 名称 | 各ピクセルの値 | 用途 |
|---|---|---|---|
| 1 | グレースケール | 輝度値 1 個 | 白黒写真、医療画像、エッジ検出の前処理 |
| 3 | カラー(RGB) | 赤・緑・青の 3 個 | 一般的なカラー画像 |
| 4 | RGBA | 赤・緑・青・透明度の 4 個 | PNG、アイコン、UIデザイン |
チャンネル数が増えるほど 1 ピクセルあたりのデータ量が増える。 画像処理では、カラー画像をグレースケールに変換して 1 チャンネルにすることで計算量を削減する手法がよく使われる。
画像のメモリサイズ
画像のデータサイズは以下で計算できる:
$$\text{サイズ (bytes)} = W \times H \times \frac{\text{ビット深度}}{8} \times \text{チャンネル数}$$例: 1920×1080のフルHD画像
- グレースケール(8bit): $1920 \times 1080 \times 1 = 2,073,600$ bytes ≈ 2MB
- カラー(24bit RGB): $1920 \times 1080 \times 3 = 6,220,800$ bytes ≈ 6MB
画像の数学的表現
画像は数学的に以下のように表現される:
グレースケール画像
行列 $\mathbf{I} \in \mathbb{R}^{H \times W}$ として表現される。各成分 $I(x,y)$ がピクセルの輝度値である。
$$\mathbf{I} = \begin{pmatrix} I(0,0) & I(1,0) & \cdots & I(W-1,0) \\ I(0,1) & I(1,1) & \cdots & I(W-1,1) \\ \vdots & \vdots & \ddots & \vdots \\ I(0,H-1) & I(1,H-1) & \cdots & I(W-1,H-1) \end{pmatrix}$$※ ここでは数学的な慣例に従い $I(x, y)$ の順序で書いているが、NumPy/OpenCV では img[y, x](行, 列)の順序でアクセスする。
カラー画像
3次元テンソル $\mathbf{I} \in \mathbb{R}^{H \times W \times C}$(C: チャンネル数、通常3)
$$I(x, y) = \begin{pmatrix} R(x,y) \\ G(x,y) \\ B(x,y) \end{pmatrix}$$OpenCV はなぜ BGR 順序なのか
一般的な画像形式(PNG, JPEG など)は RGB 順序だが、OpenCV は BGR 順序を採用している。 これは技術的な合理性ではなく、歴史的な経緯による。 OpenCV は1999年に Intel が開発を開始したが、当時 Windows で主流だったカメラ API(Video for Windows)やビットマップ形式(BMP/DIB)が BGR 順序でデータを返していたため、それに合わせた。 Windows の BMP が BGR なのは、Intel x86 のリトルエンディアンでメモリに 32bit RGBA を格納すると B, G, R, A の順になることに由来する。 OpenCV がクロスプラットフォーム化した後も、既存コードとの互換性のために BGR のまま維持されている。
OpenCV で読み込んだ画像を他のライブラリ(PIL, matplotlib など)で表示する際は cv2.cvtColor(img, cv2.COLOR_BGR2RGB) で変換が必要である。
コード例(Python)
import numpy as np
import cv2
# 画像の読み込み
img_color = cv2.imread('image.jpg') # カラー (H, W, 3)
img_gray = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE) # グレースケール (H, W)
# 画像のプロパティ
print(f"Shape: {img_color.shape}") # (高さ, 幅, チャンネル数)
print(f"Dtype: {img_color.dtype}") # uint8 (0-255)
print(f"Size: {img_color.size} bytes") # 総バイト数
# ピクセルへのアクセス
pixel = img_color[100, 200] # (B, G, R) の値
gray_value = img_gray[100, 200] # 輝度値
# 新しい画像の作成
blank = np.zeros((480, 640, 3), dtype=np.uint8) # 黒画像
white = np.ones((480, 640), dtype=np.uint8) * 255 # 白画像
まとめ
- デジタル画像はピクセルの2次元配列
- 解像度は画像のピクセル数、ビット深度は階調数を決める
- グレースケールは2次元行列、カラーは3次元テンソル
- 画像処理では行列演算が基本となる