Production de feature-profiles

This commit is contained in:
François Merciol 2018-08-06 10:53:08 +02:00
parent ebdc90f26f
commit c4adb1e225
15 changed files with 175 additions and 68 deletions

View File

@ -2,15 +2,20 @@
Note aux développeurs
** La TODO list
- refaire le tableau des exemples de traces (./result/BuildSteps.ods)
- vérifier min et max apla tos
- copier les valeurs de géolocalisation (de input vers output)
- vérifier coupure (avec sens de la monotonie)
- faire un omega-tree
- faire coupures suivant (A>, W<>, SD>, MOI>)
- sort W thresholds
- faire les features-profiles (L, mean, SD, A, MOI)
- vérifier production windows
- refaire le tableau des exemples de traces (./result/BuildSteps.ods)
- vérifier min et max apla tos
- faire un omega-tree
- faire des tests de perf pour algo parallèle
** Fonctions intégré depuis la dernière version
- copier les valeurs de géolocalisation (de input vers output)
** Infos concernant le pattern de git de Triskele
Triskele suit partiellement le [[https://nvie.com/posts/a-successful-git-branching-model/][modèle gitflow]] pour son développement en conservant certaines branches :

View File

@ -16,6 +16,7 @@ namespace otb {
using namespace otb::triskele::arrayTree;
// ========================================
enum FeatureType { AP, MEAN, SD, AREA, MOI };
class Option {
public:
@ -30,10 +31,9 @@ namespace otb {
vector<double> levelThresholds, sdThresholds, moiThresholds;
unsigned int coreCount = boost::thread::hardware_concurrency ();
bool maxTreeFlag = false, minTreeFlag = false, tosTreeFlag = false, alphaTreeFlag = false;
bool averageFlag = false;
bool border = false, oneBand = false;
Connectivity connectivity = Connectivity::C4;
FeatureType featureType = FeatureType::AP;
Option ();
Option (int argc, char** argv);

View File

@ -220,8 +220,8 @@ ArrayTreeBuilder<WeightT, PixelT>::buildTree (Tree &tree, const WeightFunct &wei
lonelyPixelCount++;
if (weightFunct.isWeightInf (topWeight, pixelWeight))
topWeight = pixelWeight;
}
});
}
});
});
for (unsigned int tileId = 0; tileId < tileCount; ++tileId) {
childCount [rootId] += lonelyPixelsCount [tileId];

View File

@ -29,6 +29,8 @@ namespace otb {
/* Définit le type d'arbre à construire */
enum TreeType { MIN, MAX, TOS, ALPHA, TreeTypeCard};
inline bool getDecrFromTreetype (TreeType treeType);
/*! Définit les noms des connectivités (utile pour le debug) */
extern string connectivityName[];

View File

@ -1,6 +1,14 @@
#ifndef _OTB_TRISKELE_ARRAY_TREE_BASE_TPP
#define _OTB_TRISKELE_ARRAY_TREE_BASE_TPP
inline bool
getDecrFromTreetype (TreeType treeType) {
switch (treeType) {
case MIN: return true;
}
return false;
}
inline ostream &
operator << (ostream &out, const Connectivity &c) {
BOOST_ASSERT (c >= 0 && c < 4);

View File

@ -16,6 +16,9 @@ namespace otb {
inline PixelT *getValues ();
inline const PixelT *getValues () const;
template<typename WeightT>
inline void setValues (const PixelT defaultValue, const WeightT *weights);
template<typename WeightT>
inline void setValues (const PixelT *pixels, const WeightT *weights);

View File

@ -36,6 +36,19 @@ AttributeProfiles<PixelT>::getValues () const {
}
// ========================================
template<typename PixelT>
template<typename WeightT>
inline void
AttributeProfiles<PixelT>::setValues (const PixelT defaultValue, const WeightT *weights) {
updateTranscient ();
fill_n (&values[0], tree.getLeafCount (), defaultValue);
PixelT *compAP = &values[tree.getLeafCount ()];
dealThreadBound (tree.getCompCount (), tree.getCoreCount (), [&compAP, &weights] (const DimImg &minVal, const DimImg &maxVal) {
for (DimImg compIdx = minVal; compIdx < maxVal; ++compIdx)
compAP[compIdx] = weights[compIdx];
});
}
template<typename PixelT>
template<typename WeightT>
inline void

View File

@ -13,7 +13,7 @@ namespace otb {
template<typename WeightT>
class WeightAttributes : public CompAttribute<WeightT> {
public:
inline WeightAttributes (const Tree &tree);
inline WeightAttributes (const Tree &tree, const bool &decr);
inline ~WeightAttributes ();
inline void setWeightBounds (Tree &tree);

View File

@ -5,8 +5,8 @@ using namespace boost::chrono;
template<typename WeightT>
inline
WeightAttributes<WeightT>::WeightAttributes (const Tree &tree)
: CompAttribute<WeightT> (tree) {
WeightAttributes<WeightT>::WeightAttributes (const Tree &tree, const bool &decr)
: CompAttribute<WeightT> (tree, decr) {
}
template<typename WeightT>
@ -48,7 +48,10 @@ inline void
WeightAttributes<WeightT>::cut (vector<vector<PixelT> > &allBands, const AttributeProfiles<PixelT> &attributeProfiles,
const vector<WeightT> &thresholds) const {
auto start = high_resolution_clock::now ();
CompAttribute<WeightT>::cut (allBands, attributeProfiles, 0., thresholds);
vector<WeightT> orderedThresholds (thresholds);
if (CompAttribute<WeightT>::decr)
reverse (orderedThresholds.begin (), orderedThresholds.end ());
CompAttribute<WeightT>::cut (allBands, attributeProfiles, 0., orderedThresholds);
globalTreeStats.addTime (filteringStats, duration_cast<duration<double> > (high_resolution_clock::now ()-start).count ());
}

View File

@ -17,13 +17,14 @@ namespace otb {
static inline vector<AttrT> getScaledThresholds (const vector<double> &thresholds, const AttrT &maxValue);
static inline vector<AttrT> getConvertedThresholds (const vector<double> &thresholds);
inline CompAttribute (const Tree &tree);
inline CompAttribute (const Tree &tree, const bool &decr = false);
inline ~CompAttribute ();
inline void updateTranscient ();
inline const AttrT *getValues () const;
inline AttrT *getValues ();
inline AttrT getMaxValue () const;
inline bool getDecr () const;
template<typename PixelT>
inline void cut (vector<vector<PixelT> > &allBands, const AttributeProfiles<PixelT> &attributeProfiles,
@ -39,6 +40,7 @@ namespace otb {
const Tree &tree;
DimNodeId leafCount;
vector<AttrT> values;
bool decr;
inline void free ();
inline void book (const DimImg &leafCount);

View File

@ -23,10 +23,12 @@ CompAttribute<AttrT>::getConvertedThresholds (const vector<double> &thresholds)
// ========================================
template<typename AttrT>
inline
CompAttribute<AttrT>::CompAttribute (const Tree &tree)
CompAttribute<AttrT>::CompAttribute (const Tree &tree, const bool &decr)
: tree (tree),
leafCount (0),
values () {
values (),
decr (decr)
{
updateTranscient ();
}
@ -88,6 +90,7 @@ CompAttribute<AttrT>::cutOnPos (vector<vector<PixelT> > &allBands, const Attribu
DimImg parentId = CompAttribute<AttrT>::tree.getLeafParent (leafId);
DimChanel thresholdsSize = thresholds.size ();
if (parentId == DimImg_MAX) {
// border case
for (DimChanel chanel = 0; chanel < thresholdsSize; ++chanel)
allBands[chanel][leafId] = 0;
return;
@ -105,9 +108,17 @@ CompAttribute<AttrT>::cutOnPos (vector<vector<PixelT> > &allBands, const Attribu
DimImg rootId = CompAttribute<AttrT>::tree.getCompRoot ();
for (DimChanel chanel = 0; chanel < thresholdsSize; ++chanel) {
AttrT ceil = thresholds[chanel];
for ( ; curValue < ceil && curId < rootId; ) {
for ( ; curId < rootId; ) {
if (decr) {
if (curValue < ceil)
break;
} else {
if (curValue > ceil)
break;
}
if (parentId == DimImg_MAX || curId >= parentId) {
// cerr << "CompAttribute::cutOnPos find sub-root:" << rootId << " rootId:" << rootId << endl;
// find root
for (; chanel < thresholdsSize; ++chanel)
allBands[chanel][leafId] = curValue;
return;

View File

@ -49,11 +49,13 @@ namespace triskele {
inline const bool isRead () const;
inline const bool isEmpty () const;
IImage (const std::string &imageFileName = "");
~IImage ();
IImage (const std::string &imageFileName = "");
~IImage ();
void readImage ();
void createImage (const Size &size, const GDALDataType &dataType, const DimChanel &nbOutputBands);
void createImage (const Size &size, const GDALDataType &dataType, const DimChanel &nbOutputBands,
const IImage &inputImage, const Point &topLeft);
void close ();
template<typename PixelT>

View File

@ -99,6 +99,7 @@ Option::parse (int argc, char** argv) {
long left = -1, top = -1, width = -1, height = -1;
string areaThresholdsName, levelThresholdsName, sdThresholdsName, moiThresholdsName;
bool c4 = false, c6p = false, c6n = false, c8 = false;
bool weightFlag = false, meanFlag = false, sdFlag = false, areaFlag = false, moiFlag;
try {
desc.add_options ()
("help", po::bool_switch (&helpFlag), "produce this help message")
@ -129,11 +130,17 @@ Option::parse (int argc, char** argv) {
("tos-tree", po::bool_switch (&tosTreeFlag), "build tree-of-shape")
("alpha-tree", po::bool_switch (&alphaTreeFlag), "build alpha-tree")
("average", po::bool_switch (&averageFlag), "produce average profiles")
("level,L", po::value<string> (&levelThresholdsName), "produce level attributs")
("area,A", po::value<string> (&areaThresholdsName), "produce area attributs")
("standard-deviation,S", po::value<string> (&sdThresholdsName), "produce standard deviation attributs")
("moment-of-inertia,M", po::value<string> (&moiThresholdsName), "produce moment of inertia attributs")
("f-weight", po::bool_switch (&weightFlag), "produce attribut profiles (default)")
// ("f-level,FPL", po::bool_switch (&weightFlag), "produce feature profiles level")
("f-mean", po::bool_switch (&meanFlag), "produce feature profiles mean")
("f-SD", po::bool_switch (&sdFlag), "produce feature profiles SD")
("f-area", po::bool_switch (&areaFlag), "produce feature profiles area")
("f-MOI", po::bool_switch (&moiFlag), "produce feature profiles area")
("area,A", po::value<string> (&areaThresholdsName), "cut according area attributs")
("weight,W", po::value<string> (&levelThresholdsName), "cut according level attributs")
("standard-deviation,S", po::value<string> (&sdThresholdsName), "cut according standard deviation attributs")
("moment-of-inertia,M", po::value<string> (&moiThresholdsName), "cut according moment of inertia attributs")
;
hide.add_options ()
("use-the-force-luke", po::bool_switch (&useTheForceLuke), "display hidded options")
@ -247,6 +254,20 @@ Option::parse (int argc, char** argv) {
else
connectivity = Connectivity::C4;
int featureCount = weightFlag + meanFlag + sdFlag + areaFlag + moiFlag;
if (featureCount > 1)
usage ("You must choose only one feature attribut profile");
if (meanFlag)
featureType = FeatureType::MEAN;
if (sdFlag)
featureType = FeatureType::SD;
if (areaFlag)
featureType = FeatureType::AREA;
if (moiFlag)
featureType = FeatureType::MOI;
else
featureType = FeatureType::AP;
cout
<< "Input:" << inputFileName << " " << orgSize << " (" << bandInputCount << " chanels of " << GDALGetDataTypeName (inputType) << ")" << endl
<< "Crop topLeft:" << topLeft << " size:" << size << " band:" << selectedBand << endl

View File

@ -93,6 +93,17 @@ IImage::createImage (const Size &size, const GDALDataType &dataType, const DimCh
LOG("gdalCount: " << gdalCount);
}
void
IImage::createImage (const Size &size, const GDALDataType &dataType, const DimChanel &nbBands,
const IImage &inputImage, const Point &topLeft)
{
createImage (size, dataType, nbBands);
string projectionRef;
vector<double> geoTransform;
inputImage.getGeo (projectionRef, geoTransform);
setGeo (projectionRef, geoTransform, topLeft);
}
void
IImage::close () {
DEF_LOG ("IImage::close", "fileName: " << fileName);

View File

@ -31,9 +31,9 @@
using namespace otb::triskele;
using namespace otb::triskele::arrayTree;
template<typename PixelT>
template<typename OutPixelT>
inline void
writeBand (Option &option, PixelT *pixels, DimChanel band) {
writeBand (Option &option, const GDALDataType &outDataType, OutPixelT *pixels, DimChanel band) {
if (!option.oneBand) {
option.outputImage.writeBand (pixels, band);
return;
@ -44,20 +44,15 @@ writeBand (Option &option, PixelT *pixels, DimChanel band) {
ostringstream fileNameStream;
fileNameStream << outputBaseName << "-" << std::setfill ('0') << std::setw (3) << (band) << outputExtension;
IImage outputImage (fileNameStream.str ());
outputImage.createImage (option.size, option.inputImage.getDataType (), 1);
// XXX en double
string projectionRef;
vector<double> geoTransform;
option.inputImage.getGeo (projectionRef, geoTransform);
outputImage.setGeo (projectionRef, geoTransform, option.topLeft);
outputImage.createImage (option.size, outDataType, 1, option.inputImage, option.topLeft);
outputImage.writeBand (pixels, 0);
}
template<typename PixelT>
template<typename InPixelT, typename OutPixelT, typename APFunct>
inline
void apGenerator (Option &option) {
void apGenerator (Option &option, const GDALDataType &outDataType, const APFunct &setAP) {
vector<TreeType> treeTypes;
if (option.minTreeFlag)
@ -76,19 +71,15 @@ void apGenerator (Option &option) {
GraphWalker graphWalker (border);
DimImg leafCount = graphWalker.vertexMaxCount ();
DimChanel maxThresholds = max (max (max (option.areaThresholds.size (), option.levelThresholds.size ()), option.sdThresholds.size ()), option.moiThresholds.size ());
vector <vector <PixelT> > allBands (maxThresholds, vector<PixelT> (leafCount, 0));
vector <vector <OutPixelT> > allBands (maxThresholds, vector<OutPixelT> (leafCount, 0));
DimChanel outputBandsCard = option.selectedBand.getSet ().size ()*(1+treeTypesCard*(option.areaThresholds.size ()+option.levelThresholds.size ()+option.sdThresholds.size ()+option.moiThresholds.size ()));
if (!option.oneBand) {
option.outputImage.createImage (option.size, option.inputImage.getDataType (), outputBandsCard);
// XXX en double
string projectionRef;
vector<double> geoTransform;
option.inputImage.getGeo (projectionRef, geoTransform);
option.outputImage.setGeo (projectionRef, geoTransform, option.topLeft);
option.outputImage.createImage (option.size, outDataType, outputBandsCard,
option.inputImage, option.topLeft);
}
Raster<PixelT> raster;
Raster<InPixelT> raster;
if (option.border) {
DimChanel bandCount (option.inputImage.getBandCount ()); // -1); // XXX sans NDVI
for (DimChanel band = 0; band < bandCount; ++band) {
@ -103,46 +94,43 @@ void apGenerator (Option &option) {
DimChanel chanel = 0;
for (DimChanel band : option.selectedBand.getSet ()) {
option.inputImage.readBand (raster, band, option.topLeft, option.size);
writeBand (option, raster.getPixels (), chanel++);
writeBand (option, outDataType, raster.getPixels (), chanel++);
for (TreeType treeType : treeTypes) {
ArrayTreeBuilder<PixelT, PixelT> atb (raster, graphWalker, treeType, option.countingSortCeil);
ArrayTreeBuilder<InPixelT, InPixelT> atb (raster, graphWalker, treeType, option.countingSortCeil);
Tree tree (option.coreCount);
WeightAttributes<PixelT> weightAttributes (tree);
WeightAttributes<InPixelT> weightAttributes (tree, getDecrFromTreetype (treeType));
atb.buildTree (tree, weightAttributes);
AttributeProfiles<PixelT> attributeProfiles (tree);
AttributeProfiles<OutPixelT> attributeProfiles (tree);
AreaAttributes areaAttributes (tree);
AverageAttributes averageAttributes (tree, raster, areaAttributes);
if (option.averageFlag)
attributeProfiles.setValues (raster.getPixels (), averageAttributes.getValues ());
else
atb.setAttributProfiles (attributeProfiles);
setAP (tree, atb, attributeProfiles, raster, averageAttributes, areaAttributes);
if (option.levelThresholds.size ()) {
vector<PixelT> thresholds (weightAttributes.getConvertedThresholds (option.levelThresholds));
vector<InPixelT> thresholds (weightAttributes.getConvertedThresholds (option.levelThresholds));
weightAttributes.cut (allBands, attributeProfiles, thresholds);
for (DimChanel c = 0; c < option.levelThresholds.size (); ++c, ++chanel)
writeBand (option, &allBands[c][0], chanel);
writeBand (option, outDataType, &allBands[c][0], chanel);
}
if (option.areaThresholds.size ()) {
areaAttributes.cut (allBands, attributeProfiles, option.areaThresholds);
for (DimChanel c = 0; c < option.areaThresholds.size (); ++c, ++chanel)
writeBand (option, &allBands[c][0], chanel);
writeBand (option, outDataType, &allBands[c][0], chanel);
}
if (option.sdThresholds.size ()) {
SDAttributes sdAttributes (tree, areaAttributes);
sdAttributes.cut (allBands, attributeProfiles, option.sdThresholds);
for (DimChanel c = 0; c < option.sdThresholds.size (); ++c, ++chanel)
writeBand (option, &allBands[c][0], chanel);
writeBand (option, outDataType, &allBands[c][0], chanel);
}
if (option.moiThresholds.size ()) {
XYAttributes xyAttributes (tree, areaAttributes);
MoIAttributes moiAttributes (tree, areaAttributes, xyAttributes);
moiAttributes.cut (allBands, attributeProfiles, option.moiThresholds);
for (DimChanel c = 0; c < option.moiThresholds.size (); ++c, ++chanel)
writeBand (option, &allBands[c][0], chanel);
writeBand (option, outDataType, &allBands[c][0], chanel);
}
}
}
@ -152,6 +140,45 @@ void apGenerator (Option &option) {
<< globalTreeStats.printTime ();
}
template<typename InPixelT>
inline
void outTypeSelection (Option &option) {
switch (option.featureType) {
case MEAN:
apGenerator<InPixelT, InPixelT> (option, option.inputImage.getDataType (),
[] (Tree &tree, ArrayTreeBuilder<InPixelT, InPixelT> &atb, AttributeProfiles<InPixelT> &attributeProfiles, Raster<InPixelT> &raster, AverageAttributes &averageAttributes, AreaAttributes &areaAttributes) {
attributeProfiles.setValues (raster.getPixels (), averageAttributes.getValues ());
});
break;
case AREA:
apGenerator<InPixelT, DimImg> (option, GDT_UInt32,
[] (Tree &tree, ArrayTreeBuilder<InPixelT, InPixelT> &atb, AttributeProfiles<DimImg> &attributeProfiles, Raster<InPixelT> &raster, AverageAttributes &averageAttributes, AreaAttributes &areaAttributes) {
attributeProfiles.setValues (1, areaAttributes.getValues ());
});
break;
case SD:
apGenerator<InPixelT, double> (option, GDT_Float64,
[] (Tree &tree, ArrayTreeBuilder<InPixelT, InPixelT> &atb, AttributeProfiles<double> &attributeProfiles, Raster<InPixelT> &raster, AverageAttributes &averageAttributes, AreaAttributes &areaAttributes) {
SDAttributes sdAttributes (tree, areaAttributes);
attributeProfiles.setValues (0., sdAttributes.getValues ());
});
break;
case MOI:
apGenerator<InPixelT, double> (option, GDT_Float64,
[] (Tree &tree, ArrayTreeBuilder<InPixelT, InPixelT> &atb, AttributeProfiles<double> &attributeProfiles, Raster<InPixelT> &raster, AverageAttributes &averageAttributes, AreaAttributes &areaAttributes) {
XYAttributes xyAttributes (tree, areaAttributes);
MoIAttributes moiAttributes (tree, areaAttributes, xyAttributes);
attributeProfiles.setValues (0., moiAttributes.getValues ());
});
break;
default:
apGenerator<InPixelT, InPixelT> (option, option.inputImage.getDataType (),
[] (Tree &tree, ArrayTreeBuilder<InPixelT, InPixelT> &atb, AttributeProfiles<InPixelT> &attributeProfiles, Raster<InPixelT> &raster, AverageAttributes &averageAttributes, AreaAttributes &areaAttributes) {
atb.setAttributProfiles (attributeProfiles);
});
}
}
int
main (int argc, char** argv, char** envp) {
Option option (argc, argv);
@ -159,20 +186,19 @@ main (int argc, char** argv, char** envp) {
switch (option.inputImage.getDataType ()) {
case GDT_Byte:
apGenerator<uint8_t> (option); break;
case GDT_UInt16:
apGenerator<uint16_t> (option); break;
case GDT_Int16:
apGenerator<int16_t> (option); break;
case GDT_UInt32:
apGenerator<uint32_t> (option); break;
case GDT_Int32:
apGenerator<int32_t> (option); break;
case GDT_Float32:
apGenerator<float> (option); break;
case GDT_Float64:
apGenerator<double> (option); break;
outTypeSelection<uint8_t> (option); break;
case GDT_UInt16:
outTypeSelection<uint16_t> (option); break;
case GDT_Int16:
outTypeSelection<int16_t> (option); break;
case GDT_UInt32:
outTypeSelection<uint32_t> (option); break;
case GDT_Int32:
outTypeSelection<int32_t> (option); break;
case GDT_Float32:
outTypeSelection<float> (option); break;
case GDT_Float64:
outTypeSelection<double> (option); break;
default :
cerr << "unknown type!" << endl; break;