void TolerantEditDistance::extractCells() { if (_groundTruth->size() != _reconstruction->size()) BOOST_THROW_EXCEPTION(SizeMismatchError() << error_message("ground truth and reconstruction have different size") << STACK_TRACE); if (_groundTruth->height() != _reconstruction->height() || _groundTruth->width() != _reconstruction->width()) BOOST_THROW_EXCEPTION(SizeMismatchError() << error_message("ground truth and reconstruction have different size") << STACK_TRACE); _depth = _groundTruth->size(); _width = _groundTruth->width(); _height = _groundTruth->height(); LOG_ALL(tedlog) << "extracting cells in " << _width << "x" << _height << "x" << _depth << " volume" << std::endl; vigra::MultiArray<3, std::pair<float, float> > gtAndRec(vigra::Shape3(_width, _height, _depth)); vigra::MultiArray<3, unsigned int> cellIds(vigra::Shape3(_width, _height, _depth)); // prepare gt and rec image for (unsigned int z = 0; z < _depth; z++) { boost::shared_ptr<Image> gt = (*_groundTruth)[z]; boost::shared_ptr<Image> rec = (*_reconstruction)[z]; for (unsigned int x = 0; x < _width; x++) for (unsigned int y = 0; y < _height; y++) { float gtLabel = (*gt)(x, y); float recLabel = (*rec)(x, y); gtAndRec(x, y, z) = std::make_pair(gtLabel, recLabel); } } // find connected components in gt and rec image cellIds = 0; _numCells = vigra::labelMultiArray(gtAndRec, cellIds); LOG_DEBUG(tedlog) << "found " << _numCells << " cells" << std::endl; // let tolerance function extract cells from that _toleranceFunction->extractCells( _numCells, cellIds, *_reconstruction, *_groundTruth); LOG_ALL(tedlog) << "found " << _toleranceFunction->getGroundTruthLabels().size() << " ground truth labels and " << _toleranceFunction->getReconstructionLabels().size() << " reconstruction labels" << std::endl; }
void VariationOfInformation::updateOutputs() { // set output if (!_errors) _errors = new VariationOfInformationErrors(); if (_headerOnly) return; if (_reconstruction->size() != _groundTruth->size()) BOOST_THROW_EXCEPTION(SizeMismatchError() << error_message("image stacks have different size") << STACK_TRACE); // count label occurences _p1.clear(); _p2.clear(); _p12.clear(); ImageStack::const_iterator i1 = _reconstruction->begin(); ImageStack::const_iterator i2 = _groundTruth->begin(); unsigned int n = 0; for (; i1 != _reconstruction->end(); i1++, i2++) { if ((*i1)->size() != (*i2)->size()) BOOST_THROW_EXCEPTION(SizeMismatchError() << error_message("images have different size") << STACK_TRACE); n += (*i1)->size(); Image::iterator j1 = (*i1)->begin(); Image::iterator j2 = (*i2)->begin(); for (; j1 != (*i1)->end(); j1++, j2++) { if (_ignoreBackground && *j2 == 0) { n--; continue; } _p1[*j1]++; _p2[*j2]++; _p12[std::make_pair(*j1, *j2)]++; } } // normalize for (typename LabelProb::iterator i = _p1.begin(); i != _p1.end(); i++) i->second /= n; for (typename LabelProb::iterator i = _p2.begin(); i != _p2.end(); i++) i->second /= n; for (typename JointLabelProb::iterator i = _p12.begin(); i != _p12.end(); i++) i->second /= n; // compute information // H(stack 1) double H1 = 0.0; // H(stack 2) double H2 = 0.0; double I = 0.0; for(typename LabelProb::const_iterator i = _p1.begin(); i != _p1.end(); i++) H1 -= i->second * std::log2(i->second); for(typename LabelProb::const_iterator i = _p2.begin(); i != _p2.end(); i++) H2 -= i->second * std::log2(i->second); for(typename JointLabelProb::const_iterator i = _p12.begin(); i != _p12.end(); i++) { const float j = i->first.first; const float k = i->first.second; const double pjk = i->second; const double pj = _p1[j]; const double pk = _p2[k]; I += pjk * std::log2( pjk / (pj*pk) ); } // H(stack 1, stack2) double H12 = H1 + H2 - I; // We compare stack1 (reconstruction) to stack2 (groundtruth). Thus, the // split entropy represents the number of splits of regions in stack2 in // stack1, and the merge entropy the number of merges of regions in stack2 // in stack1. // // H(stack 1|stack 2) = H(stack 1, stack 2) - H(stack 2) // (i.e., if I know the ground truth label, how much bits do I need to // infer the reconstructino label?) _errors->setSplitEntropy(H12 - H2); // H(stack 2|stack 1) = H(stack 1, stack 2) - H(stack 1) // (i.e., if I know the reconstruction label, how much bits do I need to // infer the groundtruth label?) _errors->setMergeEntropy(H12 - H1); LOG_DEBUG(variationofinformationlog) << "sum of conditional entropies is " << _errors->getEntropy() << ", which should be equal to " << (H1 + H2 - 2.0*I) << std::endl; }
void VariationOfInformation::updateOutputs() { if (_stack1->size() != _stack2->size()) BOOST_THROW_EXCEPTION(SizeMismatchError() << error_message("image stacks have different size") << STACK_TRACE); // count label occurences _p1.clear(); _p2.clear(); _p12.clear(); ImageStack::const_iterator i1 = _stack1->begin(); ImageStack::const_iterator i2 = _stack2->begin(); unsigned int n = 0; for (; i1 != _stack1->end(); i1++, i2++) { if ((*i1)->size() != (*i2)->size()) BOOST_THROW_EXCEPTION(SizeMismatchError() << error_message("images have different size") << STACK_TRACE); n += (*i1)->size(); Image::iterator j1 = (*i1)->begin(); Image::iterator j2 = (*i2)->begin(); for (; j1 != (*i1)->end(); j1++, j2++) { _p1[*j1]++; _p2[*j2]++; _p12[std::make_pair(*j1, *j2)]++; } } // normalize for (typename LabelProb::iterator i = _p1.begin(); i != _p1.end(); i++) i->second /= n; for (typename LabelProb::iterator i = _p2.begin(); i != _p2.end(); i++) i->second /= n; for (typename JointLabelProb::iterator i = _p12.begin(); i != _p12.end(); i++) i->second /= n; // compute information double H0 = 0.0; double H1 = 0.0; double I = 0.0; for(typename LabelProb::const_iterator i = _p1.begin(); i != _p1.end(); i++) H0 -= i->second * std::log(i->second); for(typename LabelProb::const_iterator i = _p2.begin(); i != _p2.end(); i++) H1 -= i->second * std::log(i->second); for(typename JointLabelProb::const_iterator i = _p12.begin(); i != _p12.end(); i++) { const float j = i->first.first; const float k = i->first.second; const double pjk = i->second; const double pj = _p1[j]; const double pk = _p2[k]; I += pjk * std::log( pjk / (pj*pk) ); } // set output *_variationOfInformation = H0 + H1 - 2.0 * I; // dump to output (useful for redirection into file) LOG_USER(variationofinformationlog) << "# VOI" << std::endl; LOG_USER(variationofinformationlog) << (*_variationOfInformation) << std::endl; }