示例#1
0
        public bool extractMatches(FeaturePairStack i_matche_resule, int refWidth, int refHeight)
        {
            // Extract the data from the features
            // hough.vote((float*)&query[0], (float*)&ref[0], (int)matches.size());
            int size = i_matche_resule.getLength();

            if (size == 0)
            {
                return(false);
            }
            //ワークエリア
            if (this._mSubBinLocations.Length < size)
            {
                this._mSubBinLocations = SubBinLocation.createArray(size + 10);
            }

            //FindHoughSimilarity
            int max_dim = refWidth > refHeight ? refWidth : refHeight;//math_utils.max2(mRefImageWidth, mRefImageHeight);

            if (!this.autoAdjustXYNumBins(max_dim, i_matche_resule))
            {
                return(false);
            }

            this.votemap.reset();
            int num_of_subbin   = this.vote(i_matche_resule, refWidth / 2, refHeight / 2, this._mSubBinLocations);
            int max_hough_index = this.votemap.findMax();

            if (max_hough_index < 0)
            {
                return(false);
            }
            this.FindHoughMatches(i_matche_resule, max_hough_index, kHoughBinDelta, this._mSubBinLocations, num_of_subbin);
            return(true);
        }
示例#2
0
        /**
         * 現在の特徴点セットから、
         * @param i_keymap
         * @param i_result
         * @return
         */
        public bool kpmMatching(KeyframeMap i_keymap, NyARDoubleMatrix44 i_transmat)
        {
            FeaturePairStack result = new FeaturePairStack(kMaxNumFeatures);

            if (!this.query(this.mQueryKeyframe, i_keymap, result))
            {
                return(false);
            }
            return(kpmUtilGetPose_binary(this._ref_cparam, result, i_transmat, this._result_param));
        }
示例#3
0
        private static bool kpmUtilGetPose_binary(NyARParam i_cparam, FeaturePairStack matchData, NyARDoubleMatrix44 i_transmat, NyARTransMatResultParam i_resultparam)
        {
            NyARDoubleMatrix44 initMatXw2Xc = new NyARDoubleMatrix44();
            // ARdouble err;
            int i;

            if (matchData.getLength() < 4)
            {
                return(false);
            }
            NyARDoublePoint2d[] sCoord = NyARDoublePoint2d.createArray(matchData.getLength());
            NyARDoublePoint3d[] wCoord = NyARDoublePoint3d.createArray(matchData.getLength());
            for (i = 0; i < matchData.getLength(); i++)
            {
                sCoord[i].x = matchData.getItem(i).query.x;
                sCoord[i].y = matchData.getItem(i).query.y;

                wCoord[i].x = matchData.getItem(i).ref_.pos3d.x;
                wCoord[i].y = matchData.getItem(i).ref_.pos3d.y;
                wCoord[i].z = 0.0;
            }


            NyARIcpPlane icp_planer = new NyARIcpPlane(i_cparam.getPerspectiveProjectionMatrix());

            if (!icp_planer.icpGetInitXw2Xc_from_PlanarData(sCoord, wCoord, matchData.getLength(), initMatXw2Xc))
            {
                return(false);
            }

            /*
             * printf("--- Init pose ---\n"); for( int j = 0; j < 3; j++ ) { for( i = 0; i < 4; i++ ) printf(" %8.3f",
             * initMatXw2Xc[j][i]); printf("\n"); }
             */
            NyARIcpPoint icp_point = new NyARIcpPoint(i_cparam.getPerspectiveProjectionMatrix());

            icp_point.icpPoint(sCoord, wCoord, matchData.getLength(), initMatXw2Xc, i_transmat, i_resultparam);
            if (i_resultparam.last_error > 10.0f)
            {
                return(false);
            }
            return(true);
        }
示例#4
0
        /**
         * Set the number of bins for translation based on the correspondences.
         */
        private bool autoAdjustXYNumBins(int max_dim, FeaturePairStack i_point_pair)
        {
            int l = i_point_pair.getLength();

            //prepare work area
            if (this._project_dim.Length < l)
            {
                this._project_dim = new double[l + 10];
            }
            double[] projected_dim = this._project_dim;
            for (int i = l - 1; i >= 0; i--)
            {
                // Scale is the 3rd component
                FeaturePairStack.Item item = i_point_pair.getItem(i);
                // Project the max_dim via the scale
                double scale = SafeDivision(item.query.scale, item.ref_.scale);
                projected_dim[i] = scale * max_dim;
            }

            // Find the median projected dim
            // float median_proj_dim = FastMedian<float>(&projected_dim[0],
            // (int)projected_dim.size());
            double median_proj_dim = FastMedian(projected_dim, l);

            // Compute the bin size a fraction of the median projected dim
            double bin_size = 0.25f * median_proj_dim;

            int t;

            t = (int)Math.Ceiling((mMaxX - mMinX) / bin_size);
            this.mNumXBins = (5 > t ? 5 : t);
            t = (int)Math.Ceiling((mMaxY - mMinY) / bin_size);
            this.mNumYBins = (5 > t ? 5 : t);
            if (mNumXBins >= 128 || mNumYBins >= 128)
            {
                return(false);
            }
            return(true);
        }
示例#5
0
        private bool query(FreakFeaturePointStack query_keyframe, KeyframeMap i_keymap, FeaturePairStack i_result)
        {
            // mMatchedInliers.clear();
            HomographyMat        H    = this._H;
            InverseHomographyMat hinv = this._hinv;

            hinv = new InverseHomographyMat_O1();

            int num_of_query_frame = query_keyframe.getLength();

            //ワークエリアの設定
            if (num_of_query_frame > this._tmp_pair_stack[0].getArraySize())
            {
                this._tmp_pair_stack[0] = new FeaturePairStack(num_of_query_frame + 10);
                this._tmp_pair_stack[1] = new FeaturePairStack(num_of_query_frame + 10);
            }
            int tmp_ch       = 0;
            int last_inliers = 0;

            foreach (KeyValuePair <int, Keyframe> i in i_keymap)
            {
                Keyframe second = i.Value;
                FreakMatchPointSetStack ref_points = second.getFeaturePointSet();
                //新しいワークエリアを作る。
                FeaturePairStack match_result = this._tmp_pair_stack[tmp_ch];
                //ワークエリア初期化
                match_result.clear();

                //特徴量同士のマッチング
                if (this._matcher.match(query_keyframe, second, match_result) < this.mMinNumInliers)
                {
                    continue;
                }

                // Vote for a transformation based on the correspondences
                if (!this.mHoughSimilarityVoting.extractMatches(match_result, second.width(), second.height()))
                {
                    continue;
                }

                // Estimate the transformation between the two images
                if (!this.mRobustHomography.PreemptiveRobustHomography(H, match_result, second.width(), second.height()))
                {
                    continue;
                }

                //ここでHInv計算
                if (!hinv.inverse(H))
                {
                    continue;
                }

                // Apply some heuristics to the homography
                if (!hinv.checkHomographyHeuristics(second.width(), second.height()))
                {
                    continue;
                }

                // Find the inliers
                this._find_inliner.extructMatches(H, match_result);
                if (match_result.getLength() < mMinNumInliers)
                {
                    continue;
                }

                //
                // Use the estimated homography to find more inliers
                match_result.clear();
                if (_matcher.match(query_keyframe, ref_points, hinv, 10, match_result) < mMinNumInliers)
                {
                    continue;
                }

                //
                // Vote for a similarity with new matches
                if (!this.mHoughSimilarityVoting.extractMatches(match_result, second.width(), second.height()))
                {
                    continue;
                }

                //
                // Re-estimate the homography
                if (!this.mRobustHomography.PreemptiveRobustHomography(H, match_result, second.width(), second.height()))
                {
                    continue;
                }
                // Apply some heuristics to the homography
                if (!hinv.inverse(H))
                {
                    continue;
                }
                if (!hinv.checkHomographyHeuristics(second.width(), second.height()))
                {
                    continue;
                }
                //
                // Check if this is the best match based on number of inliers
                this._find_inliner.extructMatches(H, match_result);

                //ポイント数が最小値より大きい&&最高成績ならテンポラリチャンネルを差し替える。
                if (match_result.getLength() >= mMinNumInliers && match_result.getLength() > last_inliers)
                {
                    //出力チャンネルを切り替え
                    tmp_ch       = (tmp_ch + 1) % 2;
                    last_inliers = match_result.getLength();
                }
            }
            //出力は last_inlines>0の場合に[(tmp_ch+1)%2]にある。
            if (last_inliers <= 0)
            {
                return(false);
            }
            {
                FeaturePairStack        match_result = this._tmp_pair_stack[(tmp_ch + 1) % 2];
                FeaturePairStack.Item[] dest         = match_result.getArray();
                for (int i = 0; i < match_result.getLength(); i++)
                {
                    FeaturePairStack.Item t = i_result.prePush();
                    if (t == null)
                    {
                        System.Console.WriteLine("Push overflow!");
                        break;
                    }
                    t.query = dest[i].query;
                    t.ref_  = dest[i].ref_;
                }
            }
            return(true);
        }
示例#6
0
        private int vote(FeaturePairStack i_point_pair, int i_center_x, int i_center_y, SubBinLocation[] i_sub_bin_locations)
        {
            int size = i_point_pair.getLength();


            int num_features_that_cast_vote = 0;

            for (int i = 0; i < size; i++)
            {
                //mapCorrespondence(r,i_point_pair.getItem(i),i_center_x,i_center_y);
                double rx, ry, rangle, rscale;
                {
                    FreakFeaturePoint ins  = i_point_pair.getItem(i).query;
                    FreakFeaturePoint ref_ = i_point_pair.getItem(i).ref_;

                    //angle
                    rangle = ins.angle - ref_.angle;
                    // Map angle to (-pi,pi]
                    if (rangle <= -PI)
                    {
                        rangle += (2 * PI);
                    }
                    else if (rangle > PI)
                    {
                        rangle -= (2 * PI);
                    }

                    double scale = SafeDivision(ins.scale, ref_.scale);
                    double c     = (scale * Math.Cos(rangle));
                    double s     = (scale * Math.Sin(rangle));

                    //scale
                    rscale = (double)(Math.Log(scale) * this.mScaleOneOverLogK);
                    //x,y
                    rx = c * i_center_x - s * i_center_y + (ins.x - (c * ref_.x - s * ref_.y));
                    ry = s * i_center_x + c * i_center_y + (ins.y - (s * ref_.x + c * ref_.y));
                    // Check that the vote is within range
                    if (rx < mMinX || rx >= mMaxX || ry < mMinY || ry >= mMaxY ||
                        rangle <= -PI || rangle > PI ||
                        rscale < mMinScale || rscale >= mMaxScale)
                    {
                        continue;
                    }
                }
                // Compute the bin location
                SubBinLocation sub_bin = i_sub_bin_locations[num_features_that_cast_vote];
                mapVoteToBin(sub_bin, rx, ry, rangle, rscale);
                int binX     = (int)Math.Floor(sub_bin.x - 0.5f);
                int binY     = (int)Math.Floor(sub_bin.y - 0.5f);
                int binScale = (int)Math.Floor(sub_bin.scale - 0.5f);
                int binAngle = ((int)Math.Floor(sub_bin.angle - 0.5f) + mNumAngleBins) % mNumAngleBins;

                // Check that we can voting to all 16 bin locations
                if (binX < 0 || (binX + 1) >= mNumXBins || binY < 0 ||
                    (binY + 1) >= mNumYBins || binScale < 0 ||
                    (binScale + 1) >= mNumScaleBins)
                {
                    continue;
                }
                sub_bin.index = i;
                num_features_that_cast_vote++;
                this.votemap.vote16(binX, binY, binAngle, binScale, 1);
            }
            return(num_features_that_cast_vote);
        }
示例#7
0
        /**
         * Get only the matches that are consistent based on the hough votes.
         */
        private void FindHoughMatches(FeaturePairStack in_matches, int binIndex, double binDelta, SubBinLocation[] i_sub_bin, int i_num_of_sbin)
        {
            /**
             * Get the bins locations from an index.
             */
            double ref_x, ref_y, ref_angle, ref_scale;
            {
                //ハッシュ値から元の値を復帰
                int binX     = binIndex & 0x3f;
                int binY     = (binIndex >> 7) & 0x3f;
                int binAngle = (binIndex >> 14) & 0x3f;
                int binScale = (binIndex >> 21) & 0x3f;

                ref_x     = binX + 0.5;
                ref_y     = binY + 0.5;
                ref_angle = binAngle + 0.5;
                ref_scale = binScale + 0.5;
            }


            //
            int pos = 0;

            for (int i = 0; i < i_num_of_sbin; i++)
            {
                SubBinLocation ins = i_sub_bin[i];
                //getBinDistance
                double d;

                //x
                d = Math.Abs(ins.x - ref_x);
                if (d >= binDelta)
                {
                    continue;
                }
                //y
                d = Math.Abs(ins.y - ref_y);
                if (d >= binDelta)
                {
                    continue;
                }
                //scale
                d = Math.Abs(ins.scale - ref_scale);
                if (d >= binDelta)
                {
                    continue;
                }
                // Angle
                double d1 = Math.Abs(ins.angle - ref_angle);
                double d2 = (double)this.mNumAngleBins - d1;
                d = d1 < d2 ? d1 : d2;
                if (d >= binDelta)
                {
                    continue;
                }

                //idxは昇順のはずだから詰める。
                int idx = ins.index;
                in_matches.swap(idx, pos);
                pos++;
            }
            in_matches.setLength(pos);
            return;
        }
        /**
         * Robustly solve for the homography given a set of correspondences.
         * p=src=ref,q=dest=query
         */
        public bool PreemptiveRobustHomography(HomographyMat H, FeaturePairStack matches, double i_width, double i_height)
        {
            RansacPointTable ps = this._ps;

            //		int[] tmp_i=new int[2 * num_points];
            HomographyMat[] hyp                = this.mHyp;/* 9*max_num_hypotheses */
            CostPair[]      hyp_costs          = this.mHypCosts;
            double          scale              = this.mCauchyScale;
            int             max_num_hypotheses = this.mMaxNumHypotheses;
            int             max_trials         = this.mMaxTrials;


            double one_over_scale2 = 1 / (scale * scale);

            int num_hypotheses_remaining;
            int cur_chunk_size, this_chunk_end;
            int sample_size = 4;

            this._homography_check.setTestWindow(i_width, i_height);

            int num_points = matches.getLength();

            // We need at least SAMPLE_SIZE points to sample from
            if (num_points < sample_size)
            {
                return(false);
            }

            // seed = 1234;
            ps.setSequential(matches.getArray(), num_points);
            ps.setSeed(1234);
            // Shuffle the indices
            ps.shuffle(num_points);

            int num_hypotheses = 0;

            // Compute a set of hypotheses
            for (int trial = 0; trial < max_trials; trial++)
            {
                // Shuffle the first SAMPLE_SIZE indices
                ps.shuffle(sample_size);

                // Check if the 4 points are geometrically valid
                if (!ps.geometricallyConsistent4Point())
                {
                    continue;
                }

                // Compute the homography
                if (!this._homography_solver.solveHomography4Points(ps.indics[0], ps.indics[1], ps.indics[2], ps.indics[3], hyp[num_hypotheses]))
                {
                    continue;
                }
                // Check the test points
                if (!this._homography_check.geometricallyConsistent(hyp[num_hypotheses]))
                {
                    continue;
                }
                num_hypotheses++;
                if (num_hypotheses == max_num_hypotheses)
                {
                    break;
                }
            }

            // We fail if no hypotheses could be computed
            if (num_hypotheses == 0)
            {
                return(false);
            }

            // Initialize the hypotheses costs
            for (int i = 0; i < num_hypotheses; i++)
            {
                hyp_costs[i].first  = 0;
                hyp_costs[i].second = i;
            }

            num_hypotheses_remaining = num_hypotheses;

            //チャンクサイズの決定
            int chunk_size = this.mChunkSize;

            if (chunk_size > num_points)
            {
                chunk_size = num_points;
            }
            cur_chunk_size = chunk_size;

            for (int i = 0; i < num_points && num_hypotheses_remaining > 2; i += cur_chunk_size)
            {
                // Size of the current chunk
                cur_chunk_size = (chunk_size < num_points - i) ? chunk_size : (num_points - i);

                // End of the current chunk
                this_chunk_end = i + cur_chunk_size;

                // Score each of the remaining hypotheses
                for (int j = 0; j < num_hypotheses_remaining; j++)
                {
                    // const T* H_cur = &hyp[hyp_costs[j].second*9];
                    double hf = hyp[hyp_costs[j].second].cauchyProjectiveReprojectionCostSum(ps.indics, i, this_chunk_end, one_over_scale2);
                    hyp_costs[j].first = hf;
                }
                // Cut out half of the hypotheses
                FastMedian(hyp_costs, num_hypotheses_remaining);
                num_hypotheses_remaining = num_hypotheses_remaining >> 1;
            }

            // Find the best hypothesis
            int    min_index = hyp_costs[0].second;
            double min_cost  = hyp_costs[0].first;

            for (int i = 1; i < num_hypotheses_remaining; i++)
            {
                if (hyp_costs[i].first < min_cost)
                {
                    min_cost  = hyp_costs[i].first;
                    min_index = hyp_costs[i].second;
                }
            }

            // Move the best hypothesis
            H.setValue(hyp[min_index]);
            H.normalizeHomography();

            return(true);
        }