00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00047
00048
00049
00050 #ifndef _SIMPLE_TOOLS_TEMPLATES_H
00051 #define _SIMPLE_TOOLS_TEMPLATES_H
00052
00053
00054 #include <stdexcept>
00055
00056 namespace {
00057
00058 template<typename T>
00059 T interpolate_value(const lsseg::Image<T>& img,
00060 int channel,
00061 int x_pixel,
00062 int y_pixel,
00063 int z_pixel,
00064 double x_off,
00065 double y_off,
00066 double z_off,
00067 bool linear);
00068
00069 };
00070
00071 namespace lsseg {
00072
00073
00074 template<typename ImgType>
00075 void downsample_series(const ImgType& input,
00076 std::vector<ImgType >& result,
00077 int min_num_pixels,
00078 bool downscale_z,
00079 double factor,
00080 bool only_grayscale,
00081 bool linear)
00082
00083 {
00084
00085 assert(input.dimx() >= min_num_pixels && input.dimy() >= min_num_pixels);
00086 if (downscale_z) {
00087 assert(input.dimz() >= min_num_pixels);
00088 }
00089 if (only_grayscale) {
00090 assert(input.numChannels() == 1 || input.numChannels() == 3);
00091 }
00092 assert(factor > 1);
00093
00094 result.clear();
00095 result.push_back(input);
00096 if (only_grayscale && result[0].numChannels() != 1) {
00097 assert(result[0].numChannels() == 3);
00098 to_grayscale(result[0]);
00099 }
00100 if (factor <= 1) {
00101 return;
00102 }
00103
00104 int img_size[4];
00105 img_size[0] = result.front().dimx();
00106 img_size[1] = result.front().dimy();
00107 img_size[2] = result.front().dimz();
00108 img_size[3] = result.front().numChannels();
00109
00110 img_size[0] = int(img_size[0] / factor);
00111 img_size[1] = int(img_size[1] / factor);
00112 if (downscale_z) {
00113 img_size[2] = int(img_size[2] / factor);
00114 }
00115 while (img_size[0] >= min_num_pixels &&
00116 img_size[1] >= min_num_pixels &&
00117 (!downscale_z || img_size[2] >= min_num_pixels)) {
00118 result.push_back(ImgType(img_size[0], img_size[1], img_size[2], img_size[3]));
00119 resample_into(result.front(), result.back(), linear);
00120 img_size[0] = int(img_size[0] / factor);
00121 img_size[1] = int(img_size[1] / factor);
00122 if (downscale_z) {
00123 img_size[2] = int(img_size[2] / factor);
00124 }
00125 }
00126 }
00127
00128
00129 template<typename ImgType>
00130 void resample_into(const ImgType& input, ImgType& target, bool linear)
00131
00132 {
00133 assert(target.numChannels() == input.numChannels());
00134 double input_len[3];
00135 double target_len_inv[3];
00136 input_len[0] = input.dimx() - 1;
00137 input_len[1] = input.dimy() - 1;
00138 input_len[2] = input.dimz() - 1;
00139 target_len_inv[0] = (target.dimx() > 1) ? double(1) / (target.dimx() - 1) : 0;
00140 target_len_inv[1] = (target.dimy() > 1) ? double(1) / (target.dimy() - 1) : 0;
00141 target_len_inv[2] = (target.dimz() > 1) ? double(1) / (target.dimz() - 1) : 0;
00142
00143 typename ImgType::value_type *dp = target.begin();
00144
00145 for (int c = 0; c != target.numChannels(); ++c) {
00146 for (int z = 0; z != target.dimz(); ++z) {
00147 const double z_rel_pos = z * target_len_inv[2];
00148 const int z_pix = int(input_len[2] * z_rel_pos);
00149 const double z_off = (input_len[2] * z_rel_pos) - z_pix;
00150 for (int y = 0; y != target.dimy(); ++y) {
00151 const double y_rel_pos = y * target_len_inv[1];
00152 const int y_pix = int(input_len[1] * y_rel_pos);
00153 const double y_off = (input_len[1] * y_rel_pos) - y_pix;
00154 for (int x = 0; x != target.dimx(); ++x) {
00155 const double x_rel_pos = x * target_len_inv[0];
00156 const int x_pix = int(input_len[0] * x_rel_pos);
00157 const double x_off = (input_len[0] * x_rel_pos) - x_pix;
00158 *dp++ = interpolate_value(input, c, x_pix, y_pix, z_pix, x_off, y_off, z_off, linear);
00159 }
00160 }
00161 }
00162 }
00163 }
00164
00165
00166 template<typename T>
00167 void to_grayscale(Image<T>& img)
00168
00169 {
00170 ALWAYS_ERROR_IF(img.numChannels() != 1 &&
00171 img.numChannels() != 3, "Image dimension must be 1 or 3");
00172 if (img.numChannels() == 1) {
00173 return;
00174 }
00175
00176 Image<T> res(img.dimx(), img.dimy(), img.dimz(), 1);
00177 for (int z = 0; z < img.dimz(); ++z) {
00178 for (int y = 0; y < img.dimy(); ++y) {
00179 for (int x = 0; x < img.dimx(); ++x) {
00180 double r = img(x, y, z, 0);
00181 double g = img(x, y, z, 1);
00182 double b = img(x, y, z, 2);
00183 res(x, y, z, 0) = T(0.3 * r + 0.59 * g + 0.11 * b);
00184 }
00185 }
00186 }
00187 img.swap(res);
00188 }
00189
00190 };
00191
00192 namespace {
00193
00194
00195 template<typename T>
00196 T interpolate_value(const lsseg::Image<T>& img,
00197 int ch,
00198 int x_px,
00199 int y_px,
00200 int z_px,
00201 double x_off,
00202 double y_off,
00203 double z_off,
00204 bool linear)
00205
00206 {
00207 if (!linear) {
00208
00209 x_px = (x_off >= 0.5 && x_px < (img.dimx() - 1)) ? x_px + 1 : x_px;
00210 y_px = (y_off >= 0.5 && y_px < (img.dimy() - 1)) ? y_px + 1 : y_px;
00211 z_px = (z_off >= 0.5 && z_px < (img.dimz() - 1)) ? z_px + 1 : z_px;
00212 return img(x_px, y_px, z_px, ch);
00213 }
00214
00215 const int x_top = (x_px < (img.dimx() - 1)) ? x_px + 1 : x_px;
00216 const int y_top = (y_px < (img.dimy() - 1)) ? y_px + 1 : y_px;
00217 const int z_top = (z_px < (img.dimz() - 1)) ? z_px + 1 : z_px;
00218
00219
00220 const T x_mm = x_off * img(x_top, y_px, z_px, ch) + (1 - x_off) * img(x_px, y_px, z_px, ch) ;
00221 const T x_mM = x_off * img(x_top, y_px, z_top, ch) + (1 - x_off) * img(x_px, y_px, z_top, ch) ;
00222 const T x_Mm = x_off * img(x_top, y_top, z_px, ch) + (1 - x_off) * img(x_px, y_top, z_px, ch) ;
00223 const T x_MM = x_off * img(x_top, y_top, z_top, ch) + (1 - x_off) * img(x_px, y_top, z_top, ch) ;
00224
00225 const T y_m = y_off * x_Mm + (1 - y_off) * x_mm;
00226 const T y_M = y_off * x_MM + (1 - y_off) * x_mM;
00227
00228 const T z_res = z_off * y_M + (1 - z_off) * y_m;
00229
00230 return z_res;
00231 }
00232
00233 };
00234
00235 #endif // _SIMPLE_TOOLS_TEMPLATES_H
00236