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
|
/*******************************************************
* Copyright (c) 2014, 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 <stdio.h>
#include <arrayfire.h>
#include <af/util.h>
#include <cstdlib>
using namespace af;
array morphopen(const array& img, const array& mask)
{
return dilate(erode(img, mask), mask);
}
array morphclose(const array& img, const array& mask)
{
return erode(dilate(img, mask), mask);
}
array morphgrad(const array& img, const array& mask)
{
return (dilate(img, mask) - erode(img, mask));
}
array tophat(const array& img, const array& mask)
{
return (img - morphopen(img, mask));
}
array bottomhat(const array& img, const array& mask)
{
return (morphclose(img, mask) - img);
}
array border(const array& img, const int left, const int right,
const int top, const int bottom,
const float value = 0.0)
{
if((int)img.dims(0) < (top + bottom))
std::cerr << "input does not have enough rows" << std::endl;
if((int)img.dims(1) < (left + right))
std::cerr << "input does not have enough columns" << std::endl;
dim4 imgDims = img.dims();
array ret = constant(value, imgDims);
ret(seq(top, imgDims[0]-bottom), seq(left, imgDims[1]-right), span, span) =
img(seq(top, imgDims[0]-bottom), seq(left, imgDims[1]-right), span, span);
return ret;
}
array border(const array& img, const int w, const int h,
const float value = 0.0)
{
return border(img, w, w, h, h, value);
}
array border(const array& img, const int size, const float value = 0.0)
{
return border(img, size, size, size, size, value);
}
array blur(const array& img, const array mask = gaussianKernel(3,3))
{
array blurred = array(img.dims(), img.type());
for(int i = 0; i < (int)blurred.dims(2); i++)
blurred(span, span, i) = convolve(img(span, span, i), mask);
return blurred;
}
// Demonstrates various image morphing manipulations.
static void morphing_demo()
{
af::Window wnd(1280, 720, "Morphological Operations");
// load images
array img_rgb = loadImage(ASSETS_DIR "/examples/images/man.jpg", true) / 255.f; // 3 channel RGB [0-1]
array mask = constant(1, 5, 5);
array er = erode(img_rgb, mask);
array di = dilate(img_rgb, mask);
array op = morphopen(img_rgb, mask);
array cl = morphclose(img_rgb, mask);
array gr = morphgrad(img_rgb, mask);
array th = tophat(img_rgb, mask);
array bh = bottomhat(img_rgb, mask);
array bl = blur(img_rgb, gaussianKernel(5,5));
array bp = border(img_rgb, 20, 30, 40, 50, 0.5);
array bo = border(img_rgb, 20);
while (!wnd.close()) {
wnd.grid(3, 4);
wnd(0, 0).image(img_rgb, "Input" );
wnd(1, 0).image(er , "Erosion" );
wnd(2, 0).image(di , "Dilation" );
wnd(0, 1).image(op , "Opening" );
wnd(1, 1).image(cl , "Closing" );
wnd(2, 1).image(gr , "Gradient" );
wnd(0, 2).image(th , "TopHat" );
wnd(1, 2).image(bh , "BottomHat" );
wnd(2, 2).image(bl , "Blur" );
wnd(0, 3).image(bp , "Border to Gray" );
wnd(1, 3).image(bo , "Border to black");
wnd.show();
}
}
int main(int argc, char** argv)
{
int device = argc > 1 ? atoi(argv[1]) : 0;
try {
af::info();
af::setDevice(device);
printf("** ArrayFire Image Morphing Demo **\n\n");
morphing_demo();
} catch (af::exception& e) {
fprintf(stderr, "%s\n", e.what());
throw;
}
return 0;
}
|