【特徵檢測】BRISK特徵提取演算法
阿新 • • 發佈:2019-01-09
// construct the image pyramids(構造影象金字塔) void BriskScaleSpace::constructPyramid(const cv::Mat& image) { // set correct size: pyramid_.clear(); // fill the pyramid: pyramid_.push_back(BriskLayer(image.clone())); if (layers_ > 1) { pyramid_.push_back(BriskLayer(pyramid_.back(), BriskLayer::CommonParams::TWOTHIRDSAMPLE));//d0層是2/3 } const int octaves2 = layers_; for (uchar i = 2; i < octaves2; i += 2) { pyramid_.push_back(BriskLayer(pyramid_[i - 2], BriskLayer::CommonParams::HALFSAMPLE));//c?層是前兩層的1/2 pyramid_.push_back(BriskLayer(pyramid_[i - 1], BriskLayer::CommonParams::HALFSAMPLE));//d?層是前兩層的1/2(除d0層外) } }
//提取特徵點 void BriskScaleSpace::getKeypoints(const int threshold_, std::vector<cv::KeyPoint>& keypoints) { // make sure keypoints is empty keypoints.resize(0); keypoints.reserve(2000); // assign thresholds int safeThreshold_ = (int)(threshold_ * safetyFactor_); std::vector<std::vector<cv::KeyPoint> > agastPoints; agastPoints.resize(layers_); // go through the octaves and intra layers and calculate fast corner scores: for (int i = 0; i < layers_; i++) { // call OAST16_9 without nms BriskLayer& l = pyramid_[i]; l.getAgastPoints(safeThreshold_, agastPoints[i]); } if (layers_ == 1) { // just do a simple 2d subpixel refinement... const size_t num = agastPoints[0].size(); for (size_t n = 0; n < num; n++) { const cv::Point2f& point = agastPoints.at(0)[n].pt; // first check if it is a maximum: if (!isMax2D(0, (int)point.x, (int)point.y)) continue; // let's do the subpixel and float scale refinement: BriskLayer& l = pyramid_[0]; int s_0_0 = l.getAgastScore(point.x - 1, point.y - 1, 1); int s_1_0 = l.getAgastScore(point.x, point.y - 1, 1); int s_2_0 = l.getAgastScore(point.x + 1, point.y - 1, 1); int s_2_1 = l.getAgastScore(point.x + 1, point.y, 1); int s_1_1 = l.getAgastScore(point.x, point.y, 1); int s_0_1 = l.getAgastScore(point.x - 1, point.y, 1); int s_0_2 = l.getAgastScore(point.x - 1, point.y + 1, 1); int s_1_2 = l.getAgastScore(point.x, point.y + 1, 1); int s_2_2 = l.getAgastScore(point.x + 1, point.y + 1, 1); float delta_x, delta_y; float max = subpixel2D(s_0_0, s_0_1, s_0_2, s_1_0, s_1_1, s_1_2, s_2_0, s_2_1, s_2_2, delta_x, delta_y); // store: keypoints.push_back(cv::KeyPoint(float(point.x) + delta_x, float(point.y) + delta_y, basicSize_, -1, max, 0)); } return; } float x, y, scale, score; for (int i = 0; i < layers_; i++) { BriskLayer& l = pyramid_[i]; const size_t num = agastPoints[i].size(); if (i == layers_ - 1) { for (size_t n = 0; n < num; n++) { const cv::Point2f& point = agastPoints.at(i)[n].pt; // consider only 2D maxima... if (!isMax2D(i, (int)point.x, (int)point.y)) continue; bool ismax; float dx, dy; getScoreMaxBelow(i, (int)point.x, (int)point.y, l.getAgastScore(point.x, point.y, safeThreshold_), ismax, dx, dy); if (!ismax) continue; // get the patch on this layer: int s_0_0 = l.getAgastScore(point.x - 1, point.y - 1, 1); int s_1_0 = l.getAgastScore(point.x, point.y - 1, 1); int s_2_0 = l.getAgastScore(point.x + 1, point.y - 1, 1); int s_2_1 = l.getAgastScore(point.x + 1, point.y, 1); int s_1_1 = l.getAgastScore(point.x, point.y, 1); int s_0_1 = l.getAgastScore(point.x - 1, point.y, 1); int s_0_2 = l.getAgastScore(point.x - 1, point.y + 1, 1); int s_1_2 = l.getAgastScore(point.x, point.y + 1, 1); int s_2_2 = l.getAgastScore(point.x + 1, point.y + 1, 1); float delta_x, delta_y; float max = subpixel2D(s_0_0, s_0_1, s_0_2, s_1_0, s_1_1, s_1_2, s_2_0, s_2_1, s_2_2, delta_x, delta_y); // store: keypoints.push_back( cv::KeyPoint((float(point.x) + delta_x) * l.scale() + l.offset(), (float(point.y) + delta_y) * l.scale() + l.offset(), basicSize_ * l.scale(), -1, max, i)); } } else { // not the last layer: for (size_t n = 0; n < num; n++) { const cv::Point2f& point = agastPoints.at(i)[n].pt; // first check if it is a maximum: if (!isMax2D(i, (int)point.x, (int)point.y)) continue; // let's do the subpixel and float scale refinement: bool ismax=false; score = refine3D(i, (int)point.x, (int)point.y, x, y, scale, ismax); if (!ismax) { continue; } // finally store the detected keypoint: if (score > float(threshold_)) { keypoints.push_back(cv::KeyPoint(x, y, basicSize_ * scale, -1, score, i)); } } } } }