最新閲覧日:

魚眼レンズで撮影した画像って、ひずんでますよね。
これを普通に(って何が普通かと言う問題はあるけれど)直す
処理プログラムをおしえていただけませんか?

できれば、教科書的なものでなく、サンプルプログラムがあれば
うれしいんですが・・・
言語は、C以上の高級言語ならたいていわかるので
せめてポインタだけでも・・

お願いします。

A 回答 (3件)

射影変換(とその一部であるアフィン変換)は直線が直線になる変


換ですから、魚眼レンズの変換や逆変換には使えませんよ。ごく一
部なら近似できるかもしれませんが。

で、まずは教科書的に。

広角を含む普通のレンズは、視野の一部を視点からDだけ離れた平
面に投影します。これに対して魚眼レンズは、まず視点を中心とし
た半径rの球面に視野全体を投影して、次にその投影した結果を平
面に垂直に投影しなおすものです。

# ただし、本物のレンズが完全にこの数学モデルどおりに働いてい
# るかどうかは、レンズの設計にもよると思うのでわかりません。

さて、この原理がわかれば、魚眼レンズと普通のレンズの間の変換
をするための式を立てることができます。

普通のレンズの画像で中心からLだけ離れた点と、魚眼レンズの画
像の中心からlだけ離れた点が対応しているとします。そうすると、
l/r = L/sqrt(D^2+L^2)
になります。つまり、
l = rL/sqrt(D^2+L^2)
ですね。同じように、普通の画像上の点P(X,Y)と魚眼の画像
上の点p(x,y)を対応させると、
x = rX/sqrt(D^2+X^2+Y^2)
y = rY/sqrt(D^2+X^2+Y^2)
となります。これは、普通→魚眼の座標変換式ですが、画像の逆変
換には逆変換の式を作るのではなく、この式をそのまま使います。
なぜなら、逆変換後の座標(X,Y)の画素の値は、逆変換前の座標
(x,y)の画素の値になるわけですから、プログラム上は(X,Y)をぐる
ぐる回して、(x,y)を求めて、その位置の値を(X,Y)の値とすればい
いからです。

プログラムを書くなら、
for (X=0;X<W;X++) {
 for (Y=0;Y<H;Y++) {
  x = r*(X-W/2)/sqrt(D*D+(X-W/2)*(X-W/2)+(Y-H/2)*(Y-H/2)) + w/2;
  y = r*(Y-H/2)/sqrt(D*D+(X-W/2)*(X-W/2)+(Y-H/2)*(Y-H/2)) + h/2;
  if (x >= 0 && x < w && y >= 0 && y < h) {
   futsuu[X][Y] = gyogan[x][y];
  } else {
   futsuu[X][Y] = black; /* or white or any */
  }
 }
}
て感じでしょうか。W,H, w,h は、それぞれの画像の幅と高さです。
ただし、x, y が画像の範囲をはみ出していないかチェックする必
要があります。

また、画質をよくするためには適当な補間法を適用します。補間法
については、
http://oshiete1.goo.ne.jp/kotaeru.php3?q=15511
で答えているので参考にしてください。

rには魚眼の画像の半径を設定します。
D/rが中心付近の倍率になります。


参考URL:http://oshiete1.goo.ne.jp/kotaeru.php3?q=15511
    • good
    • 1
この回答へのお礼

punchan_jpさん、ご回答ありがとうございます。
レンズのしくみから、プログラムまで、さらに画質向上の補完法まで
至れり尽くせりとはこういうことですね。
お礼に「名誉と栄光」を進呈します。いや、失敬。
 もうじき実際の画像が手に入るので、それまでに教えていただいた
プログラムをモデファイしようと思います。

あわてて締め切ってしまい「しまった~」(トヨエツ金田一風)
と思ってます。

自分の疑問が、こっちのほう「教育 > 理系の学問 > その他(理系の学問)」
だということもためになりました。
改めて、ありがとうございました。
機会があれば、結果をお知らせしたいと思います。

お礼日時:2001/03/05 16:19

魚眼(というか広角)レンズで撮った絵の中心に近いゆがみの少ない部分が


広角では無いレンズで撮った絵そのものになります。
という事で、中心のゆがみが目立たない部分だけを切り出してください。

って、これじゃ意味が無いですよね。。。(^^;

まず、ゆがみとは、平行な線が平行に写っていない事だとします。
例えば、絵の中心から八方向に平行線が出ている状態を写したとすると
それをすべて平行に変換するのは無理ですよね、。
という事で写っている範囲のすべてを変換する事はできません。

では、上下1/3くらいづつを切り取ってやるとどうでしょう?
これならば端のほうを上下に伸ばしてあげれば、それなりに見れる絵に
近似できると思います。
(上下端に近い部分は、少し横にも伸ばすほうがより良くなりますね)
アルゴリズムはCが判るという事ですので、がんばってください!
たぶん二次曲線を基準に変換すれば良いと思うのですが。

ところで、質問ではサンプルプログラムがあると嬉しいという事ですが、
そもそも画像フォーマットは何でしょうか?
質問の書き方のレベルと求める回答のレベルが違っているのではないでしょうか?

画像がbmpでしたら、上記の方法でだけですむでしょうが、
jpgなど圧縮のかかっている形式でしたらjpg→bmp変換が先になります。
jpg→bmp変換については、残念ながら私はわかりません。。(^^;
この質問のままで置いておいても答えはつかないと思うので、
フォーマット変換については検索をかけて調べるか、
新しい質問として書き込んだほうが良いですよ。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
ちょいと特殊な内容なので、回答つかないかなとあきらめかけてました。
カメラ解像度は、512×512で、メモリ上に展開されます。
(っていまごろ書いても遅いんですが・・)
メモリ上なので、たとえば輝度値は、p[y][x] という感じで配列でアクセス可能です。したがって、ファイル形式変換は、考えなくていいです。
(それを先に言わんかっ!)ってすいませんでした。
で、「上下1/3切り取る」ということは、解像度が1/9!!
それわ、つらいんですけど~、でもそれしかないとなれば、やってみます。
ありがとうございました~

お礼日時:2001/03/02 11:14

代数幾何の射影変換で多分出来ると思います


通常画像を射影変換して魚眼レンズで見たような画像に出来るので魚眼レンズの射影行列の逆行列で変換してやれば元の画像に戻るはずです

元画像をN、射影行列をA、その逆行列をA^-1とした時、
NAが魚眼レンズ画像となるので、それにA^-1をかけると
NAA^-1 = N(AA^-1)
= N1
= N
で、元画像に戻ります

サンプルプログラムは「アフィン変換」や、「射影変換」などで検索すれば出てくると思います
または3D Gameのライブラリを見ればまず載っているはずです

参考URL:http://www.microsoft.com/japan/developer/library …
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
うっ。た、確かに・・
レンズを通した画像は、すべて行列変換ですよね。
(基本でした)
ってことは、魚眼レンズの変換用行列(パラメータ)を
実測(か、計算)して、フィルタを作らなくちゃいけないんですね。

ん~、見えてきたような気がします。

また、3DGameの方面は、よく知らなかったので、
調べてみることにします。
URLは、NotFoundでしたけど、
たぶんDirectX6(?)のような気がするので
DirectX8とOpenGL関係も見てみます。

ありがとうございました~

お礼日時:2001/03/02 11:26

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報