* Copyright (c) 2015, ArrayFire
* All rights reserved.
* This file is distributed under 3-clause BSD license.
* The complete license agreement can be obtained at:
#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);
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 =<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;
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);
int main(int argc, char** argv) {
int device = argc > 1 ? atoi(argv[1]) : 0;
bool console = argc > 2 ? argv[2][0] == '-' : false;
try {
printf("** ArrayFire Harris Corner Detector Demo **\n\n");
} catch (af::exception& ae) {
fprintf(stderr, "%s\n", ae.what());
return 0;
Window object to render af::arrays.
Definition: graphics.h:37
dim4 dims() const
Get dimensions of the array.
T * host() const
Copy array data to host and return host pointer.
dim_t dims[4]
Definition: dim4.hpp:28
An ArrayFire exception class.
Definition: exception.h:22
virtual const char * what() const
Returns an error message for the exception in a string format.
Definition: exception.h:46
Definition: defines.h:340
3-channel RGB
Definition: defines.h:341
AFAPI void grad(array &dx, array &dy, const array &in)
C++ Interface for calculating the gradients.
array constant(T val, const dim4 &dims, const dtype ty=(af_dtype) dtype_traits< T >::ctype)
AFAPI void freeHost(const void *ptr)
Free memory allocated internally by ArrayFire.
AFAPI void info()
AFAPI void setDevice(const int device)
Sets the current device.
void image(const array &in, const char *title=NULL)
Renders the input array as an image to the window.
bool close()
Check if window is marked for close.
AFAPI array colorSpace(const array &image, const CSpace to, const CSpace from)
C++ Interface wrapper for colorspace conversion.
AFAPI array dilate(const array &in, const array &mask)
C++ Interface for image dilation (max filter)
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.
AFAPI array loadImage(const char *filename, const bool is_color=false)
C++ Interface for loading an image.
static af::array array(af::dim4 idims, cl_mem buf, af::dtype type, bool retain=false)
Create an af::array object from an OpenCL cl_mem buffer.
Definition: opencl.h:327
AFAPI array where(const array &in)
C++ Interface for finding the locations of non-zero values in an array.
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.
Definition: algorithm.h:15
#define af_print(...)
Definition: util.h:148