Esempio n. 1
0
        // Draw matches between two images
        public static Mat getMatchesImage(Mat query, Mat pattern, MatOfKeyPoint queryKp, MatOfKeyPoint trainKp, MatOfDMatch matches, int maxMatchesDrawn)
        {
            Mat outImg = new Mat();

            List <DMatch> matchesList = matches.toList();

            if (matchesList.Count > maxMatchesDrawn)
            {
                matchesList.RemoveRange(maxMatchesDrawn, matchesList.Count - maxMatchesDrawn);
            }

            MatOfDMatch tmpMatches = new MatOfDMatch();

            tmpMatches.fromList(matchesList);

            Features2d.drawMatches
            (
                query,
                queryKp,
                pattern,
                trainKp,
                tmpMatches,
                outImg,
                new Scalar(0, 200, 0, 255),
                Scalar.all(-1),
                new MatOfByte()
            );

            return(outImg);
        }
Esempio n. 2
0
        /// <summary>
        /// Crosses the matcher.
        /// </summary>
        /// <returns>The matcher.</returns>
        /// <param name="queryDescriptors">Query descriptors.</param>
        /// <param name="trainDescriptors">Train descriptors.</param>
        public static IList <DMatch> CrossMatcher(MatOfFloat queryDescriptors, MatOfFloat trainDescriptors)
        {
            MatOfDMatch   matchQT = new MatOfDMatch(), matchTQ = new MatOfDMatch();
            List <DMatch> bmatch = new List <DMatch>();

            DMatch[] dmatch;
            if (trainDescriptors.cols() <= 0)
            {
                throw new ApplicationException("CrossMatcherの引数trainDescriptorsがありません。");
            }
            matcher.match(queryDescriptors, trainDescriptors, matchQT);
            if (queryDescriptors.cols() <= 0)
            {
                throw new ApplicationException("CrossMatcherの引数queryDescriptorsがありません。");
            }
            matcher.match(trainDescriptors, queryDescriptors, matchTQ);
            for (int i = 0; i < matchQT.rows(); i++)
            {
                DMatch forward  = matchQT.toList()[i];
                DMatch backward = matchTQ.toList()[forward.trainIdx];
                if (backward.trainIdx == forward.queryIdx)
                {
                    bmatch.Add(forward);
                }
            }
            dmatch = bmatch.ToArray();
            bmatch.Clear();
            return(dmatch);
        }
Esempio n. 3
0
        /// <summary>
        /// Refines the matches with homography.
        /// </summary>
        /// <returns><c>true</c>, if matches with homography was refined, <c>false</c> otherwise.</returns>
        /// <param name="queryKeypoints">Query keypoints.</param>
        /// <param name="trainKeypoints">Train keypoints.</param>
        /// <param name="reprojectionThreshold">Reprojection threshold.</param>
        /// <param name="matches">Matches.</param>
        /// <param name="homography">Homography.</param>
        static bool refineMatchesWithHomography
        (
            MatOfKeyPoint queryKeypoints,
            MatOfKeyPoint trainKeypoints,
            float reprojectionThreshold,
            MatOfDMatch matches,
            Mat homography
        )
        {
            //Debug.Log ("matches " + matches.ToString ());

            int minNumberMatchesAllowed = 8;

            List <KeyPoint> queryKeypointsList = queryKeypoints.toList();
            List <KeyPoint> trainKeypointsList = trainKeypoints.toList();
            List <DMatch>   matchesList        = matches.toList();

            if (matchesList.Count < minNumberMatchesAllowed)
            {
                return(false);
            }

            // Prepare data for cv::findHomography
            List <Point> srcPointsList = new List <Point>(matchesList.Count);
            List <Point> dstPointsList = new List <Point>(matchesList.Count);

            for (int i = 0; i < matchesList.Count; i++)
            {
                srcPointsList.Add(trainKeypointsList[matchesList[i].trainIdx].pt);
                dstPointsList.Add(queryKeypointsList[matchesList[i].queryIdx].pt);
            }

            // Find homography matrix and get inliers mask
            using (MatOfPoint2f srcPoints = new MatOfPoint2f())
                using (MatOfPoint2f dstPoints = new MatOfPoint2f())
                    using (MatOfByte inliersMask = new MatOfByte(new byte[srcPointsList.Count]))
                    {
                        srcPoints.fromList(srcPointsList);
                        dstPoints.fromList(dstPointsList);

                        //Debug.Log ("srcPoints " + srcPoints.ToString ());
                        //Debug.Log ("dstPoints " + dstPoints.ToString ());

                        Calib3d.findHomography(srcPoints,
                                               dstPoints,
                                               Calib3d.FM_RANSAC,
                                               reprojectionThreshold,
                                               inliersMask, 2000, 0.955).copyTo(homography);

                        if (homography.rows() != 3 || homography.cols() != 3)
                        {
                            return(false);
                        }

                        //Debug.Log ("homography " + homography.ToString ());
                        //Debug.Log ("inliersMask " + inliersMask.dump ());

                        List <byte> inliersMaskList = inliersMask.toList();

                        List <DMatch> inliers = new List <DMatch>();
                        for (int i = 0; i < inliersMaskList.Count; i++)
                        {
                            if (inliersMaskList[i] == 1)
                            {
                                inliers.Add(matchesList[i]);
                            }
                        }

                        matches.fromList(inliers);
                        //Debug.Log ("matches " + matches.ToString ());
                    }

            return(matchesList.Count > minNumberMatchesAllowed);
        }
Esempio n. 4
0
    void Orb()
    {
        p1Mat = Imgcodecs.imread(Application.dataPath + "/Textures/1.jpg", 1);
        p2Mat = Imgcodecs.imread(Application.dataPath + "/Textures/3.jpg", 1);
        Imgproc.cvtColor(p1Mat, p1Mat, Imgproc.COLOR_BGR2RGB);
        Imgproc.cvtColor(p2Mat, p2Mat, Imgproc.COLOR_BGR2RGB);
        Imgproc.resize(p2Mat, p2Mat, new Size(p1Mat.width(), p1Mat.height()));
        Debug.Log(p2Mat);

        /*
         * //仿射变换(矩阵旋转)
         * float angle = UnityEngine.Random.Range(0, 360), scale = 1.0f;
         * Point center = new Point(img2Mat.cols() * 0.5f, img2Mat.rows() * 0.5f);
         *
         * Mat affine_matrix = Imgproc.getRotationMatrix2D(center, angle, scale);
         * Imgproc.warpAffine(img1Mat, img2Mat, affine_matrix, img2Mat.size());
         *
         * Texture2D texture = new Texture2D(img2Mat.cols(), img2Mat.rows());
         * Utils.matToTexture2D(img2Mat, texture);
         * outputRawImage.texture = texture;
         */

        ORB detector  = ORB.create();
        ORB extractor = ORB.create();

        //提取图一特征点
        MatOfKeyPoint keypoints1   = new MatOfKeyPoint();
        Mat           descriptors1 = new Mat();

        detector.detect(p1Mat, keypoints1);
        extractor.compute(p1Mat, keypoints1, descriptors1);

        //提取图二特征点
        MatOfKeyPoint keypoints2   = new MatOfKeyPoint();
        Mat           descriptors2 = new Mat();

        detector.detect(p2Mat, keypoints2);
        extractor.compute(p2Mat, keypoints2, descriptors2);

        //第一次匹配结果(密密麻麻)
        DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMINGLUT);
        MatOfDMatch       matches = new MatOfDMatch();

        matcher.match(descriptors1, descriptors2, matches);

        //筛选(非官方)
        //计算向量距离的最大值/最小值
        double max_dist = 0;
        double min_dist = 15; //通过距离控制需要的特征。
        //(设到10,最终只有2个耳朵匹配。。。)
        //(设到15,尾巴也开始匹配。。。。。。)

        //新建两个容器存放筛选样本
        List <DMatch> matchesArray = matches.toList(); //用Unity版API多转一步
        //Debug.Log(matchesArray.Count); //500
        List <DMatch> goodmatchesArray = new List <DMatch>();

        //Debug.Log(img1Mat.rows()); //512
        for (int i = 0; i < matchesArray.Count; i++)
        {
            Debug.Log("[" + i + "]" + matchesArray[i].distance);
            if (matchesArray[i].distance > max_dist)
            {
                //max_dist = matchesArray[i].distance;
            }
            if (matchesArray[i].distance < min_dist)
            {
                min_dist = matchesArray[i].distance;
            }
        }
        //Debug.Log("The max distance is: " + max_dist);
        Debug.Log("The min distance is: " + min_dist);

        for (int i = 0; i < matchesArray.Count; i++)
        {
            if (matchesArray[i].distance < 2 * min_dist) //
            {
                goodmatchesArray.Add(matchesArray[i]);
            }
        }
        MatOfDMatch newMatches = new MatOfDMatch();

        newMatches.fromList(goodmatchesArray);
        Debug.Log(newMatches.toList().Count); //第二次筛选后符合的

        //绘制第二次筛选结果
        dstMat = new Mat();
        Features2d.drawMatches(p1Mat, keypoints1, p2Mat, keypoints2, newMatches, dstMat);

        Texture2D t2d = new Texture2D(dstMat.width(), dstMat.height());

        Utils.matToTexture2D(dstMat, t2d);
        Sprite sp = Sprite.Create(t2d, new UnityEngine.Rect(0, 0, t2d.width, t2d.height), Vector2.zero);

        m_dstImage.sprite         = sp;
        m_dstImage.preserveAspect = true;
    }