キー | 機能 | 特徴 |
---|---|---|
0 | 範囲選択中に戻る | 元画像と赤枠が表示され、ドラッグ移動できるようになる |
1 | 12選択範囲.jpgが表示される | 表示されるのは元画像にクリック時の赤枠を重ねたもの |
2 | 3最近傍補間.jpgが表示される | 表示されるのは赤枠部分を実行画面の形に変形させた画像 元の1ピクセルがそのまま拡大されたような粗いドットが見える |
3 | 3双一次補間.jpgが表示される | 表示されるのは赤枠部分を実行画面の形に変形させた画像 なめらかに拡大される |
PImage[] img = new PImage[5]; // 出力ファイル名 String[] fName = {"元", "選択範囲", "1描画機能", "2最近傍補間", "3双一次補間"};
PImage[] img = new PImage[4]; // 出力ファイル名 String[] fName = {"元", "12選択範囲", "3最近傍補間", "3双一次補間"};
float cx, cy; // 拡大の基準位置 float s = 5; // 拡大の倍率
PVector[] c = new PVector[4]; // 選択範囲の端点の座標 float a0, a1, a2, b0, b1, b2, c1, c2; // 射影変換の係数 int dragP = -1; // ドラッグ中の端点の番号(-1ならドラッグ中でない)
// 1~4番を元画像と同じサイズの黒画像にする for (int i=1; i<=4; i++) {
// 1~3番を元画像と同じ画像にする for (int i=1; i<=3; i++) {
strokeWeight(2*s); // 図形の枠の太さを実質2ptにする
strokeWeight(2); // 図形の枠の太さを2ptにする
c[0] = new PVector(width*0.2, height*0.2); // 左上 c[1] = new PVector(width*0.8, height*0.2); // 右上 c[2] = new PVector(width*0.8, height*0.8); // 右下 c[3] = new PVector(width*0.2, height*0.8); // 左下
cx = mouseX; // 拡大基準の横位置の更新 cy = mouseY; // 拡大基準の縦位置の更新
translate(cx, cy); // 原点をカーソル位置に移動 scale(1/s); // 拡大率の逆数のスケールをかける translate(-cx, -cy); // 枠内での中心位置移動 rect(0, 0, width, height); // 元画像サイズの長方形を描く
beginShape(); for (int i=0; i<4; i++) { vertex(c[i].x, c[i].y); ellipse(c[i].x, c[i].y, 20, 20); } endShape(CLOSE);
PVector pos = getScaledPosition(new PVector(cx-0.5, cy-0.5), new PVector(i, j), s);
PVector pos = getScaledPosition(new PVector(i, j));
// 実行画面からc[0]~c[3]で囲まれた四角形に変形させた場合のベクトルfの移動先のベクトルを返す(課題3で使用) PVector getScaledPosition(PVector f) { return new PVector(0, 0); }
drawToImage(s, 2); // 描画機能でs倍に拡大した画像をimg[2]に保存
nearestNeighbor(s, 3); // 最近傍補間でs倍に拡大した画像をimg[3]に保存 bilinear(s, 4); // 双一次補間でs倍に拡大した画像をimg[4]に保存
if (mouseButton == RIGHT) {
}
else if (!created){ for (int i=0; i<4; i++) { if (dist(c[i].x, c[i].y, mouseX, mouseY)<10) { dragP = i; } } }
// 端点のドラッグ void mouseDragged() { if (mouseButton == LEFT && dragP>=0) { c[dragP].x = mouseX; c[dragP].y = mouseY; } } // 端点のドラッグ終了 void mouseReleased() { if (mouseButton == LEFT) { dragP = -1; } }
img[n].updatePixels(); // n番目の画像を更新
void keyPressed() { int k = key-'0'; if (created) { // 0キーで画像作成前の状態に戻す if (k==0){ created = false; noFill(); dragP = -1; } // 1~3キーで作成された画像を表示する if (k>=1 && k<=3) { background(0); image(img[k], 0, 0, width, height); fill(255, 0, 0); text(fName[k], 30, height-30); fill(255); } } }
\(\begin{eqnarray} a_0&=&\frac{(x_1+x_3-x_0-x_2)(y_2-y_3)-(y_1+y_3-y_0-y_2)(x_2-x_3)} {w\left\{(x_2-x_1)(y_2-y_3)-(y_2-y_1)(x_2-x_3)\right\}}\cr b_0&=&\frac{(x_1+x_3-x_0-x_2)(y_2-y_1)-(y_1+y_3-y_0-y_2)(x_2-x_1)} {h\left\{(x_2-x_3)(y_2-y_1)-(y_2-y_3)(x_2-x_1)\right\}}\cr a_1&=&a_0x_1+\frac{x_1-x_0}{w}\cr b_1&=&b_0x_3+\frac{x_3-x_0}{h}\cr c_1&=&x_0\cr a_2&=&a_0y_1+\frac{y_1-y_0}{w}\cr b_2&=&b_0y_3+\frac{y_3-y_0}{h}\cr c_2&=&y_0\cr \end{eqnarray}\) |
// 端点の位置を元にして射影変換の係数を計算する void calcParameters() { // ピクセルの中央の位置を元にして計算するために端点の位置を修正 for (int i=0; i<4; i++) { c[i] = c[i].sub(new PVector(0.5, 0.5)); } a0 = (c[1].x + c[3].x - c[0].x - c[2].x) * (c[2].y - c[3].y); a0-= (c[1].y + c[3].y - c[0].y - c[2].y) * (c[2].x - c[3].x); a0/= w * ((c[2].x - c[1].x) * (c[2].y - c[3].y) - (c[2].y - c[1].y) * (c[2].x - c[3].x)); b0 = (c[1].x + c[3].x - c[0].x - c[2].x) * (c[2].y - c[1].y); b0-= (c[1].y + c[3].y - c[0].y - c[2].y) * (c[2].x - c[1].x); b0/= h * ((c[2].x - c[3].x) * (c[2].y - c[1].y) - (c[2].y - c[3].y) * (c[2].x - c[1].x)); a1 = a0 * c[1].x + (c[1].x - c[0].x)/w; b1 = b0 * c[3].x + (c[3].x - c[0].x)/h; c1 = c[0].x; a2 = a0 * c[1].y + (c[1].y - c[0].y)/w; b2 = b0 * c[3].y + (c[3].y - c[0].y)/h; c2 = c[0].y; // 端点の位置を元に戻す for (int i=0; i<4; i++) { c[i] = c[i].add(new PVector(0.5, 0.5)); } }
return new PVector(0, 0);
float x = (a1*f.x+b1*f.y+c1) / (a0*f.x+b0*f.y+1); float y = (a2*f.x+b2*f.y+c2) / (a0*f.x+b0*f.y+1); return new PVector(x, y);
// 最近傍補間(課題2) void nearestNeighbor(float s, int n) {
// 最近傍補間(課題3) void nearestNeighbor(int n) {
void bilinear(float s, int n) {
void bilinear(int n) {
img[n].updatePixels(); // n番目の画像を更新
if (mouseButton == RIGHT) {
calcParameters();
// nearestNeighbor(s, 3); // 最近傍補間でs倍に拡大した画像をimg[3]に保存 // bilinear(s, 4); // 双一次補間でs倍に拡大した画像をimg[4]に保存
nearestNeighbor(2); // 最近傍補間で変形した画像をimg[2]に保存 bilinear(3); // 双一次補間で変形した画像をimg[3]に保存