【数値情報処理b】第4回の答え

課題

boats の画像を「右上角を中心に-20度回転したあと垂直反転」して表示するプログラムを作成しなさい。

for で一つ一つの画素を処理し、imshift() , imrotate() , mirror() を使わないこと。

「」の部分は人によって違う。


解答例

右上角を中心に回転には、「任意の座標中心の回転」を使う。 逆変換の計算式は以下の通り。

\begin{eqnarray} x_{0}&=&\left\{x_{1}-c_{x}(1-\cos\theta)-c_{y}\sin\theta\right\}\cos\theta+\left\{y_{1}+c_{x}\sin\theta-c_{y}(1-\cos\theta)\right\}\sin\theta\\ y_{0}&=&-\left\{x_{1}-c_{x}(1-\cos\theta)-c_{y}\sin\theta\right\}\sin\theta+\left\{y_{1}+c_{x}\sin\theta-c_{y}(1-\cos\theta)\right\}\cos\theta \end{eqnarray}

もしくは以下でも良い。

\begin{eqnarray} x_{0}&=&\left(x_{1}-c_{x}\right)\cos\theta+\left(y_{1}-c_{y}\right)\sin\theta+c_{x}\\ y_{0}&=&-\left(x_{1}-c_{x}\right)\sin\theta+\left(y_{1}-c_{y}\right)\cos\theta+c_{y} \end{eqnarray}

さらに、右上角を中心に回転のあとに垂直反転を行う必要がある。

report4.R
  1. # レポート
  2. # 右上角を中心に-20度回転したあと垂直反転
  3.  
  4. library(imager)
  5.  
  6. # 度からラジアンに変換する関数
  7. rad <- function(deg) {
  8. return(deg * pi / 180)
  9. }
  10.  
  11. im <- grayscale(boats)
  12.  
  13. dim0 <- dim(im)
  14.  
  15. # cimg変数で処理すると遅いので配列で処理する
  16. g0 <- array(im, dim0)
  17. g1 <- array(0, dim0)
  18. g2 <- array(0, dim0)
  19.  
  20. # 回転角(度)
  21. theta <- -20
  22.  
  23. # 回転の中心座標
  24. cx <- dim0[1]
  25. cy <- 0
  26.  
  27. # 任意の座標中心の回転
  28. ct <- cos(rad(theta))
  29. st <- sin(rad(theta))
  30. for (x1 in 1 : dim0[1]) {
  31. for (y1 in 1 : dim0[2]) {
  32. x2 <- x1 - cx * (1 - ct) - cy * st
  33. y2 <- y1 + cx * st - cy * (1 - ct)
  34. x0 <- round( x2 * ct + y2 * st)
  35. # もしくは x0 <- round( (x1 - cx) * ct + (y1 - cy) * st + cx)
  36. y0 <- round(-x2 * st + y2 * ct)
  37. # もしくは y0 <- round(-(x1 - cx) * st + (y1 - cy) * ct + cy)
  38. if (x0 < 1 || x0 > dim0[1] || y0 < 1 || y0 > dim0[2]) next
  39. g1[x1, y1, ,] <- g0[x0, y0, ,]
  40. }
  41. }
  42.  
  43. # 移動量
  44. bx <- 0
  45. by <- -dim0[2]
  46.  
  47. # 垂直反転と平行移動
  48. for (x1 in 1 : dim0[1]) {
  49. x0 <- x1 - bx
  50. if (x0 < 1 || x0 > dim0[1]) next
  51. for (y1 in 1 : dim0[2]) {
  52. y0 <- -y1 - by # 垂直反転と平行移動
  53. if (y0 < 1 || y0 > dim0[2]) next
  54. g2[x1, y1, ,] <- g1[x0, y0, ,]
  55. }
  56. }
  57.  
  58. # 配列→cimg変数
  59. im.rotate <- as.cimg(g2)
  60.  
  61. # 同時に2枚並べるレイアウト
  62. layout(t(1 : 2))
  63.  
  64. plot(im, interpolate = FALSE, main = "元の画像")
  65. plot(im.rotate, interpolate = FALSE, main = "回転後の画像")
  66.  
  67. # レイアウトを元に戻す

回転中心を変えるには 24,25 行目を以下のように変更する。

cx <- dim0[1]
cy <- dim0[2]
cx <- 0
cy <- dim0[2]

垂直反転の後に回転の場合は、39行目と54行目を入れ替えたあとに 20-41 行目と 43-56 行目を入れ替える。