Example #1
0
    void R2RegionCoverer::getCovering( const R2Region& region, vector<GeoHash>* cover ) {
        // Strategy: Start with the full plane. Discard any
        // that do not intersect the shape.  Then repeatedly choose the
        // largest cell that intersects the shape and subdivide it.
        //
        // _result contains the cells that will be part of the output, while the
        // queue contains cells that we may still subdivide further.  Cells that
        // are entirely contained within the region are immediately added to the
        // output, while cells that do not intersect the region are immediately
        // discarded. Therefore the queue only contains cells that partially
        // intersect the region. Candidates are prioritized first according to
        // cell size (larger cells first), then by the number of intersecting
        // children they have (fewest children first), and then by the number of
        // fully contained children (fewest children first).

        verify(_minLevel <= _maxLevel);
        dassert(_candidateQueue->empty());
        dassert(_results->empty());
        _region = &region;

        getInitialCandidates();

        while(!_candidateQueue->empty()) {
            Candidate* candidate = _candidateQueue->top().second; // Owned
            _candidateQueue->pop();
            LOG(3) << "Pop: " << candidate->cell;

            // Try to expand this cell into its children
            if (candidate->cell.getBits() < _minLevel ||
                    candidate->numChildren == 1 ||
                    (int)_results->size() +
                    (int)_candidateQueue->size() +
                    candidate->numChildren <= _maxCells) {

                for (int i = 0; i < candidate->numChildren; i++) {
                    addCandidate(candidate->children[i]);
                }
                deleteCandidate(candidate, false);
            } else {
                // Reached max cells. Move all candidates from the queue into results.
                candidate->isTerminal = true;
                addCandidate(candidate);
            }
            LOG(3) << "Queue: " << _candidateQueue->size();
        }

        _region = NULL;
        cover->swap(*_results);
    }
Example #2
0
std::vector<PipelineGrid> GridFitter::fitGrid(const Tag& tag, const TagCandidate &candidate)
{
#ifdef DEBUG_GRIDFITTER
	cv::destroyAllWindows();
#endif

	const Ellipse& ellipse_orig = candidate.getEllipse();

	// region of interest of tag candidate
    const cv::Size2i roiSize = tag.getRoi().size();
	cv::Mat roi;
    tag.getRepresentations().clahe.copyTo(roi);

	cv::Mat binarizedROI(roiSize, CV_8UC1);
	cv::adaptiveThreshold(roi, binarizedROI, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C,
	                      cv::THRESH_BINARY, _settings.get_adaptive_block_size(),
	                      _settings.get_adaptive_c());

	cv::Mat blurredRoi;
	cv::GaussianBlur(roi, blurredRoi, cv::Size(3, 3), 0, 0, cv::BORDER_DEFAULT);

	auto getSobel = [&](const int dx, const int dy) {
		cv::Mat sobelImg;
		cv::Scharr(blurredRoi, sobelImg, CV_32F, dx, dy);

        static const double ksize = 3.;
        const double denom = std::pow(2., ksize * 2. - dx - dy - 2);

        sobelImg.convertTo(sobelImg, CV_8UC1, 1. / (2. * denom), 255. / 2.);

		return sobelImg;
	};

	cv::Mat edgeRoiX = getSobel(1, 0);
	cv::Mat edgeRoiY = getSobel(0, 1);

	// TODO: constant/setting for axis border
	// TODO: add sanity checks
	const cv::Mat ellipseMask = candidate.getEllipse().getMask(cv::Size(10, 10));
	cv::Mat equalizedRoi;
	roi.copyTo(equalizedRoi, ellipseMask);
	cv::equalizeHist(equalizedRoi, roi);

	// get initial candidates using brute force search over small number of
	// rotations and position offsets
	candidate_set gridCandidates = getInitialCandidates(binarizedROI, edgeRoiX, edgeRoiY, ellipse_orig, roi);

#ifdef DEBUG_GRIDFITTER
	visualizeDebug(gridCandidates, roi, roiSize, edgeRoiX, edgeRoiY, tag, binarizedROI, "candidate", _settings.get_gradient_num_initial());
#endif

	// optimize best candidates using gradient descent
	GradientDescent optimizer(gridCandidates, roi, binarizedROI, edgeRoiX, edgeRoiY, _settings_cache);
	optimizer.optimize();

	const candidate_set& bestGrids = optimizer.getBestGrids();

#ifdef DEBUG_GRIDFITTER
	std::cout << "min initial candidate error: " << gridCandidates.begin()->error << std::endl;
	std::cout << "min final candidate error: " << bestGrids.begin()->error << std::endl;

	visualizeDebug(bestGrids, roi, roiSize, edgeRoiX, edgeRoiY, tag, binarizedROI, "best fit", _settings.get_gradient_num_results());
#endif

	// return the settings.numResults best candidates
	std::vector<PipelineGrid> results;
	{
		const size_t to = std::min(_settings.get_gradient_num_results(), bestGrids.size());
		size_t idx = 0;
		for (candidate_t const& gridCandidate : bestGrids) {
			Util::gridconfig_t const& config = gridCandidate.config;
            results.emplace_back(config.center + tag.getRoi().tl(), config.radius, config.angle_z,
								 config.angle_y, config.angle_x, gridCandidate.error);

			++idx;
			if (idx == to) break;
		}
	}

	return results;
}