我正在尝试按照OpenCV教程在c ++中实现自己的FAST算法。作为算法says:
如果存在一组n个连续像素,则像素p是一个角 圆圈中的像素(共16个像素)都比I_p + t,或者都比I_p − t更暗。 (在上方显示为白色虚线) 图片)。 n 被选择为12。
提出了一项高速测试,以排除大量 非角。此测试仅检查1、9、5和13处的四个像素 (首先检查第1个和第9个是否太亮或太暗。如果是, 然后检查5和13)。如果p是一个角,那么至少其中三个 必须全部比I_p + t亮或比I_p − t暗。如果两者都不 在这种情况下,则p不能为角。全段测试 然后可以通过检查将标准应用于通过的候选人 圆圈中的所有像素。该探测器本身表现出很高的 性能
我将FAST输出与OpenCV的FAST输出(阈值= 100)进行了比较。我意识到我的未能检测到所有角落:
当我将n减小为0时(为了获得最佳结果,n应当大于12),我使用这种类型的图像测试(仅)获得了相同的结果,但通常它仍然无法检测到矩形的角:
这是我的完整代码:
#include <opencv2/opencv.hpp>
#include <stdio.h>
#include <iostream>
#include <opencv2/features2d/features2d.hpp>
using namespace std;
using namespace cv;
#define THRESHOLD 100
/*
** Compares intensity of pixels 1,5,9,13 of the circle surrounding a pixel at (i,j) of an image with its intensity ip.
** If 3 out of 4 satisfy the threshold FAST constraints : bright (i>ip+t) & dark (i<ip-t),
** the pixel at (i,j) is considered a possible key point
*/
bool couldBeKeyPoint(Mat imageIn, int i, int j, int threshold) {
uchar ip = imageIn.at<unsigned char>(i, j); //intensity of the potential key point
uchar ip9 = imageIn.at<unsigned char>(i, j - 3); //intensity of pixel 1 of the surrounding circle
uchar ip1 = imageIn.at<unsigned char>(i, j + 3); //intensity of pixel 9 of the surrounding circle
uchar ip5 = imageIn.at<unsigned char>(i + 3, j); //intensity of pixel 5 of the surrounding circle
uchar ip13 = imageIn.at<unsigned char>(i - 3, j); //intensity of pixel 13 of the surrounding circle
//checking FAST bright constraints on these 4 surrounding pixels
bool b1 = (ip1 >= ip + threshold);
bool b9 = (ip9 >= ip + threshold);
bool b5 = (ip5 >= ip + threshold);
bool b13 = (ip13 >= ip + threshold);
//cout << b1+b9+b5+b13 ;
//at least three of these must all be brighter than I_p + t.
if (b1+b9+b5+b13 >=3)
return true;
bool d1 = (ip1 <= ip - threshold);
bool d9 = (ip9 <= ip - threshold);
bool d5 = (ip5 <= ip - threshold);
bool d13 = (ip13 <= ip - threshold);
//cout << d1+d9+d5+d13 << "\n" ;
//at least three of these must all be darker than I_p − t.
if (d1+d9+d5+d13 >=3)
return true;
return false;
}
bool isKeyPoint(Mat imageIn, int i, int j, int threshold, int numberPixelsToCheck){
cout << "iskeypoint";
vector<unsigned char> pixelSurroundings;
pixelSurroundings.push_back(imageIn.at<unsigned char>(i, j));//the potential key point
pixelSurroundings.push_back(imageIn.at<unsigned char>(i, j + 3));//pixel 1
pixelSurroundings.push_back(imageIn.at<unsigned char>(i + 1, j + 3 3));//pixel 2
pixelSurroundings.push_back(imageIn.at<unsigned char>(i + 2, j + 2));//pixel 3
pixelSurroundings.push_back(imageIn.at<unsigned char>(i + 3, j + 1));//pixel 4
pixelSurroundings.push_back(imageIn.at<unsigned char>(i + 3, j));//pixel 5
pixelSurroundings.push_back(imageIn.at<unsigned char>(i + 3, j - 1));//pixel 6
pixelSurroundings.push_back(imageIn.at<unsigned char>(i + 2, j - 2));//pixel 7
pixelSurroundings.push_back(imageIn.at<unsigned char>(i + 1, j - 3));//pixel 8
pixelSurroundings.push_back(imageIn.at<unsigned char>(i, j - 3));//pixel 9
pixelSurroundings.push_back(imageIn.at<unsigned char>(i - 1, j - 3));//pixel 10
pixelSurroundings.push_back(imageIn.at<unsigned char>(i - 2, j - 2));//pixel 11
pixelSurroundings.push_back(imageIn.at<unsigned char>(i - 3, j - 1));//pixel 12
pixelSurroundings.push_back(imageIn.at<unsigned char>(i - 3, j));//pixel 13
pixelSurroundings.push_back(imageIn.at<unsigned char>(i - 3, j + 1));//pixel 14
pixelSurroundings.push_back(imageIn.at<unsigned char>(i - 2, j + 2));//pixel 15
pixelSurroundings.push_back(imageIn.at<unsigned char>(i - 1, j + 3));//pixel 16
if (numberPixelsToCheck > 16){
numberPixelsToCheck = 12; //The author have used N=12 in the first version of the algorithm
cout << "Error number of surrounding pixels to check should not exceed 16! Value 12 was used instead. " << std::endl ;
}
unsigned char ip = pixelSurroundings[0];
int brightScore = 0;
int darkScore = 0;
bool d = false,e=false;
for(int j=1;j<pixelSurroundings.size();j++){
unsigned char i = pixelSurroundings[j];
d = (i >= ip + (unsigned char ) threshold);
e = (i <= ip - (unsigned char ) threshold);
brightScore += d;
darkScore += e;
}
cout << darkScore << " DARKSCORE \n";
cout << brightScore << " BRIGHTSCORE \n";
if (darkScore >= numberPixelsToCheck || brightScore >= numberPixelsToCheck){
//cout << darkScore << " DARKSCORE \n";
//cout << brightScore << " BRIGHTSCORE \n";
return true; //the pixel is a key point
}
return false;
}
//renvoit un ensemble de détections
//inputarray image
vector<KeyPoint> FAST(Mat imageIn, vector<KeyPoint> keypoints, int threshold){
if(!imageIn.data ) // Check for invalid input
{
cout << "Could not open or find the image" << std::endl ;
//return {};
}
keypoints.clear();
int i, j, count =0;
for (i = 3; i < imageIn.rows - 3; i++)
{
for (j = 3; j < imageIn.cols - 3; j++)
{
if (couldBeKeyPoint(imageIn, i, j, threshold)){
if (isKeyPoint(imageIn, i, j, threshold, 0)){
keypoints.push_back(KeyPoint(j, i ,1));
count++;
cout << "keypoint found at " << i << " " << j << "\n";
}
}
}
}
cout << "NUMBER OF KEYPOINTS :" << keypoints.size() << "\n";
return keypoints;
}
int main(int argc, char** argv){
vector<KeyPoint> keypointsMyFast;
vector<KeyPoint> keypointsOpenCvFast;
Mat src, destMyFast, destOpenCvFast;
//src= imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
//src= imread(argv[1], CV_8UC3);
src= imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
imshow( "ORGINAL",src);
waitKey(1);
keypointsMyFast = FAST(src, keypointsMyFast,THRESHOLD);
drawKeypoints(src, keypointsMyFast, destMyFast, Scalar(255,0,0));
imshow( "MYFAST",destMyFast);
waitKey(1);
FAST(src,keypointsOpenCvFast,THRESHOLD,false);
cout << "NUMBER OF open cv KEYPOINTS :" << keypointsOpenCvFast.size() << "\n";
drawKeypoints(src, keypointsOpenCvFast, destOpenCvFast, Scalar(255,0,0));
imshow( "Display window",destOpenCvFast);
waitKey(0);
}
关于什么可能导致算法不检测矩形角的任何想法?
从本质上讲:如何使用imread
正确加载图像? (更改第二个参数会得出不同的结果)
非常感谢您
答案 0 :(得分:3)
最初的canbeBeKeyPoint函数中出现问题。此功能检查顶部,底部,左侧,右侧位置的候选关键点位置,如果中心点的亮度高于/高于周围三个点,则返回true。
此假设不适用于直角正方形或矩形,因为正方形/矩形的边缘永远无法满足条件。您需要通过将周围的点数减少到2来放松函数的条件。