前提・実現したいこと
C# + OpenCv 2.4.6 + OpenCvSharpを利用して「チェスパターンを読み込み、歪みのないチェスパターン画像に変換」しようとしています。
0. チェスパターン画像を読み込み、交点の座標を取り出す
0. 撮像された交点の位置から、それぞれの交点に対応する理想的な表示位置を算出
0. Remap()で元のチェスパターン画像から歪みのないチェスパターン画像を生成。
発生している問題・エラーメッセージ
Remap()の第3、4引数 (map1, map2) をどう生成すれば良いか判らず困っています。
コードというより、引数の意味とOpenCvに生成のための関数が用意されているか教えて頂ければ幸いです。
※当該引数について、ドキュメントでは
map1 – 型 CV_16SC2 , CV_32FC1 あるいは CV_32FC2 である座標点 (x,y) ,または単なる値 x の1番目のマップ.高速化のために浮動小数点表現から固定小数点表現に変換する方法については, convertMaps() を参照してください
map2 – 型 CV_16UC1 , CV_32FC1 あるいは none(map1 が (x,y) である場合は空のマップ) である値 y の2番目のマップ
と記述されているのですが、理解できません。
該当のソースコード
C#でのソースコード該当部分です。
C#
1 2/// <summary>ファイルから読み出したチェスパターンの点群とその理想的な位置から画像の歪みを変換する</summary> 3/// <param name="fn">チェスパターン画像ファイルパス</param> 4/// <returns>成否</returns> 5private bool AnalyzeCheckImages2( string fn ) 6{ 7 try 8 { 9 var confCol = _config.PtnCol; // チェスパターン交点数(列) 10 var confRow = _config.PtnRow; // チェスパターン交点数(行) 11 var cornerCount = confCol * confRow; // チェスパターン交点総数 12 var corners = new CvPoint2D32f[cornerCount]; 13 var pattern_size = Cv.Size(confCol, confRow); 14 15 16 // チェスパターンを読み込み 17 using (var ipl = new IplImage(fn)) 18 using (var src_gray = Cv.CreateImage(Cv.GetSize(ipl), BitDepth.U8, 1)) 19 { 20 int cCount; 21 // 読み込んだ(ゆがんだ)チェスパターン画像の交点座標群を取得する 22 var found = Cv.FindChessboardCorners(ipl, pattern_size, out corners, out cCount); 23 24 // 画像上の交点座標群(corners)から、対応する理想的な座標群を生成する。 25 var targetPoss = CreateTargetPoss(corners, confCol, confRow ); 26 27 // Remap()でゆがんだ元画像を、綺麗な形にする 28 using (var dst_ipl = new IplImage(ipl.Size, ipl.Depth, ipl.NChannels)) 29 { 30 // ! Map1, Map2はどう生成すれば良い??(多分、corners, targetPosから生成できる?) 31 32 Cv.Remap( ipl, dst_ipl, Map1, Map2 ) ; 33 34 // この時点でdst_iplには綺麗なチェスパターンが欲しい。 35 } 36 } 37 } 38 catch (Exception ex) 39 { 40 MessageBox.Show(String.Format("例外が発生 Message={0}, Stack={1}", ex.Message, ex.StackTrace)); 41 return false; 42 } 43 return false; 44} 45 46 47/// <summary>理想的な表示位置(群)を生成します</summary> 48/// <param name="cPos">コーナー位置群</param> 49/// <param name="MaxCol">コーナーカラム数</param> 50/// <param name="MaxRow">コーナー列数</param> 51/// <returns>理想的なマッピング</returns> 52private CvPoint2D32f[] CreateTargetPoss(CvPoint2D32f[] cPos, int MaxCol, int MaxRow ) 53{ 54 try 55 { 56 // 中央の位置と(その右側の点から割り出した)間隔をもとに、理想的な表示位置の点群を生成する 57 var centerCol = MaxCol / 2; 58 var centerRow = MaxRow / 2; 59 var center = cPos[centerCol + centerRow * MaxCol]; 60 var right = cPos[centerCol + centerRow * MaxCol + 1]; // 中央の右隣 61 var len = Math.Sqrt((center.X - right.X) * (center.X - right.X) + (center.Y - right.Y) * (center.Y - right.Y)); 62 var list = Enumerable.Range(0, MaxRow).SelectMany(yy => Enumerable.Range(0, MaxCol).Select(xx => new { XX = xx, YY = yy }).Select(p => new CvPoint2D32f(center.X + (p.XX - centerCol) * len, center.Y + (p.YY - centerRow) * len))); // 理想位置 63 return list.ToArray(); 64 } 65 catch (Exception ex) 66 { 67 MessageBox.Show(String.Format("例外が発生 Message={0}, Stack={1}", ex.Message, ex.StackTrace)); 68 return null; 69 } 70} 71 72 73### 補足 74 75map1とmap2の意味については判りました。 76歪み補正マップと呼ばれ、入力画像の任意のピクセルがどの位置に移動すれば良いかを示しており、map1(x座標用)、map2(y座標用)と分かれているようです。 77問題は、これが画像サイズ分・各ピクセル毎の情報ということです。 78交点の移動前・後の座標が判っているので、全ピクセル分補間すれば、全ピクセルが計算できるとは思うのですが、これを算出するような関数を見つけることができません。 79 80なお、calibrateCamera() + undistort()による補正は キャリブレーション画像が1枚ではできないと聞いているので、アプローチからは外して考えています。
回答3件
あなたの回答
tips
プレビュー