image_processing/adaptive_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;
using std::abs;
typedef enum { MEAN = 0, MEDIAN, MINMAX_AVG } LocalThresholdType;
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 adaptiveThreshold(const array &in, LocalThresholdType kind,
int window_size, int constnt) {
int wr = window_size;
array ret_val = colorSpace(in, AF_GRAY, AF_RGB);
if (kind == MEAN) {
array wind = constant(1, wr, wr) / (wr * wr);
array mean = convolve(ret_val, wind);
array diff = mean - ret_val;
ret_val = (diff < constnt) * 0.f + 255.f * (diff > constnt);
} else if (kind == MEDIAN) {
array medf = medfilt(ret_val, wr, wr);
array diff = medf - ret_val;
ret_val = (diff < constnt) * 0.f + 255.f * (diff > constnt);
} else if (kind == MINMAX_AVG) {
array minf = minfilt(ret_val, wr, wr);
array maxf = maxfilt(ret_val, wr, wr);
array mean = (minf + maxf) / 2.0f;
array diff = mean - ret_val;
ret_val = (diff < constnt) * 0.f + 255.f * (diff > constnt);
}
ret_val = 255.f - ret_val;
return ret_val;
}
array iterativeThreshold(const array &in) {
array ret_val = colorSpace(in, AF_GRAY, AF_RGB);
float T = mean<float>(ret_val);
bool isContinue = true;
while (isContinue) {
array region1 = (ret_val > T) * ret_val;
array region2 = (ret_val <= T) * ret_val;
float r1_avg = mean<float>(region1);
float r2_avg = mean<float>(region2);
float tempT = (r1_avg + r2_avg) / 2.0f;
if (abs(tempT - T) < 0.01f) { break; }
T = tempT;
}
return threshold(ret_val, T);
}
int main(int argc, char **argv) {
try {
int device = argc > 1 ? atoi(argv[1]) : 0;
af::setDevice(device);
array sudoku =
loadImage(ASSETS_DIR "/examples/images/sudoku.jpg", true);
array mnt = adaptiveThreshold(sudoku, MEAN, 37, 10);
array mdt = adaptiveThreshold(sudoku, MEDIAN, 7, 4);
array mmt = adaptiveThreshold(sudoku, MINMAX_AVG, 11, 4);
array itt = 255.0f - iterativeThreshold(sudoku);
af::Window wnd("Adaptive Thresholding Algorithms");
printf("Press ESC while the window is in focus to exit\n");
while (!wnd.close()) {
wnd.grid(2, 3);
wnd(0, 0).image(sudoku / 255, "Input");
wnd(1, 0).image(mnt, "Adap. Threshold(Mean)");
wnd(0, 1).image(mdt, "Adap. Threshold(Median)");
wnd(1, 1).image(mmt, "Adap. Threshold(Avg. Min,Max)");
wnd(0, 2).image(itt, "Iterative Threshold");
wnd.show();
}
} catch (af::exception &e) {
fprintf(stderr, "%s\n", e.what());
throw;
}
return 0;
}
af::maxfilt
AFAPI array maxfilt(const array &in, const dim_t wind_length=3, const dim_t wind_width=3, const borderType edge_pad=AF_PAD_ZERO)
C++ Interface for maximum filter.
af::info
AFAPI void info()
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::mean
AFAPI array mean(const array &in, const dim_t dim=-1)
C++ Interface for mean.
af::abs
AFAPI array abs(const array &in)
C++ Interface for absolute value.
af::array
A multi dimensional data container.
Definition: array.h:35
af
Definition: algorithm.h:15
af::medfilt
AFAPI array medfilt(const array &in, const dim_t wind_length=3, const dim_t wind_width=3, const borderType edge_pad=AF_PAD_ZERO)
C++ Interface for median filter.
af::minfilt
AFAPI array minfilt(const array &in, const dim_t wind_length=3, const dim_t wind_width=3, const borderType edge_pad=AF_PAD_ZERO)
C++ Interface for minimum filter.
af::exception
An ArrayFire exception class.
Definition: exception.h:29
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