Commit 6991ce02 authored by nanored's avatar nanored
Browse files

anms

parent 521d1dc4
......@@ -10,7 +10,11 @@ const static double sigmaD = 1.0;
const static int kD = 2;
const static double sigmaI = 4.0;
const static int kI = 5;
const static double kappa = 0.05;
const static double kappa = 0.045;
const static double threshold = 0.005;
const static double rNMS = 5;
const static double c = 0.9;
// Return a 1D gaussian kernel of standard deviation sigma of size 2k+1
vector<double> gaussianKernel(double sigma, int k) {
......@@ -73,6 +77,58 @@ Image<double> applyFilterY(const Image<double> &I, const vector<double> &K) {
return IK;
}
// Apply NMS to the points given in first argument for an image of size w
// points in input are represented with a pair composed of the opposite of Harris response
// and an interger representing the pixel index p = x + y*w
// The function returns a subset of points
vector<pair<double, int>> NMS(const vector<pair<double, int>> &points, int w, int h,
const Image<double> &R, int offset)
{
vector<pair<double, int>> res;
int w2 = w-2*offset, h2 = h-2*offset;
for(const auto &p : points) {
int x = p.second % w - offset, y = p.second / w - offset;
double r = R(x, y) / c;
bool maxi = true;
for(int i = max(0, x - int(rNMS)); i <= min(w2-1, x + int(rNMS)); i++) {
int dj = sqrt(rNMS*rNMS - (i-x)*(i-x));
for(int j = max(0, y - dj); j <= min(h2-1, y + dj); j++) {
if(R(i, j) > r) {
maxi = false;
i = w2;
break;
}
}
}
if(maxi) res.push_back(p);
}
return res;
}
// Apply ANMS to the points given in first argument for an image of size w
// points in input are represented with a pair composed of the opposite of Harris response
// and an interger representing the pixel index p = x + y*w
// The function returns a new sorted list of points but this times the first value of pairs
// is the opposite of the 10*radius + epsilon
vector<pair<double, int>> ANMS(const vector<pair<double, int>> &points, int w) {
double INF = 1e9, maxHR = points[0].first;
int n = points.size();
vector<pair<double, int>> res;
for(int i = 0; i < n; i++) {
double r = INF;
int x = points[i].second % w, y = points[i].second / w;
for(int j = 0; j < i; j++) {
if(points[i].first < c * points[j].first) break;
double dx = (points[j].second % w) - x;
double dy = (points[j].second / w) - y;
r = min(dx*dx + dy*dy, r);
}
res.push_back({-10*sqrt(r) - points[i].first/maxHR, points[i].second});
}
sort(res.begin(), res.end());
return res;
}
int main() {
Image<byte> I0;
if(! load(I0, srcPath("im1.jpg"))) {
......@@ -111,31 +167,56 @@ int main() {
// Corner Response
Image<double> R(w2, h2);
vector<pair<double, int>> responses;
double t = 0; // Response Threshold
// Compute responses
for(int i = 0; i < w2; i++)
for(int j = 0; j < h2; j++) {
double det = Ixx(i, j) * Iyy(i, j) - Ixy(i, j) * Ixy(i, j);
double trace = Ixx(i, j) + Iyy(i, j);
R(i, j) = det - kappa * trace;
if(i > 1 && j > 1) {
R(i, j) = det - kappa * trace * trace;
t = max(t, R(i, j));
}
t *= threshold;
// Keep only local maximums
for(int i = 2; i < w2; i++)
for(int j = 2; j < h2; j++) {
double r = R(i-1, j-1);
bool max = true;
if(r < t) continue;
bool maxi = true;
for(int k = i-2; k <= i; k++)
for(int l = j-2; l <= j; l++)
if(R(k, l) > r) max = false;
if(max) responses.push_back({-r, i-1+offset + (j-1+offset)*w});
}
if(R(k, l) > r) maxi = false;
if(maxi) responses.push_back({-r, i-1+offset + (j-1+offset)*w});
}
cout << "Harris found " << responses.size() << " corner points" << endl;
sort(responses.begin(), responses.end());
cout << "Harris found " << responses.size() << " corner points" << endl;
// Display
openWindow(w, h);
string tabNames[3] = {"Best Harris responses", "Best NMS responses", "Best ANMS responses"};
Window W = openComplexWindow(w, h, "Harris Detection", 3, tabNames);
// 200 best Harris responses
setActiveWindow(W, 0);
display(I0);
for(int i = 0; i < 300; i++) {
for(int i = 0; i < 200; i++) {
int p = responses[i].second;
drawCircle(p % w, p / w, 4, RED, 3);
}
click();
// 200 best NMS responses
setActiveWindow(W, 1);
display(I0);
vector<pair<double, int>> nms = NMS(responses, w, h, R, offset);
for(int i = 0; i < 200; i++) {
int p = nms[i].second;
drawCircle(p % w, p / w, 4, RED, 3);
}
// 200 best ANMS responses
setActiveWindow(W, 2);
display(I0);
vector<pair<double, int>> anms = ANMS(responses, w);
for(int i = 0; i < 200; i++) {
int p = anms[i].second;
drawCircle(p % w, p / w, 4, RED, 3);
}
endGraphics();
return 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment