画像情報処理特論⑥

149 Views

December 09, 23

スライド概要

第6回 描画操作、領域塗りつぶし

profile-image

大学教員です。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

(ダウンロード不可)

関連スライド

各ページのテキスト
1.

2018/05/24 画像情報処理特論 第6回 描画操作、領域塗りつぶし 東京工科大学 助教 加納 徹

2.

授業計画 第1回:ガイダンス、Java開発環境の構築 第2回:GUIアプリケーション開発、画像データの入出力 第3回:前処理(1)(二値化処理、画像の配列化) 第4回:前処理(2)(モルフォロジー演算) 第5回:前処理(3)(平滑化、鮮鋭化) 第6回:後処理(1)(描画操作、領域塗りつぶし) 第7回:画像の定量評価(MSE、PSNR、CNR) 第8回:コンピュータ診断支援への展開、まとめ 2

3.

注意事項 ⚫ 前回作った GUI を一部削除します ⚫ プロジェクトを右クリックし、 [コピー] で複製しておくことを おすすめします 3

4.

マウスによる描画操作

5.

マウスによる描画操作 マウスによる描画操作の流れ マウスの座標取得 取得座標の情報から BufferedImage を操作 BufferedImage をラベルに表示 5 今回はお絵かきプログラムみたいな感じ

6.

クリック処理の追加 ラベル上で右クリックし、[イベント] ➡ [Mouse] ➡ [mouseClicked] と進む 6

7.

クリック処理の追加 lblDrawMouseClicked (ラベル上でクリックした際に呼ばれるメソッド) private void lblDrawMouseClicked(java.awt.event.MouseEvent evt) { // マウスのX,Y座標を取得し、変数に格納 int mouseX = evt.getX(); int mouseY = evt.getY(); // マウス座標に基づいて画像編集(ここではクリックした点を白くする命令) bufImageShow.setRGB(mouseX, mouseY, white); // BufferedImage をラベルに貼り付け lblDraw.setIcon(new ImageIcon(bufImageShow)); } 自分がわかりやすいようにどんどんコメントを書こう

8.

実行結果 8

9.

クリック処理の追加 lblDrawMouseClicked (ラベル上でクリックした際に呼ばれるメソッド) private void lblDrawMouseClicked(java.awt.event.MouseEvent evt) { // マウスのX,Y座標を取得し、変数に格納 int mouseX = evt.getX(); int mouseY = evt.getY(); // マウス座標を中心とした正方形(中心から各辺までの距離が5)を描画するメソッド fillSquare(bufImageShow, imageWidth, imageHeight, mouseX, mouseY, 5); // BufferedImage をラベルに貼り付け lblDraw.setIcon(new ImageIcon(bufImageShow)); } メソッドの作り方、覚えてる?

10.

実行結果 10

11.

演習問題 【演習1】 引数として画像データ(BufferedImage)、画像の幅(int)、画像の高 さ(int)、マウスX座標(int)、マウスY座標(int)、中心から各辺まで の距離(int)を与え、正方形を描画する(配列の該当部分を255で埋め る)fillSquare() メソッドを完成させなさい。 【課題2】 引数として画像データ(BufferedImage) 、画像の幅(int)、画像の 高さ(int)、マウスX座標(int)、マウスY座標(int)、半径(int)を与 え、円を描画する(配列の該当部分を255で埋める)fillCircle() メソッド を完成させなさい。 ブレゼンハムのアルゴリズムを応用することで高速化可能 11

12.
[beta]
正方形を描画するメソッドの例
fillSquare() (正方形領域を描画するメソッド)
void fillSquare(BufferedImage image, int width, int height, int ox, int oy, int r) {
// マウス座標 (ox, oy) を中心とし、各辺までの距離が r の正方形領域
for (int y = oy - r; y <= oy + r; y++) {
for (int x = ox - r; x <= ox + r; x++) {
// (x, y) が画像の範囲外である場合、処理をスキップ

if (x < 0 || x > width - 1 || y < 0 || y > height - 1) continue;

まずは自分の力で考えてみよう

// (x, y) が画像の範囲内である場合、白で塗る
image.setRGB(x, y, white);
}
}
}

画像からはみ出した際の例外処理もしっかり書こう

13.
[beta]
円を描画するメソッドの例
fillCircle() (円領域を描画するメソッド)
void fillCircle(BufferedImage image, int width, int height, int ox, int oy, int r) {

// マウス座標 (ox, oy) を中心とし、半径が r の円領域
for (int y = oy - r; y <= oy + r; y++) {
for (int x = ox - r; x <= ox + r; x++) {
// (x, y) が画像の範囲外である場合、処理をスキップ
if (x < 0 || x > width - 1 || y < 0 || y > height - 1) continue;
// (x, y) が半径 r の円形範囲内である場合、白で塗る

まずは自分の力で考えてみよう

if ((x - ox) * (x - ox) + (y - oy) * (y - oy) < r * r) {
image.setRGB(x, y, white);
}
}
}

}

点が円の内部に含まれる条件を方程式で考えよう

14.

ドラッグ処理の追加 ラベル上で右クリックし、[イベント] ➡ [MouseMotion] ➡ [mouseDragged] と進む 14

15.

ドラッグ処理の追加 lblDrawMouseDragged (ラベル上でドラッグした際に呼ばれるメソッド) private void lblDrawMouseDragged(java.awt.event.MouseEvent evt) { // マウスのX,Y座標を取得し、変数に格納 int mouseX = evt.getX(); int mouseY = evt.getY(); // マウス座標を中心とした円(半径が5)を描画するメソッド fillCircle(bufImageShow, imageWidth, imageHeight, mouseX, mouseY, 5); // BufferedImage をラベルに貼り付け lblDraw.setIcon(new ImageIcon(bufImageShow)); } クリックの処理と何も変わっていない

16.

実行結果 16 線が途切れ途切れ・・・

17.

実行結果(応用) 17 線が繋がった!

18.

線を繋げる操作の流れ 直前のマウス座標を記憶するフィールド変数を作成 (mouseBufX, mouseBufY) ※ mousePressed() の中で、(mouseBufX, mouseBufY) の値を初期化する mouseDragged() で現在のマウス座標を取得 (mouseX, mouseY) マウスの移動距離を計算 (dis = hypot(mouseX – mouseBufX, mouseY - mouseBufY)) マウスの単位移動距離を dis から算出し、移動経路上の各点で描画処理 直前のマウス座標の更新 (mouseBufX,Y ← mouseX,Y) 18 うっ・・・

19.
[beta]
線を繋げる操作のコード例
lblDrawMouseDragged (ラベル上でドラッグした際に呼ばれるメソッド)
private void lblDrawMouseDragged(java.awt.event.MouseEvent evt) {

int mouseX = evt.getX();
int mouseY = evt.getY();
int x, y, dis = (int) Math.hypot(mouseX - mouseBufX, mouseY - mouseBufY);
for (int i = 0; i < dis; i++) {
x = mouseBufX + i * (mouseX - mouseBufX) / dis;
y = mouseBufY + i * (mouseY - mouseBufY) / dis;
fillCircle(bufImageShow, imageWidth, imageHeight, x, y, 5);
}
fillCircle(bufImageShow, imageWidth, imageHeight, mouseX, mouseY, 5);
lblDraw.setIcon(new ImageIcon(bufImageShow));
mouseBufX = mouseX;

mouseBufY = mouseY;
}

lblDrawMousePressed (ラベル上でプレスした際に呼ばれるメソッド)
private void lblDrawMouseDragged(java.awt.event.MouseEvent evt) {

mouseBufX = evt.getX();
mouseBufY = evt.getY();
}

今回だけだぞ

20.

塗りつぶし処理

21.

塗りつぶし処理 1. 画像の一点をクリック 21 2. クリックした点を白くする

22.

塗りつぶし処理 2. クリックした点を白くする 22 3. クリックした点の 上下左右をチェックする

23.

塗りつぶし処理 3. クリックした点の 上下左右をチェックする 23 4. まずは上方向をチェック (どのような順番でも良い)

24.

塗りつぶし処理 4. まずは上方向をチェック (どのような順番でも良い) 24 5. チェックした点が黒の場合 その点を白で塗る

25.

塗りつぶし処理 5. チェックした点が黒の場合 その点を白で塗る 25 6. 塗った点を起点として 上下左右をチェック

26.

塗りつぶし処理 6. 塗った点を起点として 上下左右をチェック 26 7. チェックした点が白の場合 処理をスキップする

27.

クリック処理の修正 lblDrawMouseClicked (ラベル上でクリックした際に呼ばれるメソッド) private void lblDrawMouseClicked(java.awt.event.MouseEvent evt) { // マウスのX,Y座標を取得し、変数に格納 int mouseX = evt.getX(); int mouseY = evt.getY(); // クリックした点を起点として白で塗りつぶすメソッド fill(mouseX, mouseY); // BufferedImage をラベルに貼り付け lblDraw.setIcon(new ImageIcon(bufImageShow)); } 上下左右をチェックするメソッドを作って、 自身を繰り返し呼び出す(再帰呼出)ことで塗りつぶせそう

28.
[beta]
クリック処理の修正
塗りつぶし処理を行う fill() メソッド
void fill (int x, int y) {
// チェックする点が画像の外側だった場合、終了
if (x < 0 || x > imageWidth - 1 || y < 0 || y > imageHeight - 1) return;
// チェックした点が白だった場合、終了
if (bufImageShow.getRGB(x, y) == white) return;

// チェックした点が白でなかった場合、白で塗る
bufImageShow.setRGB(x, y, white);
// 上下左右もチェックする(再帰呼出し)
fill(x - 1, y);
fill(x + 1, y);

まずは自分の力で考えてみよう

fill(x, y - 1);

fill(x, y + 1);
}

29.

実行結果 29

30.

うまくいかない場合 プロジェクトを右クリックし、[プロパティ] ➡ [実行] ➡ [VMオプション] で「-Xss128m」(スタック領域128MB確保)などのコマンドを記載する 30 ヒープ領域は –Xms(初期) や –Xmx(最大)で設定できる

31.

宿題 以下の課題を Word 等で作成し、PDF形式で提出しなさい。 (ファイル名:学籍番号_氏名.pdf) 【課題】 描画や塗りつぶしを、白だけでなく黒でも行えるように 拡張しなさい。 【発展課題】 BufferedImage の配列を利用し、Undo (元に戻す)、 Redo (やり直す) 機能を追加しなさい。 ※適宜スクリーンショットや処理画像、ソースコードを掲載すること ちょいむずい? 31

32.

お疲れ様でした つづく