/// <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); } }