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 137
|
/*******************************************************
* 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 <cstdio>
#include <arrayfire.h>
#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++;
}
}
}
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];
std::cout << "Corners found: " << good_corners << std::endl << std::endl;
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();
std::cout << "** ArrayFire Harris Corner Detector Demo **" << std::endl << std::endl;
harris_demo(console);
} catch (af::exception& ae) {
std::cerr << ae.what() << std::endl;
throw;
}
return 0;
}
|