computer_vision/harris.cpp
/*******************************************************
* Copyright (c) 2015, ArrayFire
* All rights reserved.
*
* This file is distributed under 3-clause BSD license.
* The complete license agreement can be obtained at:
* https://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);
printf("** ArrayFire Harris Corner Detector Demo **\n\n");
harris_demo(console);
} catch (af::exception& ae) {
fprintf(stderr, "%s\n", ae.what());
throw;
}
return 0;
}
af::Window::image
void image(const array &in, const char *title=NULL)
Renders the input array as an image to the window.
af::seq
seq is used to create sequences for indexing af::array
Definition: seq.h:46
af::array::host
T * host() const
Copy array data to host and return host pointer.
af::info
AFAPI void info()
af::grad
AFAPI void grad(array &dx, array &dy, const array &in)
C++ Interface for calculating the gradients.
af::constant
array constant(T val, const dim4 &dims, const dtype ty=(af_dtype) dtype_traits< T >::ctype)
af::setDevice
AFAPI void setDevice(const int device)
Sets the current device.
af::array
A multi dimensional data container.
Definition: array.h:35
af
Definition: algorithm.h:15
af::gaussianKernel
AFAPI array gaussianKernel(const int rows, const int cols, const double sig_r=0, const double sig_c=0)
C++ Interface for generating gausian kernels.
af_print
#define af_print(...)
Definition: util.h:148
af::Window::close
bool close()
Check if window is marked for close.
af::exception
An ArrayFire exception class.
Definition: exception.h:29
af::where
AFAPI array where(const array &in)
C++ Interface for finding the locations of non-zero values in an array.
af::freeHost
AFAPI void freeHost(const void *ptr)
Free memory allocated internally by ArrayFire.
AF_RGB
@ AF_RGB
3-channel RGB
Definition: defines.h:341
af::array::dims
dim4 dims() const
Get dimensions of the array.
af::colorSpace
AFAPI array colorSpace(const array &image, const CSpace to, const CSpace from)
C++ Interface wrapper for colorspace conversion.
af::loadImage
AFAPI array loadImage(const char *filename, const bool is_color=false)
C++ Interface for loading an image.
arrayfire.h
AF_GRAY
@ AF_GRAY
Grayscale.
Definition: defines.h:340
af::dilate
AFAPI array dilate(const array &in, const array &mask)
C++ Interface for image dilation (max filter)
af::exception::what
virtual const char * what() const
Returns an error message for the exception in a string format.
Definition: exception.h:60
af::convolve
AFAPI array convolve(const array &signal, const array &filter, const convMode mode=AF_CONV_DEFAULT, const convDomain domain=AF_CONV_AUTO)
C++ Interface for convolution any(one through three) dimensional signals.
af::Window
Window object to render af::arrays.
Definition: graphics.h:37