forked from arrayfire/arrayfire
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathharris.cpp
More file actions
136 lines (109 loc) · 4.46 KB
/
harris.cpp
File metadata and controls
136 lines (109 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*******************************************************
* Copyright (c) 2015, ArrayFire
* All rights reserved.
*
* This file is distributed under 3-clause BSD license.
* The complete license agreement can be obtained at:
* http://arrayfire.com/licenses/BSD-3-Clause
********************************************************/
#include <arrayfire.h>
#include <cstdio>
#include <cstdlib>
using namespace af;
static void harris_demo(bool console) {
af::Window wnd("Harris Corner Detector");
// Load image
array img_color;
if (console)
img_color = loadImage(ASSETS_DIR "/examples/images/square.png", true);
else
img_color = loadImage(ASSETS_DIR "/examples/images/man.jpg", true);
// Convert the image from RGB to gray-scale
array img = colorSpace(img_color, AF_GRAY, AF_RGB);
// For visualization in ArrayFire, color images must be in the [0.0f-1.0f]
// interval
img_color /= 255.f;
// Calculate image gradients
array ix, iy;
grad(ix, iy, img);
// Compute second-order derivatives
array ixx = ix * ix;
array ixy = ix * iy;
array iyy = iy * iy;
// Compute a Gaussian kernel with standard deviation of 1.0 and length of 5
// pixels These values can be changed to use a smaller or larger window
array gauss_filt = gaussianKernel(5, 5, 1.0, 1.0);
// Filter second-order derivatives with Gaussian kernel computed previously
ixx = convolve(ixx, gauss_filt);
ixy = convolve(ixy, gauss_filt);
iyy = convolve(iyy, gauss_filt);
// Calculate trace
array itr = ixx + iyy;
// Calculate determinant
array idet = ixx * iyy - ixy * ixy;
// Calculate Harris response
array response = idet - 0.04f * (itr * itr);
// Gets maximum response for each 3x3 neighborhood
// array max_resp = maxfilt(response, 3, 3);
array mask = constant(1, 3, 3);
array max_resp = dilate(response, mask);
// Discard responses that are not greater than threshold
array corners = response > 1e5f;
corners = corners * response;
// Discard responses that are not equal to maximum neighborhood response,
// scale them to original response value
corners = (corners == max_resp) * corners;
// Gets host pointer to response data
float* h_corners = corners.host<float>();
unsigned good_corners = 0;
// Draw draw_len x draw_len crosshairs where the corners are
const int draw_len = 3;
for (int y = draw_len; y < img_color.dims(0) - draw_len; y++) {
for (int x = draw_len; x < img_color.dims(1) - draw_len; x++) {
// Only draws crosshair if is a corner
if (h_corners[x * corners.dims(0) + y] > 1e5f) {
// Draw horizontal line of (draw_len * 2 + 1) pixels centered on
// the corner Set only the first channel to 1 (green lines)
img_color(y, seq(x - draw_len, x + draw_len), 0) = 0.f;
img_color(y, seq(x - draw_len, x + draw_len), 1) = 1.f;
img_color(y, seq(x - draw_len, x + draw_len), 2) = 0.f;
// Draw vertical line of (draw_len * 2 + 1) pixels centered on
// the corner Set only the first channel to 1 (green lines)
img_color(seq(y - draw_len, y + draw_len), x, 0) = 0.f;
img_color(seq(y - draw_len, y + draw_len), x, 1) = 1.f;
img_color(seq(y - draw_len, y + draw_len), x, 2) = 0.f;
good_corners++;
}
}
}
freeHost(h_corners);
printf("Corners found: %u\n", good_corners);
if (!console) {
// Previews color image with green crosshairs
while (!wnd.close()) wnd.image(img_color);
} else {
// Find corner indexes in the image as 1D indexes
array idx = where(corners);
// Calculate 2D corner indexes
array corners_x = idx / corners.dims()[0];
array corners_y = idx % corners.dims()[0];
const int good_corners = corners_x.dims()[0];
printf("Corners found: %d\n\n", good_corners);
af_print(corners_x);
af_print(corners_y);
}
}
int main(int argc, char** argv) {
int device = argc > 1 ? atoi(argv[1]) : 0;
bool console = argc > 2 ? argv[2][0] == '-' : false;
try {
af::setDevice(device);
af::info();
printf("** ArrayFire Harris Corner Detector Demo **\n\n");
harris_demo(console);
} catch (af::exception& ae) {
fprintf(stderr, "%s\n", ae.what());
throw;
}
return 0;
}