21 #ifndef mia_core_splineparzenmi_hh 22 #define mia_core_splineparzenmi_hh 24 #include <boost/concept/requires.hpp> 25 #include <boost/concept_check.hpp> 69 template <
typename MovIterator,
typename RefIterator>
70 BOOST_CONCEPT_REQUIRES( ((::boost::ForwardIterator<MovIterator>))
71 ((::boost::ForwardIterator<RefIterator>)),
74 fill(MovIterator mov_begin, MovIterator mov_end,
75 RefIterator ref_begin, RefIterator ref_end);
91 template <
typename MovIterator,
typename RefIterator,
typename MaskIterator>
92 void fill(MovIterator mov_begin, MovIterator mov_end,
93 RefIterator ref_begin, RefIterator ref_end,
94 MaskIterator mask_begin, MaskIterator mask_end);
101 double value()
const;
110 double get_gradient(
double moving,
double reference)
const;
119 double get_gradient_slow(
double moving,
double reference)
const;
126 void fill_histograms(
const std::vector<double>& values,
127 double rmin,
double rmax,
128 double mmin,
double mmax);
131 double scale_moving(
double x)
const;
132 double scale_reference(
double x)
const;
134 void evaluate_histograms();
135 void evaluate_log_cache();
140 size_t m_ref_real_bins;
149 size_t m_mov_real_bins;
155 std::vector<double> m_joined_histogram;
156 std::vector<double> m_ref_histogram;
157 std::vector<double> m_mov_histogram;
159 std::vector<std::vector<double> > m_pdfLogCache;
160 double m_cut_histogram;
162 template <
typename Iterator>
163 std::pair<double,double> get_reduced_range(Iterator begin, Iterator end)
const;
165 template <
typename DataIterator,
typename MaskIterator>
166 std::pair<double,double>
167 get_reduced_range_masked(DataIterator dbegin,
169 MaskIterator mbegin)
const;
173 template <
typename MovIterator,
typename RefIterator>
174 BOOST_CONCEPT_REQUIRES( ((::boost::ForwardIterator<MovIterator>))
175 ((::boost::ForwardIterator<RefIterator>)),
179 RefIterator ref_begin, RefIterator ref_end)
181 std::fill(m_joined_histogram.begin(), m_joined_histogram.end(), 0.0);
183 assert(mov_begin != mov_end);
184 assert(ref_begin != ref_end);
186 if (m_mov_max < m_mov_min) {
188 auto mov_range = get_reduced_range(mov_begin, mov_end);
189 if (mov_range.second == mov_range.first)
190 throw std::invalid_argument(
"relevant moving image intensity range is zero");
191 m_mov_min = mov_range.first;
192 m_mov_max = mov_range.second;
193 m_mov_scale = (m_mov_bins - 1) / (m_mov_max - m_mov_min);
194 cvdebug() <<
"Mov Range = [" << m_mov_min <<
", " << m_mov_max <<
"]\n";
198 if (m_ref_max < m_ref_min) {
199 auto ref_range = get_reduced_range(ref_begin, ref_end);
200 if (ref_range.second == ref_range.first)
201 throw std::invalid_argument(
"relevant reference image intensity range is zero");
203 m_ref_min = ref_range.first;
204 m_ref_max = ref_range.second;
205 m_ref_scale = (m_ref_bins - 1) / (m_ref_max - m_ref_min);
206 cvdebug() <<
"Ref Range = [" << m_ref_min <<
", " << m_ref_max <<
"]\n";
210 std::vector<double> mweights(m_mov_kernel->size());
211 std::vector<double> rweights(m_ref_kernel->size());
214 while (ref_begin != ref_end && mov_begin != mov_end) {
216 const double mov = scale_moving(*mov_begin);
217 const double ref = scale_reference(*ref_begin);
219 const int mov_start = m_mov_kernel->get_start_idx_and_value_weights(mov, mweights) + m_mov_border;
220 const int ref_start = m_ref_kernel->get_start_idx_and_value_weights(ref, rweights) + m_ref_border;
222 for (
size_t r = 0; r < m_ref_kernel->size(); ++r) {
223 auto inbeg = m_joined_histogram.begin() +
224 m_mov_real_bins * (ref_start + r) + mov_start;
225 double rw = rweights[r];
226 std::transform(mweights.begin(), mweights.end(), inbeg, inbeg,
227 [rw](
double mw,
double jhvalue){
return mw * rw + jhvalue;});
235 cvdebug() <<
"CSplineParzenMI::fill: counted " << N <<
" pixels\n";
237 const double nscale = 1.0/N;
238 transform(m_joined_histogram.begin(), m_joined_histogram.end(), m_joined_histogram.begin(),
239 [&nscale](
double jhvalue){
return jhvalue * nscale;});
241 evaluate_histograms();
242 evaluate_log_cache();
246 template <
typename MovIterator,
typename RefIterator,
typename MaskIterator>
248 RefIterator ref_begin, RefIterator ref_end,
249 MaskIterator mask_begin, MaskIterator mask_end)
251 std::fill(m_joined_histogram.begin(), m_joined_histogram.end(), 0.0);
253 assert(mov_begin != mov_end);
254 assert(ref_begin != ref_end);
257 if (mask_begin == mask_end)
258 fill(mov_begin, mov_end, ref_begin, ref_end);
260 if (m_mov_max < m_mov_min) {
263 auto mov_range = get_reduced_range_masked(mov_begin, mov_end, mask_begin);
264 if (mov_range.second == mov_range.first)
265 throw std::invalid_argument(
"relevant moving image intensity range is zero");
266 m_mov_min = mov_range.first;
267 m_mov_max = mov_range.second;
268 m_mov_scale = (m_mov_bins - 1) / (m_mov_max - m_mov_min);
269 cvdebug() <<
"Mov Range = [" << m_mov_min <<
", " << m_mov_max <<
"]\n";
273 if (m_ref_max < m_ref_min) {
275 auto ref_range = get_reduced_range_masked(ref_begin, ref_end, mask_begin);
276 if (ref_range.second == ref_range.first)
277 throw std::invalid_argument(
"relevant reference image intensity range is zero");
279 m_ref_min = ref_range.first;
280 m_ref_max = ref_range.second;
281 m_ref_scale = (m_ref_bins - 1) / (m_ref_max - m_ref_min);
282 cvdebug() <<
"Ref Range = [" << m_ref_min <<
", " << m_ref_max <<
"]\n";
286 std::vector<double> mweights(m_mov_kernel->size());
287 std::vector<double> rweights(m_ref_kernel->size());
290 while (ref_begin != ref_end && mov_begin != mov_end) {
293 const double mov = scale_moving(*mov_begin);
294 const double ref = scale_reference(*ref_begin);
296 const int mov_start = m_mov_kernel->get_start_idx_and_value_weights(mov, mweights) + m_mov_border;
297 const int ref_start = m_ref_kernel->get_start_idx_and_value_weights(ref, rweights) + m_ref_border;
299 for (
size_t r = 0; r < m_ref_kernel->size(); ++r) {
300 auto inbeg = m_joined_histogram.begin() +
301 m_mov_real_bins * (ref_start + r) + mov_start;
302 double rw = rweights[r];
303 std::transform(mweights.begin(), mweights.end(), inbeg, inbeg,
304 [rw](
double mw,
double jhvalue){
return mw * rw + jhvalue;});
314 cvdebug() <<
"CSplineParzenMI::fill: counted " << N <<
" pixels\n";
316 const double nscale = 1.0/N;
317 transform(m_joined_histogram.begin(), m_joined_histogram.end(), m_joined_histogram.begin(),
318 [&nscale](
double jhvalue){
return jhvalue * nscale;});
320 evaluate_histograms();
321 evaluate_log_cache();
324 template <
typename Iterator>
325 std::pair<double,double> CSplineParzenMI::get_reduced_range(Iterator begin, Iterator end)
const 327 auto range = std::minmax_element(begin, end);
332 cvinfo() <<
"CSplineParzenMI: reduce range by "<< m_cut_histogram
333 <<
"% from [" << *range.first <<
", " << *range.second
334 <<
"] to [" << reduced_range.first <<
", " << reduced_range.second <<
"]\n";
335 return std::make_pair(reduced_range.first, reduced_range.second);
339 template <
typename DataIterator,
typename MaskIterator>
340 std::pair<double,double>
341 CSplineParzenMI::get_reduced_range_masked(DataIterator dbegin,
343 MaskIterator mbegin)
const 348 while (! *im && ib != dend) {
354 throw std::runtime_error(
"CSplineParzenMI: empty mask");
356 double range_max = *ib;
357 double range_min = *ib;
385 cvinfo() <<
"CSplineParzenMI: reduce range by "<< m_cut_histogram
386 <<
"% from [" << range_min <<
", " << range_max
387 <<
"] to [" << reduced_range.first <<
", " << reduced_range.second <<
"]\n";
388 return std::make_pair(reduced_range.first, reduced_range.second);
vstream & cvinfo()
informal output that may be of interest to understand problems with a program and are of higher prior...
void fill(MovIterator mov_begin, MovIterator mov_end, RefIterator ref_begin, RefIterator ref_end)
range_type get_reduced_range(double remove) const
#define NS_MIA_BEGIN
conveniance define to start the mia namespace
Implementation of mutual information based on B-splines.
a simple histogram that uses an instance of THistogramFeeder as input converter
std::shared_ptr< CSplineKernel > PSplineKernel
EXPORT_2D C2DFVectorfield get_gradient(const C2DImage &image)
A class to normalize and quantizize input data to a given histogram range with its given number of bi...
void push(typename Feeder::value_type x)
#define EXPORT_CORE
Macro to manage Visual C++ style dllimport/dllexport.
void push_range(Iterator begin, Iterator end)
#define NS_MIA_END
conveniance define to end the mia namespace