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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
/* -*- mia-c++ -*-
*
* This file is part of MIA - a toolbox for medical image analysis
* Copyright (c) Leipzig, Madrid 1999-2014 Gert Wollny
*
* MIA is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MIA; if not, see <http://www.gnu.org/licenses/>.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <iostream>
#include <string>
#include <stdexcept>
#include <algorithm>
#include <mia/core/cmdlineparser.hh>
#include <mia/internal/main.hh>
#include <mia/core/msgstream.hh>
#include <mia/2d/filter.hh>
#include <mia/2d/imageio.hh>
using namespace std;
NS_MIA_USE
const SProgramDescription g_general_help = {
{pdi_group, "Analysis, filtering, combining, and segmentation of 2D images"},
{pdi_short, "Distance between binary masks."},
{pdi_description, "This program evaluate the average or maximum distance of a mask "
"given by a binary image to an image representing a distance map "
"and prints the result to stdout. The distance map can be obtained by "
"running the filter 'diatance' on a binary image."},
{pdi_example_descr, "Evaluate the maximum distance of mask m.v by using "
"the distance field distance.v and scale by factor 2.0. The result is "
"written to stdout"},
{pdi_example_code, "-i m.v -d distance.v -s 2.0 -m max"}
};
enum EOps {dist_avg,
dist_max,
dist_unknown
};
const TDictMap<EOps>::Table combine_option_table[] = {
{"avg", dist_avg, "use average"},
{"max", dist_max, "use maximum" },
{NULL, dist_unknown, ""},
};
class Convert2DoubleAndScale: public TFilter<C2DDImage>{
public:
Convert2DoubleAndScale(double scale):_M_scale(scale){
}
template <typename T>
C2DDImage operator ()(const T2DImage<T>& image) const {
C2DDImage result(image.get_size());
transform(image.begin(), image.end(), result.begin(),
[this](T x){return x/_M_scale;});
return result;
}
private:
double _M_scale;
};
class CGetDistance: public TFilter<double> {
public:
CGetDistance(const C2DDImage& dist_field, EOps method):
_M_distance(dist_field),
_M_method(method)
{
}
template <typename T>
CGetDistance::result_type operator()(const T2DImage<T>& image) const
{
auto d = _M_distance.begin();
auto i = image.begin();
auto e = image.end();
switch (_M_method) {
case dist_avg: {
int n = 0;
double result = 0.0;
while (i != e) {
if (*i) {
result += *d;
++n;
}
++d;
++i;
}
return n == 0 ? 0 : result / n;
}
case dist_max: {
double result = 0.0;
while (i != e) {
if (*i)
if (result < *d)
result = *d;
++d;
++i;
}
return result;
}
default:
throw runtime_error("unknown distance measure requested\n");
}
}
private:
const C2DDImage& _M_distance;
EOps _M_method;
};
int do_main( int argc, char *argv[] )
{
string in_filename;
string dist_filename;
float scale = 1.0;
EOps method = dist_avg;
TDictMap<EOps> combine_option(combine_option_table);
const auto& imageio = C2DImageIOPluginHandler::instance();
CCmdOptionList options(g_general_help);
options.add(make_opt( in_filename, "in-file", 'i', "input image",
CCmdOptionFlags::required_input, &imageio));
options.add(make_opt( dist_filename, "distance-file", 'd', "distance field image (floating point)",
CCmdOptionFlags::required_output, &imageio));
options.add(make_opt( scale, "scale", 's', "distance scaling factor"));
options.add(make_opt( method, combine_option, "method", 'm', "distance measuring method"));
if (options.parse(argc, argv) != CCmdOptionList::hr_no)
return EXIT_SUCCESS;
auto in_image = load_image2d(in_filename);
auto dist_image = load_image2d(dist_filename);
Convert2DoubleAndScale create_dist(scale);
C2DDImage dist = mia::filter(create_dist, *dist_image);
CGetDistance get_distance(dist, method);
cout << filter(get_distance, *in_image) <<"\n";
return EXIT_SUCCESS;
}
MIA_MAIN(do_main);
|