画像処理に関する質問なのですが、
現在2Dの入力実画像を座標変換(視点変換,射影変換)するソフトを作成しようと思うの
ですが、
どのようにすればよいでしょうか?
具体的には、正面から撮影した2D実映像を、視点変換して
下方向から撮影した2D実画像に変換したいのです。( TopView変換と逆のイメージ )
理論的に説明されている文献などは多くありますが、
コードレベルで説明していただけないでしょうか?
または、そのようなHPありましたら教えて頂けないでしょうか?
開発環境VC++6.0
以上宜しくお願い致します。
ちょっとちがうかもしれませんが・・どうでしょ?
#include <windows.h>
LRESULT On_Destroy ( ) ;
LRESULT On_Paint ( HWND ) ;
LRESULT CALLBACK WindowProc ( HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam )
{
switch ( Msg )
{
case WM_DESTROY : return On_Destroy ( ) ;
case WM_PAINT : return On_Paint ( hwnd ) ;
}
return DefWindowProc ( hwnd, Msg, wParam, lParam ) ;
}
LRESULT On_Paint ( HWND hWnd )
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
XFORM xForm ;
hdc = BeginPaint ( hWnd, &ps ) ;
/* ワールド変換可能モードにする */
SetGraphicsMode ( hdc, GM_ADVANCED ) ;
/* 論理単位を、0.01 インチへ変換 */
SetMapMode ( hdc, MM_LOENGLISH ) ;
/* 変換内容を設定 */
xForm.eM11 = ( FLOAT ) 0.5 ; // X方向を1/2にする(cos)
xForm.eM12 = ( FLOAT ) 0.25 ; // Y軸の角度を変える(sin)
xForm.eM21 = ( FLOAT ) 0.1 ; // X軸の角度を変える(sin)
xForm.eM22 = ( FLOAT ) -1.0 ; // 上下逆さま(cos)
xForm.eDx = ( FLOAT ) -250.0 ; // 左に2.5インチ移動
xForm.eDy = ( FLOAT ) 300.0 ; // 上に3インチ移動
/* 変換する */
SetWorldTransform ( hdc, &xForm ) ;
/* クライアント領域のサイズを取得 */
GetClientRect ( hWnd, &rect ) ;
/* 論理座標に変換 */
DPtoLP ( hdc, ( LPPOINT ) &rect, 2 ) ;
SelectObject ( hdc, GetStockObject ( HOLLOW_BRUSH ) ) ;
Ellipse ( hdc, ( rect.right / 2 - 100 ), ( rect.bottom / 2 + 100 ),
( rect.right / 2 + 100 ), ( rect.bottom / 2 - 100 ) ) ;
POINT pt[] = { rect.right / 2 - 150, rect.bottom / 2,
rect.right / 2 + 150, rect.bottom / 2,
rect.right / 2, rect.bottom / 2 + 150,
rect.right / 2, rect.bottom / 2 - 150 } ;
Polyline ( hdc, pt, ARRAYSIZE ( pt ) ) ;
EndPaint ( hWnd, &ps ) ;
return 0 ;
}
LRESULT On_Destroy ( )
{
PostQuitMessage ( 0 ) ;
return 0 ;
}
int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE, LPSTR, int CmdShow )
{
LPCTSTR ClassName = TEXT ( ClassName ) ;
LPCTSTR TitleName = TEXT ( WindowName ) ;
WNDCLASSEX wc ;
wc.cbSize = sizeof ( wc ) ;
wc.style = CS_HREDRAW | CS_VREDRAW ;
wc.lpfnWndProc = WindowProc ;
wc.cbClsExtra = 0 ;
wc.cbWndExtra = 0 ;
wc.hInstance = hInstance ;
wc.hIcon = ( HICON ) LoadImage ( NULL, MAKEINTRESOURCE (
IDI_APPLICATION ),
IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED ) ;
wc.hCursor = ( HCURSOR ) LoadImage ( NULL, MAKEINTRESOURCE ( IDC_ARROW ),
IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED ) ;
wc.hbrBackground = ( HBRUSH ) GetStockObject ( WHITE_BRUSH ) ;
wc.lpszClassName = ClassName ;
wc.lpszMenuName = NULL ;
wc.hIconSm = NULL ;
if ( ! RegisterClassEx ( & wc ) )
{
return -1 ;
}
HWND hwnd = CreateWindowEx (
NULL, ClassName, TitleName, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL ) ;
if ( ! hwnd )
{
return -1 ;
}
ShowWindow ( hwnd, CmdShow ) ;
UpdateWindow ( hwnd ) ;
MSG msg ;
while ( ( GetMessage ( &msg, NULL, 0, 0 ) ) > 0 )
{
TranslateMessage ( &msg ) ;
DispatchMessage ( &msg ) ;
}
return PtrToInt ( msg.wParam ) ;
}
早速の回答ありがとうございます。
これは見る所、アファイン変換と言われるものではないでしょうか?
画像自体を回転したり、移動表示させたりする変換技術。(間違っていたらスミマセン)
当方が知りたいのは、視点を変換する技術なのです。
よく、正面から撮った映像を上から視線に変換する技術が紹介されてますが
あれのコードレベルでの処理方法が知りたいのです。
ご存知でしょか?
xForm のパラメータを動的に変化すればなんとかなるかと
思いましたが・・・的はずれのようでしたね。すみません。
> よく、正面から撮った映像を上から視線に変換する技術が紹介されてますが
そのURL等をここに書けば、どんな技術か伝わりやすいのではないかと。
きっと私には分からないので、どっちかというと興味本位で聞いているのですが。
以下にネット上に置かれている大学生のレポートを示させて貰います。
http://www.ktlab.ei.tuat.ac.jp/pdf/0602ITE_tujimr.pdf
このレポートの項目7で射影変換について述べられているのですが、
当方数学が得意でないものですから、この公式でどう画像処理を実現するのかが
解りません。。。
どなたか、実際にプログラムレベルで組まれた方おられますか?
# 論文一読したものの的外れでしょうが。
台形変換(Trapezoid ?)とは違うのカナぁ。「Trapezoid Graphics」あたりで
ググるとC#で作った方がいらっしゃるようです。
# 問題なのは、論文にもあるように4点(以上)の指定ですが、どのように
# 決定するのでしょうね (手動で、って書いてあるんですが・・・)。
> 現在2Dの入力実画像を座標変換(視点変換,射影変換)するソフト
とのことですが,質問者様が示した文献にもあるように,
まともにやるならば,その入力画像を撮影したカメラの内部パラメタが必要になります.
もしカメラキャリブレーションによってカメラの内部パラメタが得られているならば,
入力画像上のある点が「カメラに対してどの方向にあったか」がわかることになるので,
トップビューぼくするようなカメラ向きだけの変換はそれほど難しくありません.
入力画像上の点
↓カメラパラメタを使って変換
カメラに対する入射角度
↓好きな方向を向いた仮想カメラの像面に対してその角度を投影
結果画像上の点
単一の入力画像からは上記のように角度はわかりますが,カメラからの距離はわからない
ため
視点位置まで変えるのは難しいです.
質問者様の目的がそういうものではなくて,
キャリブレーション等をしないなんとなくな処理を行うだけならば,
例えば「単に入力画像を適当なポリゴンに貼り付けてそれをある位置から見る」ような
処理を行うことになると思います.
皆様ご指導ありがとうございました。
とりあえず、なんちゃって射影変換で(カメラキャリブレーションなし)
公式をそのままコード化し、行列をかければ実現しました。
厳密にいうとホウジョウウサギ氏が言われるように、カメラキャリブレーションを
するのが筋なのでしょうが。。。。
ありがとうございました。