/// <summary> /// /// </summary> /// <param name="subdiv"></param> /// <param name="img"></param> private void PaintVoronoi(CvSubdiv2D subdiv, IplImage img) { CvSeqReader reader = new CvSeqReader(); int total = subdiv.Edges.Total; int elem_size = subdiv.Edges.ElemSize; subdiv.CalcVoronoi2D(); subdiv.Edges.StartRead(reader, false); for (int i = 0; i < total; i++) { CvQuadEdge2D edge = CvQuadEdge2D.FromSeqReader(reader); //CvQuadEdge2D edge = CvQuadEdge2D.FromPtr(reader.Ptr); if (Cv.IS_SET_ELEM(edge)) { CvSubdiv2DEdge e = edge.ToCvSubdiv2DEdge(); // left DrawSubdivFacet(img, e.RotateEdge(RotateEdgeFlag.Rotate)); // right DrawSubdivFacet(img, e.RotateEdge(RotateEdgeFlag.ReverseRotate)); } reader.NextSeqElem(elem_size); //Cv.NEXT_SEQ_ELEM(elem_size, reader); } }
/// <summary> /// /// </summary> /// <param name="fileName"></param> private static void SampleFileStorageReadSeq(string fileName) { // cvGetHashedKey, cvGetFileNode using (CvFileStorage fs = new CvFileStorage("sequence.yml", null, FileStorageMode.Read)) { CvStringHashNode xKey = fs.GetHashedKey("x", true); CvStringHashNode yKey = fs.GetHashedKey("y", true); CvFileNode points = fs.GetFileNodeByName(null, "points"); if ((points.Tag & NodeType.Seq) != 0) { CvSeq seq = points.DataSeq; int total = seq.Total; CvSeqReader reader = new CvSeqReader(); seq.StartRead(reader, false); for (int i = 0; i < total; i++) { CvFileNode pt = CvFileNode.FromPtr(reader.Ptr); int x = fs.ReadIntByName(pt, "x", 0); int y = fs.ReadIntByName(pt, "y", 0); Cv.NEXT_SEQ_ELEM(seq.ElemSize, reader); Console.WriteLine("{0}: ({1}, {2})", i, x, y); } } } Console.ReadKey(); }
/// <summary> /// /// </summary> /// <param name="img"></param> /// <param name="subdiv"></param> /// <param name="delaunay_color"></param> /// <param name="voronoi_color"></param> private void DrawSubdiv(IplImage img, CvSubdiv2D subdiv, CvColor delaunay_color, CvColor voronoi_color) { CvSeqReader reader = new CvSeqReader(); int total = subdiv.Edges.Total; int elem_size = subdiv.Edges.ElemSize; subdiv.Edges.StartRead(reader, false); for (int i = 0; i < total; i++) { //CvQuadEdge2D edge = (CvQuadEdge2D)reader.CvPtr; CvQuadEdge2D edge = CvQuadEdge2D.FromSeqReader(reader); if (Cv.IS_SET_ELEM(edge)) { DrawSubdivEdge(img, (CvSubdiv2DEdge)edge + 1, voronoi_color); DrawSubdivEdge(img, (CvSubdiv2DEdge)edge, delaunay_color); } //reader.NextSeqElem(elem_size); Cv.NEXT_SEQ_ELEM(elem_size, reader); } }
/// <summary> /// /// </summary> /// <param name="objectKeypoints"></param> /// <param name="objectDescriptors"></param> /// <param name="imageKeypoints"></param> /// <param name="imageDescriptors"></param> /// <returns></returns> private static int[] FindPairs(CvSeq<CvSURFPoint> objectKeypoints, CvSeq<float> objectDescriptors, CvSeq<CvSURFPoint> imageKeypoints, CvSeq<float> imageDescriptors) { CvSeqReader<float> reader = new CvSeqReader<float>(); CvSeqReader<CvSURFPoint> kreader = new CvSeqReader<CvSURFPoint>(); Cv.StartReadSeq(objectDescriptors, reader); Cv.StartReadSeq(objectKeypoints, kreader); List<int> ptpairs = new List<int>(); for (int i = 0; i < objectDescriptors.Total; i++) { CvSURFPoint kp = CvSURFPoint.FromPtr(kreader.Ptr); IntPtr descriptor = reader.Ptr; Cv.NEXT_SEQ_ELEM(kreader.Seq.ElemSize, kreader); Cv.NEXT_SEQ_ELEM(reader.Seq.ElemSize, reader); int nearestNeighbor = NaiveNearestNeighbor(descriptor, kp.Laplacian, imageKeypoints, imageDescriptors); if (nearestNeighbor >= 0) { ptpairs.Add(i); ptpairs.Add(nearestNeighbor); } } return ptpairs.ToArray(); }
/// <summary> /// /// </summary> /// <param name="vec">Cではconst float*</param> /// <param name="laplacian"></param> /// <param name="model_keypoints"></param> /// <param name="model_descriptors"></param> /// <returns></returns> private static int NaiveNearestNeighbor(IntPtr vec, int laplacian, CvSeq<CvSURFPoint> model_keypoints, CvSeq<float> model_descriptors) { int length = (int)(model_descriptors.ElemSize / sizeof(float)); int neighbor = -1; double dist1 = 1e6, dist2 = 1e6; CvSeqReader<float> reader = new CvSeqReader<float>(); CvSeqReader<CvSURFPoint> kreader = new CvSeqReader<CvSURFPoint>(); Cv.StartReadSeq(model_keypoints, kreader, false); Cv.StartReadSeq(model_descriptors, reader, false); IntPtr mvec; CvSURFPoint kp; double d; for (int i = 0; i < model_descriptors.Total; i++) { // const CvSURFPoint* kp = (const CvSURFPoint*)kreader.ptr; が結構曲者。 // OpenCvSharpの構造体はFromPtrでポインタからインスタンス生成できるようにしてるので、こう書ける。 kp = CvSURFPoint.FromPtr(kreader.Ptr); // まともにキャストする場合はこんな感じか // CvSURFPoint kp = (CvSURFPoint)Marshal.PtrToStructure(kreader.Ptr, typeof(CvSURFPoint)); mvec = reader.Ptr; Cv.NEXT_SEQ_ELEM(kreader.Seq.ElemSize, kreader); Cv.NEXT_SEQ_ELEM(reader.Seq.ElemSize, reader); if (laplacian != kp.Laplacian) { continue; } d = CompareSurfDescriptors(vec, mvec, dist2, length); if (d < dist1) { dist2 = dist1; dist1 = d; neighbor = i; } else if (d < dist2) dist2 = d; } if (dist1 < 0.6 * dist2) return neighbor; else return -1; }
/// <summary> /// CvSeqReaderからCvQuadEdge2Dのインスタンスを読み込んで返す /// </summary> /// <param name="reader"></param> /// <returns></returns> #else /// <summary> /// Reads a CvQuadEdge2D instance from CvSeqReader /// </summary> /// <param name="reader"></param> /// <returns></returns> #endif public static CvQuadEdge2D FromSeqReader(CvSeqReader reader) { if (reader == null) { throw new ArgumentNullException("reader"); } return new CvQuadEdge2D(reader.Ptr); }
/// <summary> /// マップのシーケンスのファイルストレージからの読み込み /// </summary> /// <param name="fileName">書きこむXML or YAMLファイル</param> private static void SampleFileStorageReadSeq(string fileName) { // cvGetHashedKey, cvGetFileNode // 二つのエントリを持つマップのシーケンスをファイルから読み込む // (1)ファイルストレージのオープン,ハッシュドキーの計算,シーケンスノードの取得 using (CvFileStorage fs = new CvFileStorage("sequence.yml", null, FileStorageMode.Read)) { CvStringHashNode xKey = fs.GetHashedKey("x", true); CvStringHashNode yKey = fs.GetHashedKey("y", true); CvFileNode points = fs.GetFileNodeByName(null, "points"); // (2)シーケンスリーダを初期化,各ノードを順次取得 if ((points.Tag & NodeType.Seq) != 0) { CvSeq seq = points.DataSeq; int total = seq.Total; CvSeqReader reader = new CvSeqReader(); seq.StartRead(reader, false); for (int i = 0; i < total; i++) { CvFileNode pt = CvFileNode.FromPtr(reader.Ptr); // (3)高速バージョン /* * CvFileNode xnode = fs.GetFileNode(pt, x_key, false); * CvFileNode ynode = fs.GetFileNode(pt, y_key, false); * Debug.Assert( * xnode != null && * (xnode.Tag & NodeType.Integer) != 0 && * ynode != null && * (ynode.Tag & NodeType.Integer) != 0 * ); * int x = xnode.DataI; * int i = ynode.DataI; * //*/ // (4)低速バージョン.x_keyとy_keyを使わない /* * CvFileNode xnode = fs.GetFileNodeByName(pt, "x"); * CvFileNode ynode = fs.GetFileNodeByName(pt, "i"); * Debug.Assert( * xnode != null && * (xnode.Tag & NodeType.Integer) != 0 && * ynode != null && * (ynode.Tag & NodeType.Integer) != 0 * ); * int x = xnode.DataI; * int i = ynode.DataI; * //*/ // (5)さらに低速だが,使いやすいバージョン ///* int x = fs.ReadIntByName(pt, "x", 0); int y = fs.ReadIntByName(pt, "y", 0); //*/ // (6)データを表示し,次のシーケンスノードを取得 Cv.NEXT_SEQ_ELEM(seq.ElemSize, reader); Console.WriteLine("{0}: ({1}, {2})", i, x, y); } } } Console.ReadKey(); }
/// <summary> /// マップのシーケンスのファイルストレージからの読み込み /// </summary> /// <param name="fileName">書きこむXML or YAMLファイル</param> private static void SampleFileStorageReadSeq(string fileName) { // cvGetHashedKey, cvGetFileNode // 二つのエントリを持つマップのシーケンスをファイルから読み込む // (1)ファイルストレージのオープン,ハッシュドキーの計算,シーケンスノードの取得 using (CvFileStorage fs = new CvFileStorage("sequence.yml", null, FileStorageMode.Read)) { CvStringHashNode xKey = fs.GetHashedKey("x", true); CvStringHashNode yKey = fs.GetHashedKey("y", true); CvFileNode points = fs.GetFileNodeByName(null, "points"); // (2)シーケンスリーダを初期化,各ノードを順次取得 if ((points.Tag & NodeType.Seq) != 0) { CvSeq seq = points.DataSeq; int total = seq.Total; CvSeqReader reader = new CvSeqReader(); seq.StartRead(reader, false); for (int i = 0; i < total; i++) { CvFileNode pt = CvFileNode.FromPtr(reader.Ptr); // (3)高速バージョン /* CvFileNode xnode = fs.GetFileNode(pt, x_key, false); CvFileNode ynode = fs.GetFileNode(pt, y_key, false); Debug.Assert( xnode != null && (xnode.Tag & NodeType.Integer) != 0 && ynode != null && (ynode.Tag & NodeType.Integer) != 0 ); int x = xnode.DataI; int i = ynode.DataI; //*/ // (4)低速バージョン.x_keyとy_keyを使わない /* CvFileNode xnode = fs.GetFileNodeByName(pt, "x"); CvFileNode ynode = fs.GetFileNodeByName(pt, "i"); Debug.Assert( xnode != null && (xnode.Tag & NodeType.Integer) != 0 && ynode != null && (ynode.Tag & NodeType.Integer) != 0 ); int x = xnode.DataI; int i = ynode.DataI; //*/ // (5)さらに低速だが,使いやすいバージョン ///* int x = fs.ReadIntByName(pt, "x", 0); int y = fs.ReadIntByName(pt, "y", 0); //*/ // (6)データを表示し,次のシーケンスノードを取得 Cv.NEXT_SEQ_ELEM(seq.ElemSize, reader); Console.WriteLine("{0}: ({1}, {2})", i, x, y); } } } Console.ReadKey(); }
/// <summary> /// 単純な最近傍 /// </summary> /// <param name="vec">Cではconst float*</param> /// <param name="laplacian"></param> /// <param name="model_keypoints"></param> /// <param name="model_descriptors"></param> /// <returns></returns> private static int NaiveNearestNeighbor( IntPtr vec, int laplacian, CvSeq<CvSURFPoint> model_keypoints, CvSeq<IntPtr> model_descriptors) { int length = (int)(model_descriptors.ElemSize / sizeof(float)); int neighbor = -1; double dist1 = 1e6; double dist2 = 1e6; using(CvSeqReader<float> reader = new CvSeqReader<float>()) using (CvSeqReader<CvSURFPoint> kreader = new CvSeqReader<CvSURFPoint>()) { Cv.StartReadSeq(model_keypoints, kreader, false); Cv.StartReadSeq(model_descriptors, reader, false); IntPtr mvec; CvSURFPoint kp; double d; for (int i = 0; i < model_descriptors.Total; i++) { // const CvSURFPoint* kp = (const CvSURFPoint*)kreader.ptr; が結構曲者。 // OpenCvSharpの構造体はFromPtrでポインタからインスタンス生成できるようにしてるので、こう書ける。 kp = CvSURFPoint.FromPtr(kreader.Ptr); mvec = reader.Ptr; Cv.NEXT_SEQ_ELEM(kreader.Seq.ElemSize, kreader); Cv.NEXT_SEQ_ELEM(reader.Seq.ElemSize, reader); if (laplacian != kp.Laplacian) { continue; } // SURF特徴点の比較を行う d = CompareSURFDescriptors(vec, mvec, dist2, length); if (d < dist1) { dist2 = dist1; dist1 = d; neighbor = i; } else if (d < dist2) { dist2 = d; } } } return (dist1 < dist2 * 0.6) ? neighbor : -1; }
/// <summary> /// 特徴点のペアを見つけて配列として返す /// </summary> /// <param name="objectKeypoints"></param> /// <param name="objectDescriptors"></param> /// <param name="imageKeypoints"></param> /// <param name="imageDescriptors"></param> /// <returns></returns> private static int[] FindPairs( CvSeq<CvSURFPoint> objectKeypoints, CvSeq<IntPtr> objectDescriptors, CvSeq<CvSURFPoint> imageKeypoints, CvSeq<IntPtr> imageDescriptors) { List<int> ptPairs = new List<int>(); using(CvSeqReader<float> descReader = new CvSeqReader<float>()) using (CvSeqReader<CvSURFPoint> keyReader = new CvSeqReader<CvSURFPoint>()) { Cv.StartReadSeq(objectDescriptors, descReader); Cv.StartReadSeq(objectKeypoints, keyReader); for (int i = 0; i < objectDescriptors.Total; i++) { CvSURFPoint keypoint = CvSURFPoint.FromPtr(keyReader.Ptr); IntPtr descriptor = descReader.Ptr; Cv.NEXT_SEQ_ELEM(keyReader.Seq.ElemSize, keyReader); Cv.NEXT_SEQ_ELEM(descReader.Seq.ElemSize, descReader); // 単純な最近傍によって類似度の高い要素を探す int nearestNeighbor = NaiveNearestNeighbor(descriptor, keypoint.Laplacian, imageKeypoints, imageDescriptors); if (nearestNeighbor >= 0) { ptPairs.Add(i); ptPairs.Add(nearestNeighbor); } } } return ptPairs.ToArray(); }