デジタルC

デジタル画像とC言語
画像の表現
• 一般的に、画像は2次元配列で表現される
例:320x240(240行、320列)画素の濃淡画像
unsigned char image[240][320];
説明:
unsigned = 符号なし
char = 文字型
unsigned char = 符号なしの文字型で
8
0~255 (= 2  1 )の値が表現できる
画像の操作(1)
位置が(x,y)である画素は, y行、x列にある画素である。
0列
1列
2列
x列
0 行
1 行
2 行
y行
画素値の読出し:
例: (x,y)の画素の値を変数vに代入する。
(変数vは既に定義しているものとする)
v = image[y][x];
画像の操作(2)
0列
1列
2列
x列
0 行
1 行
2 行
y行
画素値の設定:
例: (x,y)の画素の値を128にセットする。
image[y][x] = 128;
画像操作の例:90度回転(1)
y
x
y’ x
H
x’
y
W
W
H
元画像の(x,y)の画素が回転した後の位置(x’,y’)とする。
x’= H -1 – y;
y’= x;
元画像を表す配列: image 回転した後の画像を表す配列: image_new
とすると、 image_new[x][H-1-y] = image[y][x]; で回転したあとの画素値が設
定できる。
画像操作の例:90度回転(2)
y
x
y’ x
H
y
x’
W
W
int x,y;
for (y = 0; y < H; y++)
for (x = 0; x < W ; x++)
image_new[x][H-1-y] = image[y][x];
H
画像の移動(1)
y
Δy
Δy +
y
Δx
x
H
H
Δx + x
W
画像をX方向にΔx, Y方向にΔyを移動する。
(x,y)の画素が移動後に (x’,y’)なるとすると、
x’= x + Δx;
y’= y + Δy;
W
画像の移動(2)
y
Δy
Δy +
y
Δx
x
H
H
Δx + x
W
W
元画像を表す配列: image 回転した後の画像を表す配列: image_new
とすると、
image_new[y+Δy][x+Δx] = image[y][x];
で移動したあとの画素値が設定できる。
画像内の移動(3)
(x0,y0)
h dy
w
dx
画像を表す配列: image
移動する矩形部分の左上の角の座標: (x0,y0)
横幅、縦幅: w, h
水平、垂直方向の移動量、dx, dy
とすると、
int x, y;
for (y = y0; y < y0+h; y++)
for (x = x0; x < x0+w; x++) {
xnew = x + dx;
ynew = y + dy;
image[ynew][xnew] = image[y][x];
}
で図に示すように矩形部分の画像を移動することが
できる。
しかし
画像内の移動(1)
(x0,y0)
dy
移動元 と 移動先 と 重なる 部分があると、
処理は難しくなる。
h
dx
dy
h
(x0,y0)
dx
画像内の移動 移動の順序(1)
int x, xnew;
for (x= 0; x < 4; x++) {
xnew = x + 2;
image[xnew] = image[x];
}
移動前
正しい結果
1
2
3
4
5
6
7
8
9
1
1
2
1
4
5
6
7
8
9
x: 0, xnew: 2 image[2] = image[0]
1 2 1 2 5 6 7 8 9
x: 1, xnew: 3 image[3] = image[1]
1
2
1
2
1
9
x: 2, xnew: 4 image[4] = image[2]
1
2
1
2
1 2 7 8 9
x: 3, xnew: 5 image[5] = image[3]
6
7
8
2
1
間違った!
2
3
4
7
8
9
画像内の移動 移動の順序(2)
int x, xnew;
for (x= 3; x >= 0; x--) { /* 逆の順でコピーする */
xnew = x + 2;
image[xnew] = image[x];
}
移動前
1
2
3
4
5
6
7
8
9
1
1
2
3
4
5
4
7
8
9
x: 3, xnew: 5 image[5] = image[3]
1 2 3 4 3 4 7 8 9
x: 2, xnew: 4 image[4] = image[2]
1
2
3
2
3
4
7
8
9
x: 1, xnew: 3 image[3] = image[1]
1
2
1
2
3
4
7
8
9
x: 0, xnew: 2 image[2] = image[0]
正解!
2
正しい結果
1
2
3
4
7
8
9
画像内の移動 移動範囲
(x0,y0)
移動した後の矩形領域は画像の範囲を超えること
がある。
dy
dx
この場合、移動しようとする矩形の画像範囲から
はみ出す部分を削り、移動した後も画像の範囲内に
なるようにする。 (削り=矩形の形を変える)
(x0,y0)
dy
dx
実際にプログラムを書いてみよう
• 画像処理のプログラムを書くために、画像処理用の
ライブラリが要る。
理由: 下記の機能が必要である。
① 処理しようとする画像の読込み
(ファイルなどから)
② 処理結果を保存する画像の用意
③ 処理結果をファイルに保存する
が、これらの部分を作るのは面倒で、難しい。
RASLIB:画像処理演習用ライブラリ
RASLIBは、私(陳謙)が画像処理のプログラムを簡単に書けるため
に作ったライブラリである。
Linux版とWindows版両方あるが、Linux版をお勧めする。
以降の説明はLinux版に関するものである。
RASLIBのダウンロード
① ダウンロード:RASLIBのWEBページ
http://www.wakayama-u.ac.jp/~chen/RASLIB/raslib.htm
からダウンロードできます。
そのページの“RASLIBの入手”の章から、raslib.tgzという
ファイルをダウンロードしてください。
(firefoxのデフォールトのダウンロード先は $HOME/Desktop です。)
RASLIB:画像処理演習用ライブラリ
RASLIBのインストール
1.端末ウィンドウを開く。
2.端末ウィンドウで次の命令を入力することにより、
ダウンロードした raslib.tgz ファイルを自分のホームに
移動する。
cd
mv $HOME/Desktop/raslib.tgz
.
3.以下の命令を実行して、必要なディレクトリを作ってください。
mkdir
include
lib
4.ダウンロードしたファイルを解凍します。
tar
xvzf
raslib.tgz
5.ソフトウェアをコンパイルし、インストールします。
cd
RASLIB
make
clean
make
PREFIX=$HOME
install
これでインストールが完了します。
RASLIBを使って画像を生成する(1)
0 1 2
15 16 17
...
...
15
31
32 33 34
...
47
240 241 242
. . .
255
16x16画素
256x256画素の濃淡画像: 中身は16x16個=256個の正方形の領域である。
1個の領域の大きさは16x16画素で、画素値は全部同じである。
/* Begin grey_image_16x16.c */
#include “raslib.h” /* RASLIBを使うプログラムにはこれが必要 */
int main(int argc, char **argv) /* main関数はこのように書く */
{
Rasimg *img;
/* 画像を現す関数。RASLIBでは、画像は Rasimg *型の変数で表現される。*/
RASLIBを使って画像を生成する(2)
int block_x; /* 横のブロックの番号 */
int block_y; /* 横のブロックの番号 */
int v; /* ブロックの画素値 */
int x0, y0; /* ブロックの左上の角の座標 */
int x, y;
unsigned char **image;
/* 画像の中身を現す変数,画像を現す2次元配列のように使える */
img = ras_alloc(256, 256, 8);
/* 256x256画素の濃淡画像(8bit)を用意する */
/* ras_alloc(横, 縦, ビット数) は 「横」x「縦」 画素で、
1画素が「ビット数」ビットの画像を用意するための関数である。*/
image = ras_lnidx(img);
/* Rasimg *型の変数から、画像の中身を現す変数を取り出す。
その後、imageは2次元配列のように使える */
RASLIBを使って画像を生成する(3)
/* 画素値をセットする */
for (block_x = 0; block_x < 16; block_x++) {
x0 = block_x * 16;
for (block_y = 0; block_y < 16; block_y++) {
y0 = block_y * 16;
v = block_y * 16 + block_x;
for (x = 0; x < 16; ++x)
for (y = 0; y < 16; ++y)
image[y+y0][x+x0] = v;
}
}
pnm_save(“grey256.pgm", img);
return 0;
}
/* End */
RASLIBを使って画像を生成する(4)
コンパイルと実行
1.grey_image_16x16.c を作ります
emacs を使って、“ /* Begin grey_image_16x16.c */ から/* End
*/ までの部分の内容の「grey_image_16x16.c」というファイルを作る。
2
コンパイル
grey_image_16x16.c は次のようにコンパイルする。
cc -I$HOME/include -L$HOME/lib grey_image_16x16.c -o
grey_image_16x16 -lras
3
コンパイルしたプログラムを実行する
./grey_image_16x16
4
実行結果を確認する
gimp grey256.pgm
練習問題1:
grey_image_16x16.cを改造して(pnm_saveの前に追加)、作ったグレーブロック
の画像を90度回転するプログラムを作りなさい。