image_processing/binary_thresholding.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 <cmath>
#include <cstdio>
#include <cstdlib>
using namespace af;
array threshold(const array& in, float thresholdValue) {
int channels = in.dims(2);
array ret_val = in.copy();
if (channels > 1) ret_val = colorSpace(in, AF_GRAY, AF_RGB);
ret_val =
(ret_val < thresholdValue) * 0.0f + 255.0f * (ret_val > thresholdValue);
return ret_val;
}
array otsu(const array& in) {
array gray;
int channels = in.dims(2);
if (channels > 1)
gray = colorSpace(in, AF_GRAY, AF_RGB);
else
gray = in;
unsigned total = gray.elements();
array hist = histogram(gray, 256, 0.0f, 255.0f);
array wts = range(256);
array wtB = accum(hist);
array wtF = total - wtB;
array sumB = accum(wts * hist);
array meanB = sumB / wtB;
float lastElemInSumB;
sumB(seq(255, 255, 1)).host((void*)&lastElemInSumB);
array meanF = (lastElemInSumB - sumB) / wtF;
array mDiff = meanB - meanF;
array interClsVar = wtB * wtF * mDiff * mDiff;
float max = af::max<float>(interClsVar);
float threshold2 = where(interClsVar == max).scalar<unsigned>();
array threshIdx = where(interClsVar >= max);
float threshold1 =
threshIdx.elements() > 0 ? threshIdx.scalar<unsigned>() : 0.0f;
return threshold(gray, (threshold1 + threshold2) / 2.0f);
}
int main(int argc, char** argv) {
try {
int device = argc > 1 ? atoi(argv[1]) : 0;
af::setDevice(device);
array bimodal =
loadImage(ASSETS_DIR "/examples/images/noisy_square.png", false);
bimodal = resize(0.75f, bimodal);
array bt = threshold(bimodal, 180.0f);
array ot = otsu(bimodal);
array bimodHist = histogram(bimodal, 256, 0, 255);
array smooth = convolve(bimodal, gaussianKernel(5, 5));
array smoothHist = histogram(smooth, 256, 0, 255);
af::Window wnd(1536, 1024, "Binary Thresholding Algorithms");
printf("Press ESC while the window is in focus to proceed to exit\n");
wnd.grid(3, 3);
wnd(0, 1).setAxesTitles("Bins", "Frequency");
wnd(1, 1).setAxesTitles("Bins", "Frequency");
wnd(2, 1).setAxesTitles("Bins", "Frequency");
while (!wnd.close()) {
wnd(0, 0).image(bimodal / 255, "Input Image");
wnd(1, 0).image(bimodal / 255, "Input Image");
wnd(2, 0).image(smooth / 255, "Input Smoothed by Gaussian Filter");
wnd(0, 1).hist(bimodHist, 0, 255, "Input Histogram");
wnd(1, 1).hist(bimodHist, 0, 255, "Input Histogram");
wnd(2, 1).hist(smoothHist, 0, 255, "Smoothed Input Histogram");
wnd(0, 2).image(bt, "Simple Binary threshold");
wnd(1, 2).image(ot, "Otsu's Threshold");
wnd(2, 2).image(otsu(smooth), "Otsu's Threshold on Smoothed Image");
wnd.show();
}
} catch (af::exception& e) {
fprintf(stderr, "%s\n", e.what());
throw;
}
return 0;
}
af::accum
AFAPI array accum(const array &in, const int dim=0)
C++ Interface for computing the cumulative sum (inclusive) of an array.
af::range
AFAPI array range(const dim4 &dims, const int seq_dim=-1, const dtype ty=f32)
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::setDevice
AFAPI void setDevice(const int device)
Sets the current device.
af::array::scalar
T scalar() const
Get the first element of the array as a scalar.
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::max
AFAPI array max(const array &in, const int dim=-1)
C++ Interface for maximum values in an array.
af::array::elements
dim_t elements() const
Get the total number of elements across all dimensions of the array.
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_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::array::copy
array copy() const
Perform deep copy of the array.
AF_GRAY
@ AF_GRAY
Grayscale.
Definition: defines.h:340
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
af::resize
AFAPI array resize(const array &in, const dim_t odim0, const dim_t odim1, const interpType method=AF_INTERP_NEAREST)
C++ Interface for resizing an image to specified dimensions.
af::histogram
AFAPI array histogram(const array &in, const unsigned nbins, const double minval, const double maxval)
C++ Interface for histogram.