【数値情報処理b】第1回 デジタル画像について

数値情報処理b について

コンピュータで扱う画像はデジタルデータである。 画像を見やすくしたり、画像から情報を抽出することは画像処理ソフトウェアを使えば簡単にできるが、その画像処理の原理を知らなければソフトウェアを使いこなすことができない。 本講義では R と imager を使って様々な画像処理の方法の原理について学ぶ1)


授業では RStudio を使用する。 RStudio は Web ブラウザで動作する R のIDE(統合開発環境)である。

学内の RStudio サーバにアクセスできるのは学内の環境からのみになる。

学外で RStudio を使いたい場合は、3つ方法がある。

  1. VPN 接続した後、ブラウザで学内 RStudio サーバにアクセス

学内 RStudio サーバの利用

プロジェクトの作成

「数値情報処理b」用のプロジェクトを作成する。

  1. 右上のプロジェクトボタンをクリックして [New Project] を選ぶ、もしくはメニューの [File][New Project] を選ぶと「Create Project」のウィンドウが開く。
  2. [New Directory] を選ぶ。
  3. [New Project] を選ぶ。
  4. 「Directory name:」にプロジェクト名「数値情報処理b」を入力する(RStudio Cloud では日本語のプロジェクト名を使わない方がいいので英語でプロジェクト名を入力する)。
  5. 「Create project as subdirectory of:」 が「~」になっていなければ [Browse] をクリックして [Home] ボタンをクリックした後 [Choose] ボタンをクリックする。
  6. [Create Project] をクリックする。

これでプロジェクトが作成できる。

他の講義でこの学内 RStudio サーバを使う場合は、ファイルが混ざってごちゃごちゃにならないように講義ごとにプロジェクトを作成し、プロジェクトを切り替えて使うと良い。

別のプロジェクトの切り替えは右上のプロジェクトボタンから行う。

R と RStudio の使い方

画像編集用ソフトウェア

画像編集用ソフトウェアは、画像を表示するだけでなく、変形や合成を行えるなど様々な機能を持っている。

代表的な画像編集用ソフトウェアは以下のものがある。

本講義では画像編集ソフトウェアが実際にどのような処理を行っているのかを R のプログラムを通して理解する。

imager(R のパッケージ)

本講義では R で画像を扱うために imager という画像処理のパッケージを利用する。

imager を利用するには2通りの方法がある。

library(imager)

画像の読み込み

画像の読み込みは load.image() で行う。

> 変数 <- load.image("ファイル名")

ファイル名には RStudio サーバにアップした画像ファイルや URL を指定する。 このコマンドでは、読み込まれた画像のデータが変数に代入され、その型は cimg になる。

以下、cimg 型の変数を「cimg 変数」とする。


画像の表示

画像の表示は plot() で行う。

> plot(cimg変数)

RStudio では、右下のペインの Plots タブにグラフのように画像が表示される。

さらに引数を追加することができる。 よく使う引数は以下の通り。

引数 デフォルト 機能
rescale TRUE TRUE だと画素値が [0,1] の範囲になるように調整される(リスケール)。
interpolate TRUE TRUE だと画像の画素を滑らかに表示する(アンチエリアス)。
axes TRUE TRUE だと軸を表示する。

例えば以下のコマンドでは、im という cimg 変数に https://www.koeki-u.ac.jp/images/base/logo.jpg という URL の画像を読み込み表示する(# 以下はコメント)。

> im <- load.image("https://www.koeki-u.ac.jp/images/base/logo.jpg")
> plot(im)
> plot(im, axes = FALSE)     # 軸を表示しない

サンプル画像

imager ではサンプル画像が用意されている。

特に boats はあらかじめ cimg 変数として用意されているのですぐに使えて便利である。

> plot(boats)

その他のサンプル画像は load.example() で読み込む必要がある。

画像名 説明
parrots オウムの写真
coins コインの写真
birds 鳥の絵
hubble ハッブル宇宙望遠鏡で撮影された深宇宙の画像
tennis 卓球の動画
> im <- load.example("parrots")
> plot(im)

画像の書き出し

cimg 型の変数のデータを画像ファイルに書き出すには save.image() を使う。

> save.image(cimg変数, "ファイル名")

画像ファイルフォーマットはファイル名の拡張子で判断される。

JPEG の場合は、引数に quality を与えることで品質を設定できる。 品質の値は 0 から 1 の間の範囲で、1 に近いほど高品質になり画像の劣化は少ないが、ファイルサイズは大きくなる(デフォルトは 0.7)。

画素値が [0,1] の範囲以外の場合は自動的にリスケールされる。

書き出した画像ファイルは RStudio サーバに保存される。 RStudio サーバに保存された画像ファイルは右下のペインの Files タブでクリックすればブラウザ上に表示されるので、それを自分の PC や端末に保存できる。


新規画像の作成

新規画像を作成するには imfill() を使う。

> 変数 <- imfill(横幅, 縦幅, val = 塗りつぶしの色)

塗りつぶしの色には "black", "white", "red" のように英語文字列で色名を与えるか、c(1,0,0) のように RGB の値で与えることができる。


文字列の描画

画像に文字列を描画するには draw_text() を使う。 cimg 変数の画像を背景とした文字列を描画した新しい画像を生成する場合は以下のようになる(元の cimg 変数は変わらない)。

> draw_text(cimg変数, x座標, y座標, 文字列, col = フォント色)

フォント色には "black", "white", "red" のように英語文字列で色名を与えるか、c(1,0,0) のように RGB の値で与えることができる。

オプション fsize でフォントサイズを変更できる(デフォルトは 20 ピクセル)。

例えば以下のコマンドでは、黒で塗りつぶした画像を im1 に代入し、im1 を背景として文字列 "KOEKI" を描画した画像を im2 に代入する。

> im1 <- imfill(60, 20, val = "black")
> im2 <- draw_text(im1, 1, 1, "KOEKI", col = "white")

デジタル画像

コンピュータの中では画像は画素(ピクセル)の集合として描かれる。 1 つの画素は 1 色で塗りつぶされたタイルである。 それぞれの画素における色の濃淡の値を画素値という。

画素のイメージ

上図のように画像中の画素は縦と横に格子状に並んでいる。 右方向を $x$ 軸の正方向下方向を $y$ 軸の正方向2)にとり、画素の(中心)座標は $(x,y)$ で表す。

それぞれの画素の画素値はコンピュータの中では配列として格納されている。 一般的な画素値は 8bit(1byte)の整数で表される。 つまり $2^{8}=256$ 階調で 0 から 255 の範囲の整数値であり、小さいほど暗く大きいほど明るい。

コンピュータでは、色は光の 3 原色である 赤(Red)緑(Green)青(Blue) の重ね合わせで表現される。 これらは略して R, G, B とそれぞれ呼ばれる。

光の三原色

カラー画像の場合、1 つの画素には R, G, B の 3 つの情報があり、カラーチャンネルという。 それぞれのカラーチャンネルは 256 階調の画素値を持ち、 R, G, B の 3 つのカラーチャンネルを合わせると $256^{3}=16777216$ 色の表現が可能である。

カラー画像のカラーチャンネル

グレースケール画像(モノクロ画像)の場合、1 つのカラーチャンネルの情報で表現できる。 256 階調の画素値を持ち、0 だと真っ黒、255 だと真っ白を表す。

グレースケール画像

カラーチャンネルの他にアルファチャンネルを持つ場合があり、補助的な情報(透明度など)に利用される。


cimg型

imager で読み込んだ画像は cimg 型のデータである。

cimg 型は4次元の配列であり、各次元は順に x, y, z, cc となっている。

各次元 意味
x 横方向の座標
y 縦方向の座標
z z は動画のフレーム番号(画像では使わないので z=1 に固定)
cc カラーチャンネル

各次元の配列のサイズは dim(cimg変数) で分かる。

> dim(boats)
[1] 256 384   1   3

boats の画像は

であることが分かる。

画像のサイズを知るための関数としては以下がある。

関数 機能
width(cimg変数) x のサイズ(横幅)を返す。
height(cimg変数) y のサイズ(縦幅)を返す。
depth(cimg変数) z のサイズ(動画のフレーム数)を返す。画像の場合は 1 である。
spectrum(cimg変数) カラーチャンネル数を返す。
dim(cimg変数) 横幅、縦幅、フレーム数、カラーチャンネル数を返す。
nPix(cimg変数) 全ピクセル数(横幅×縦幅×フレーム数×チャンネル数)を返す。
prod(dim(cimg変数)) と同じ。

カラー画像の場合、各カラーチャンネルの画素値の配列は以下のように取り出せる(#以下はコメント)。

> imc <- boats
> imc[, , 1, 1]     # Rチャンネル
> imc[, , 1, 2]     # Gチャンネル
> imc[, , 1, 3]     # Bチャンネル

これで取り出した値は matrix 型になるので plot() で表示させようとしても画像表示にはならない。 画像表示させたければ、as.cimg() で cimg 型にするとよい。

> plot(as.cimg(imc[, , 1, 1]))

座標 $(x,y)$ の画素値を取り出すには以下のようにする。

> imc[x, y, 1, 1]    # Rチャンネルの座標(x,y)の画素値

color.at() を使うと座標 $(x,y)$ の全てのカラーチャンネルの画素値が取り出せる。

> color.at(imc, x, y)

一般的な画素値は 0 から 255 の範囲の整数値と上で述べたが、cimg の画素値は一般的な画素値を 255 で割って 0 から 1 の範囲 [0,1] の実数値にしたものになる。 [0, 1] の範囲以外の値も一応使えるが、plot() などでは自動的にリスケールして解釈されることがある。

グレースケール化

カラー画像は grayscale() でグレースケール化することができる。

> grayscale(cimg変数)

グレースケール画像の場合、基本的にカラーチャンネルは1つだけである3)

> img <- grayscale(boats)  # グレースケール化
> dim(img)
[1] 256 384   1   1

grayscale() は元の画像にアルファチャンネルが含まれているとうまくいかない。 そのときはアルファチャンネルを rm.alpha() で削除する必要がある。

> im <- load.image("https://www.kitp.org/class/lib/exe/fetch.php?media=numericalipb:sample_rgb.png")
> dim(im)
[1] 964 343   1   4              # カラーチャンネルが4チャンネル
> img <- grayscale(im)           # アルファチャンネルのためにエラー
> img <- grayscale(rm.alpha(im))
> plot(img)

画像ファイルフォーマット

当然ながらサイズの大きい画像ほどデータ量は多くなる。

画素値が8bit(1byte)とすると、横 $w$ ピクセル、縦 $h$ ピクセルの画像のデータ量は、グレースケール画像では1 チャンネルのみなので $w\times h$ bytes、カラー画像では 3 チャンネルになるので $w\times h\times 3$ bytes になる。

例えば、横 2000ピクセル、縦 1000ピクセルのカラー画像では、 \[ 2000\times 1000\times 3=6\times 10^{6}\mathrm{bytes}=6\mathrm{Mbytes} \] となり、一枚でかなりのデータ量になる。

このように大きな画像データをそのまま保存するのは容量の無駄なので、何らかのアルゴリズムを使って小さいデータ量に圧縮してファイルに保存するのが普通である。

例えば、16進数で「3a, 3a, 3a, 3a, 3a, 3a, b1, b1, b1, b1」というデータは 10bytes だが、0x3a が6個と 0xb1 が4個続くので「3a, 06, b1, 04」というデータで表すことにすれば 4bytes で済む。 これはかなり原始的な圧縮アルゴリズムであるが、現在はより効率的な圧縮アルゴリズムが色々と開発されて使われている。

圧縮した画像は展開して元の画像に戻して見ることができる。 圧縮方法には完全に元の画像に戻せる可逆圧縮と完全には戻せない不可逆圧縮がある。 一般的に可逆圧縮より不可逆圧縮の方が圧縮率は高い。 特に写真画像は様々な色や形が混じっているので、不可逆圧縮で少々情報が失われてもパッと見では違いが分からない。

以下は一般的な画像ファイルフォーマットである。

フォーマット 拡張子 圧縮 説明
JPEG .jpg, .jpeg 主に不可逆 写真画像に適している。品質を設定できる。
PNG .png 可逆 CGなどに適している。
GIF(ジフ) .gif 可逆 アニメーション機能がよく使われる(GIFアニメーション)。
256色までしか使えない。
Windows bitmap .bmp 無圧縮 Windows で標準的に使われる。

課題

Moodle Server(非公式)で第1回の課題を行いなさい。

Moodleでファイル提出の方法

締め切り:2025年6月18日(水)20時

1)
R を使うが、Ruby でも C 言語でも同じことができる。
2)
数学の場合は上方向を $y$ 軸の正方向にとる。
3)
ただし、RGB の3チャンネルでもグレースケールを表現することは可能。