diff --git a/MMVII/include/MMVII_Bench.h b/MMVII/include/MMVII_Bench.h index 931ad02636..3ad981ce99 100755 --- a/MMVII/include/MMVII_Bench.h +++ b/MMVII/include/MMVII_Bench.h @@ -113,6 +113,8 @@ void BenchGlobImage(cParamExeBench & aParam); ///< Global bench on image void BenchFilterImage1(cParamExeBench & aParam); void BenchFilterLinear(cParamExeBench & aParam); void BenchGeom(cParamExeBench & aParam); +void BenchPlane3D(); +void BenchPlaneInter(); void BenchMapping(cParamExeBench & aParam); void BenchInvertMapping(cParamExeBench & aParam); diff --git a/MMVII/include/MMVII_DeclareAllCmd.h b/MMVII/include/MMVII_DeclareAllCmd.h index f95de67a3c..5ec9d04b41 100755 --- a/MMVII/include/MMVII_DeclareAllCmd.h +++ b/MMVII/include/MMVII_DeclareAllCmd.h @@ -98,6 +98,7 @@ extern cSpecMMVII_Appli TheSpec_TutoSerial; extern cSpecMMVII_Appli TheSpec_TutoFormalDeriv; extern cSpecMMVII_Appli TheSpec_ExportUndistMesIm; extern cSpecMMVII_Appli TheSpecAppliExtractLine; +extern cSpecMMVII_Appli TheSpec_CERN_ImportClino; }; #endif // _MMVII_DeclareAllCmd_H_ diff --git a/MMVII/include/MMVII_Error.h b/MMVII/include/MMVII_Error.h index 0b901462a3..235878b719 100755 --- a/MMVII/include/MMVII_Error.h +++ b/MMVII/include/MMVII_Error.h @@ -30,6 +30,7 @@ namespace MMVII // extern int The_MMVII_DebugLevel = The_MMVII_DebugLevel_InternalError_medium; +// #define The_MMVII_DebugLevel The_MMVII_DebugLevel_BenchError #define The_MMVII_DebugLevel The_MMVII_DebugLevel_InternalError_tiny // #define The_MMVII_DebugLevel The_MMVII_DebugLevel_BenchError // #define The_MMVII_DebugLevel The_MMVII_DebugLevel_UserError diff --git a/MMVII/include/MMVII_ExtractLines.h b/MMVII/include/MMVII_ExtractLines.h index 9d7ea5c525..f655d5c37b 100755 --- a/MMVII/include/MMVII_ExtractLines.h +++ b/MMVII/include/MMVII_ExtractLines.h @@ -10,6 +10,12 @@ class cHoughTransform; template class cImGradWithN; template class cExtractLines; +enum class eCodeHPS +{ + Ok, + LowCumul, + NotFirst +}; class cHoughPS : public cMemCheck { @@ -21,13 +27,16 @@ class cHoughPS : public cMemCheck tREAL8 DistAnglAntiPar(const cHoughPS& aPS2) const; tREAL8 DY(const cHoughPS&) const; tREAL8 Dist(const cHoughPS&,const tREAL8 &aFactTeta=1.0) const; + tSeg2dr SegMoyAntiParal(const cHoughPS& aPS2) const; const cPt2dr & TetaRho() const; ///< Accessor const tREAL8 & Teta() const; ///< Accessor const tREAL8 & Rho() const; ///< Accessor const tSeg & Seg() const ; ///< Accessor cHoughPS * Matched() const; ///< Accessor - const tREAL8 & Cumul() const; ///< Accessor + const tREAL8 & Cumul() const; ///< Accessor + eCodeHPS Code() const ; ///< Accessor + void SetCode(eCodeHPS); ///< Modifior cPt2dr IndTetaRho() const; ///< Teta/Rho in hough accum dynamic @@ -48,6 +57,8 @@ class cHoughPS : public cMemCheck tSeg mSegE; cHoughPS * mMatched; tREAL8 mDistM; + + eCodeHPS mCode; }; @@ -91,9 +102,12 @@ class cHoughTransform tREAL8 aThrMax // threshold on Max, select if Accum > Max * Avg ) const; - /// max the conversion houg-point -> euclidian line + rho teta + /// max the conversion houg-point + value -> euclidian line + rho teta cHoughPS * PtToLine(const cPt3dr &) const; + /// make the conversion seg (oriented) -> hough point + cPt2dr Line2Pt(const tSeg2dr &) const; + const tREAL8 & RhoMax() const; ///< Accessor /// return the angle teta, of a given index/position in hough accumulator inline tREAL8 RInd2Teta(tREAL8 aIndTeta) const {return aIndTeta *mFactI2T;} diff --git a/MMVII/include/MMVII_Geom2D.h b/MMVII/include/MMVII_Geom2D.h index 2eb1f23271..269242f64d 100755 --- a/MMVII/include/MMVII_Geom2D.h +++ b/MMVII/include/MMVII_Geom2D.h @@ -9,6 +9,8 @@ namespace MMVII { +typedef cSegment tSeg2dr; + /** \file MMVII_Geom2D.h \brief contain classes for geometric manipulation, specific to 2D space : @@ -84,6 +86,7 @@ template class cSegment2DCompiled : public cSegmentCompiled public : typedef cPtxd tPt; cSegment2DCompiled(const tPt& aP1,const tPt& aP2); + cSegment2DCompiled(const cSegment&); tPt ToCoordLoc(const tPt&) const; tPt FromCoordLoc(const tPt&) const; Type DistLine(const tPt&) const; ///< distance between the line and the point diff --git a/MMVII/include/MMVII_Geom3D.h b/MMVII/include/MMVII_Geom3D.h index bfbf7db4ca..2df6df3ad9 100755 --- a/MMVII/include/MMVII_Geom3D.h +++ b/MMVII/include/MMVII_Geom3D.h @@ -326,13 +326,20 @@ template class cTriangulation3D : public cTriangulation class cPlane3D { public : + /* --------------------- Static constructor ---------------------------*/ + /// construct with 1 point inside, and 2 vector inside static cPlane3D FromP0And2V(const cPt3dr & aP0,const cPt3dr& aAxeI , const cPt3dr& aAxeJ); + /// construct with 1 point inside, and the normal direction static cPlane3D FromPtAndNormal(const cPt3dr & aP0,const cPt3dr& aAxeK); + /// construct with 3 point inside static cPlane3D From3Point(const cPt3dr & aP0, const cPt3dr & aP1, const cPt3dr &aP2); + + /// Estimate from a set of point, + static std::pair RansacEstimate(const std::vector & aP0,bool AvgOrMax,int aNbTest=-1,tREAL8 aRegulMinTri =1e-3); /// Return the indexes of the "best" plane static std::pair IndexRansacEstimate(const std::vector & aP0,bool AvgOrMax,int aNbTest=-1,tREAL8 aRegulMinTri =1e-3); - static std::pair RansacEstimate(const std::vector & aP0,bool AvgOrMax,int aNbTest=-1,tREAL8 aRegulMinTri =1e-3); + /// Avegrage distance tREAL8 AvgDist(const std::vector &) const; tREAL8 MaxDist(const std::vector &) const; @@ -344,10 +351,19 @@ class cPlane3D // return 3 point for random plane static std::vector RandParam(); - const cPt3dr& AxeI() const; - const cPt3dr& AxeJ() const; - const cPt3dr& AxeK() const; + const cPt3dr& P0() const; ///< Accessor + const cPt3dr& AxeI() const; ///< Accessor + const cPt3dr& AxeJ() const; ///< Accessor + const cPt3dr& AxeK() const; ///< Accessor + + /** Return the intersection of the planes consider as vector space , used eigen decomposition + * to get the best solutuob if Nb>2, if Sz=1 or 0 and aSzMin is Ok, return a random acceptable solution */ + static cPt3dr DirInterPlane(const std::vector& aVPlanes,int aSzMin=2); + static cPt3dr DirInterPlane(const std::vector& aVPlanes,int aSzMin=2); + + static tSeg3dr InterPlane(const std::vector& aVPlanes,int aSzMin=2,tREAL8 aWeithStab=1e-10); + static tSeg3dr InterPlane(const std::vector& aVPlanes,int aSzMin=2,tREAL8 aWeithStab=1e-10); private : cPlane3D(const cPt3dr & aP0,const cPt3dr& aAxeI , const cPt3dr& aAxeJ); cPt3dr mP0; diff --git a/MMVII/include/MMVII_Matrix.h b/MMVII/include/MMVII_Matrix.h index f944391f3d..d0cae53501 100755 --- a/MMVII/include/MMVII_Matrix.h +++ b/MMVII/include/MMVII_Matrix.h @@ -552,7 +552,7 @@ template class cResulSymEigenValue // => mEigenVectors * cDenseMatrix::Diag(mEigenValues) * mEigenVectors.Transpose(); - const cDenseVect & EigenValues() const ; ///< Eigen values + const cDenseVect & EigenValues() const ; ///< Eigen values, in growing order !!! != cResulSVDDecomp const cDenseMatrix & EigenVectors()const ; ///< Eigen vector void SetKthEigenValue(int aK,const Type & aVal) ; ///< Eigen values Type Cond(Type Def=Type(-1)) const ; ///< Conditioning, def value is when all 0, if all0 and Def<0 : Error @@ -571,7 +571,7 @@ template class cResulSVDDecomp cDenseMatrix OriMatr() const; ///< Check the avability to reconstruct original matrix - const cDenseVect & SingularValues() const ; ///< Eigen values + const cDenseVect & SingularValues() const ; ///< Eigen values, in decreasing order !!! != cResulSymEigenValue const cDenseMatrix & MatU()const ; ///< Eigen vector const cDenseMatrix & MatV()const ; ///< Eigen vector // void SetKthEigenValue(int aK,const Type & aVal) ; ///< Eigen values diff --git a/MMVII/include/MMVII_MeasuresIm.h b/MMVII/include/MMVII_MeasuresIm.h index 3d81deb68b..a6f40437a8 100755 --- a/MMVII/include/MMVII_MeasuresIm.h +++ b/MMVII/include/MMVII_MeasuresIm.h @@ -3,6 +3,7 @@ #include "MMVII_Ptxd.h" #include "MMVII_util_tpl.h" +#include "MMVII_Geom2D.h" namespace MMVII { @@ -494,6 +495,30 @@ class cFilterMesIm }; +/** Represent one line anti paral (computed by matching of 2 oriented line anti paral) */ + +class cOneLineAntiParal +{ + public : + cOneLineAntiParal(); + + tSeg2dr mSeg; + tREAL8 mAng; + tREAL8 mWidth; + tREAL8 mCumul; +}; +void AddData(const cAuxAr2007 & anAux,cOneLineAntiParal & anEx); + + +class cLinesAntiParal1Im +{ + public : + std::string mNameIm; + std::string mDirCalib; + std::vector mLines; +}; +void AddData(const cAuxAr2007 & anAux,cLinesAntiParal1Im & anEx); + }; diff --git a/MMVII/include/MMVII_PCSens.h b/MMVII/include/MMVII_PCSens.h index 10735f840f..c90c6bd0f5 100755 --- a/MMVII/include/MMVII_PCSens.h +++ b/MMVII/include/MMVII_PCSens.h @@ -320,6 +320,14 @@ class cPerspCamIntrCalib : public cObj2DelAtEnd, /// For inversion, or sampling point, we need seed that is +- corresponding of sensor midle, befor dist cPt2dr PtSeedInv() const; + /// Let S be a seg in undist space, extend as much as possible while distorted is include in image + tSeg2dr ExtenSegUndistIncluded + ( + const tSeg2dr & aSegInit, + tREAL8 aStepInitRel=0.05, + tREAL8 aStepEnd=1.0, + tREAL8 aRetract=0.0 + ) const; private : /// big object, no valuable copy cPerspCamIntrCalib(const cPerspCamIntrCalib &) = delete; diff --git a/MMVII/include/MMVII_Ptxd.h b/MMVII/include/MMVII_Ptxd.h index 079eff4c61..46dc72f2df 100755 --- a/MMVII/include/MMVII_Ptxd.h +++ b/MMVII/include/MMVII_Ptxd.h @@ -836,6 +836,8 @@ template class cSegment void CompileFoncLinear(Type & aVal,tPt & aVec,const Type &aV1,const Type & aV2) const; const tPt& P1() const; ///< Accessor const tPt& P2() const; ///< Accessor + tPt& P1() ; ///< Accessor + tPt& P2() ; ///< Accessor tPt V12() const; ///< Vector P1->P2 tPt PMil() const; ///< P middle diff --git a/MMVII/include/MMVII_Sensor.h b/MMVII/include/MMVII_Sensor.h index b4f9483306..182bd888c6 100755 --- a/MMVII/include/MMVII_Sensor.h +++ b/MMVII/include/MMVII_Sensor.h @@ -533,6 +533,8 @@ class cPhotogrammetricProject //=================================================================== void SaveMeasureIm(const cSetMesPtOf1Im & aSetM) const; + /// Does the measure exist + bool HasMeasureIm(const std::string & aNameIm,bool InDir=true) const; /// return from Std Dir, can be out in case of reload cSetMesPtOf1Im LoadMeasureIm(const std::string &,bool InDir=true) const; void LoadGCP(cSetMesImGCP&,const std::string & aPatFiltrFile="",const std::string & aFiltrNameGCP="", @@ -564,6 +566,13 @@ class cPhotogrammetricProject cSet2D3D LoadSet32(const std::string & aNameIm) const; void SaveAndFilterAttrEll(const cSetMesPtOf1Im & aSetM,const std::list & ToRem) const ; + + + // --------------- Segment in/out ---------------------------------------- + std::string NameFileLines(const std::string & aNameIm) const; + bool HasFileLines(const std::string & aNameIm) const; + void SaveLines(const cLinesAntiParal1Im &) const; + cLinesAntiParal1Im ReadLines(const std::string & aNameIm) const; //=================================================================== //================== META-DATA ============================== diff --git a/MMVII/include/MMVII_Stringifier.h b/MMVII/include/MMVII_Stringifier.h index dbba580fe8..03aaa1544a 100755 --- a/MMVII/include/MMVII_Stringifier.h +++ b/MMVII/include/MMVII_Stringifier.h @@ -533,6 +533,21 @@ class cCmpSerializer }; */ +static std::string CurFile; /// global var to get context, not proud of that +static int CurLine; /// global var to get context, not proud of that + +template inline Type GetV(std::istringstream & iss) +{ + Type aNum; + iss >> aNum; + if ( iss.rdstate()) + { + MMVII_UnclasseUsEr("Bad reading at line " + ToStr(CurLine) + " of file [" + CurFile + "] , rdstate=" + ToStr((size_t)iss.rdstate())); + } + return aNum; +} + + }; diff --git a/MMVII/include/MMVII_enums.h b/MMVII/include/MMVII_enums.h index a9d7db8fd3..2ea1cf509b 100755 --- a/MMVII/include/MMVII_enums.h +++ b/MMVII/include/MMVII_enums.h @@ -237,6 +237,7 @@ enum class eTyUEr eNoFocaleEqui35, eNoNumberPixel, eNoCameraName, + eMultipleTargetInOneImage, eUnClassedError, eNbVals }; diff --git a/MMVII/include/MMVII_util.h b/MMVII/include/MMVII_util.h index 13e2beb837..5f475e81f4 100755 --- a/MMVII/include/MMVII_util.h +++ b/MMVII/include/MMVII_util.h @@ -47,7 +47,7 @@ class cCarLookUpTable void InitId(char aC1,char aC2); void Chg1C(char aC1,char aC2); - + void InitIdGlob(); inline char Val(const int & aV) const { @@ -67,6 +67,7 @@ class cCarLookUpTable bool mReUsable; ///< If InitId of Chg1C used -> no longer reusable }; + // Indicate if all "word" of list are in KeyList, use aSpace to separate word // Si aMes=="SVP"=> No Error just return false, else aMes is error message bool CheckIntersect(const std::string & aMes,const std::string & aKeyList,const std::string & aList,const std::string & aSpace); diff --git a/MMVII/include/MMVII_util_tpl.h b/MMVII/include/MMVII_util_tpl.h index 7e4420466d..724540cb26 100755 --- a/MMVII/include/MMVII_util_tpl.h +++ b/MMVII/include/MMVII_util_tpl.h @@ -517,6 +517,17 @@ template typename tCont::value_type * KthElem(tCont & aCont,int return nullptr; } +template std::vector VecObj2VecPtr(const std::vector & aVecObj) +{ + std::vector aVPtr; + + for (const auto & aObj : aVecObj) + aVPtr.push_back(&aObj); + + return aVPtr; +} + + /** Used in Metadata, but can be used more generally. * diff --git a/MMVII/include/cMMVII_Appli.h b/MMVII/include/cMMVII_Appli.h index 39c71db68a..3decb767b2 100755 --- a/MMVII/include/cMMVII_Appli.h +++ b/MMVII/include/cMMVII_Appli.h @@ -446,6 +446,7 @@ class cMMVII_Appli : public cMMVII_Ap_NameManip, bool ModeHelp() const; ///< If we are in help mode, don't execute bool ModeArgsSpec() const; ///< If called only to output args specs, don't execute virtual ~cMMVII_Appli(); ///< Always virtual Dstrctr for "big" classes + void ToDoBeforeDestruction(); ///< Some stuff to do at the end, require virtual method that cannot be called in X::~X() bool IsInit(const void *) const; ///< indicate for each variable if it was initiazed by argc/argv bool IsInSpecObl(const void *); ///< indicate for each variable if it was in an arg opt list (used with cPhotogrammetricProject) bool IsInSpecFac(const void *); ///< indicate for each variable if it was in an arg obl list (used with cPhotogrammetricProject) @@ -531,10 +532,15 @@ class cMMVII_Appli : public cMMVII_Ap_NameManip, std::string NameTmpReport(const std::string &anId,const std::string &anImg); void SetReportSubDir(const std::string &); - void InitReport(const std::string &anId,const std::string & aPost,bool IsMul); + /// Mehod called when the report is finished, usefull when the report is used to memorize problem + virtual void OnCloseReport(int aNbLine,const std::string & anIdent,const std::string & aNameFile) const; + + void InitReport(const std::string &anId,const std::string & aPost,bool IsMul,const std::vector & aHeader={}); // void AddTopReport(const std::string &anId,const std::string & VecMsg); void AddOneReportCSV(const std::string &anId,const std::vector & VecMsg); + /// Add a header line, do it only it at top-level + void AddHeaderReportCSV(const std::string &anId,const std::vector & VecMsg); void AddStdHeaderStatCSV(const std::string &anId,const std::string & aNameCol1,const std::vector aVPerc,const std::vector & ={}); void AddStdStatCSV(const std::string &anId,const std::string & aCol1,const cStdStatRes &,const std::vector aVPerc,const std::vector & ={}); diff --git a/MMVII/src/Appli/cMMVII_Appli.cpp b/MMVII/src/Appli/cMMVII_Appli.cpp index 0957483da0..04842de15e 100755 --- a/MMVII/src/Appli/cMMVII_Appli.cpp +++ b/MMVII/src/Appli/cMMVII_Appli.cpp @@ -179,9 +179,15 @@ void cMMVII_Appli::AddObj2DelAtEnd(cObj2DelAtEnd * aPtrO) mVectObj2DelAtEnd.insert(aPtrO); } -cMMVII_Appli::~cMMVII_Appli() +void cMMVII_Appli::ToDoBeforeDestruction() { + // Merge report call virtual methode :q DoMergeReport(); +} + +cMMVII_Appli::~cMMVII_Appli() +{ + // Maybe part, or all, the remaining can/should be done in ToDoBeforeDestruction ... if (mMainAppliInsideP) { for (auto aPtrO : mVectObj2DelAtEnd) @@ -781,8 +787,10 @@ void cMMVII_Appli::InitParam(cGenArgsSpecContext *aArgsSpecs) const std::string & aNameInterval = mIntervFilterMS[aNum]; if (IsInit(&aNameInterval)) { + // JOE cPatternTransfo aPat(mTransfoFFI[aNum]); mVMainSets.at(aNum).Filter(Str2Interv(aNameInterval),aPat); + // mVMainSets.at(aNum).Filter(Str2Interv(aNameInterval)); } } // Test non empty diff --git a/MMVII/src/Appli/cMMVII_Appli_MakeReport.cpp b/MMVII/src/Appli/cMMVII_Appli_MakeReport.cpp index 6352b248b0..301330b700 100755 --- a/MMVII/src/Appli/cMMVII_Appli_MakeReport.cpp +++ b/MMVII/src/Appli/cMMVII_Appli_MakeReport.cpp @@ -31,12 +31,12 @@ std::string cMMVII_Appli::DirSubPReport(const std::string &anId) } -void cMMVII_Appli::InitReport(const std::string &anId,const std::string &aPost,bool IsMul) +void cMMVII_Appli::InitReport(const std::string &anId,const std::string &aPost,bool IsMul,const std::vector & aHeader) { if (IsMul && (LevelCall()==0)) { mReport2Merge.insert(anId); - } + } if (LevelCall()==0) { @@ -54,6 +54,9 @@ void cMMVII_Appli::InitReport(const std::string &anId,const std::string &aPost, mMapIdPostReport[anId] = aPost; cMMVII_Ofs(mMapIdFilesReport[anId], eFileModeOut::CreateText); + + if (! aHeader.empty()) + AddHeaderReportCSV(anId,aHeader); } /* @@ -75,6 +78,13 @@ void cMMVII_Appli::AddOneReport(const std::string &anId,const std::string & aMs aFile.Ofs() << aMsg; } +void cMMVII_Appli::AddHeaderReportCSV(const std::string &anId,const std::vector & aVecMsg) +{ + // Add header line : do handle single or multiple process , do it only if at top-level + if (mLevelCall==0) + AddOneReportCSV(anId,aVecMsg); +} + void cMMVII_Appli::AddOneReportCSV(const std::string &anId,const std::vector & aVecMsg) { MMVII_INTERNAL_ASSERT_tiny(!aVecMsg.empty(),"No file in AddOneMesCSV"); @@ -132,6 +142,7 @@ void cMMVII_Appli::DoMergeReport() cMMVII_Ofs aFileGlob(anIt.second, eFileModeOut::AppendText); const std::string & anId = anIt.first; + int aNbLines = 0; if (mRMSWasUsed) { for (const auto & aNameIm : VectMainSet(0)) @@ -143,13 +154,25 @@ void cMMVII_Appli::DoMergeReport() while (std::getline(aIn.Ifs(), aLine)) { aFileGlob.Ofs() << aLine<< "\n"; + aNbLines++; } } } RemoveRecurs(DirSubPReport(anId),false,false); + OnCloseReport(aNbLines,anIt.first,anIt.second); } } } +// By default nothing to do +void cMMVII_Appli::OnCloseReport(int aNbLine,const std::string & anIdent,const std::string & aNameFile) const +{ +} + + }; + + + + diff --git a/MMVII/src/Appli/cMMVII_CalcSet.cpp b/MMVII/src/Appli/cMMVII_CalcSet.cpp index a312f09319..09e3734c4d 100755 --- a/MMVII/src/Appli/cMMVII_CalcSet.cpp +++ b/MMVII/src/Appli/cMMVII_CalcSet.cpp @@ -178,9 +178,31 @@ int cAppli_EditSet::ExecuteBench(cParamExeBench & aParam) { for (int aK=0 ; aK<2 ; aK++) { + /* + int aNumTest, // Change test condition + const std::string & anOp, // Operator + bool InitInput, // If true, Input is set to last output + const std::string & aPat, // Pattern of image + int aNumAskedOut, // Required num version + int aRealNumOut, // Real Num Version + int ExpectCard, // Number of element required, useless with ExpSet added + const std::string & Interv, // Interval, + const std::string & ExpSet // Expect set + // */ std::string C09="0123456789"; // Basic test, we create the file - OneBenchEditSet(aK,"+=",false,".*txt" ,0,2,10,"",C09); // + OneBenchEditSet + ( + aK, // Change test condition : Use or Not Dir Project + "+=", // operator for mpdi + false, // If true, Previous OutPut is moved on input, else Input is purged at end of process + ".*txt", // Pattern of used files + 0, // Required num version + 2, // Real Num Version + 10, // Number of element expected (become obsolet with expected set) + "", // Interval modifying the pattern if != "" + C09 // Ground truth, what the string should be + ); // OneBenchEditSet(aK,"+=",false,".*txt" ,1,1,10,"",C09); OneBenchEditSet(aK,"+=",false,".*txt" ,2,2,10,"",C09); OneBenchEditSet(aK,"+=",false,"F[02468].txt",2,2,5,"","02468"); diff --git a/MMVII/src/Appli/cSpecMMVII_Appli.cpp b/MMVII/src/Appli/cSpecMMVII_Appli.cpp index 375bfb33f3..89ab560b32 100755 --- a/MMVII/src/Appli/cSpecMMVII_Appli.cpp +++ b/MMVII/src/Appli/cSpecMMVII_Appli.cpp @@ -84,6 +84,7 @@ int cSpecMMVII_Appli::AllocExecuteDestruct(const std::vector & aVAr { CloseRandom(); } + anAppli->ToDoBeforeDestruction(); } cMemManager::CheckRestoration(aMemoState); MMVII_INTERNAL_ASSERT_always(cMemCountable::NbObjLive()==aNbObjLive,"Mem check obj not killed"); @@ -242,6 +243,7 @@ std::vector & cSpecMMVII_Appli::InternVecAll() TheVecAll.push_back(&TheSpec_TutoFormalDeriv); TheVecAll.push_back(&TheSpec_ExportUndistMesIm); TheVecAll.push_back(&TheSpecAppliExtractLine); + TheVecAll.push_back(&TheSpec_CERN_ImportClino); std::sort(TheVecAll.begin(),TheVecAll.end(),CmpCmd); } diff --git a/MMVII/src/Bench/BenchMatrix.cpp b/MMVII/src/Bench/BenchMatrix.cpp index a936845379..d5d832ee08 100755 --- a/MMVII/src/Bench/BenchMatrix.cpp +++ b/MMVII/src/Bench/BenchMatrix.cpp @@ -334,10 +334,10 @@ template void TplBenchDenseMatr(int aSzX,int aSzY) MMVII_INTERNAL_ASSERT_bench(aRSEV.EigenVectors().Unitarity() <1e-5,"Bench unitarity EigenValue"); // Test Eigen value are given in growing order const cDenseVect & aEVals = aRSEV.EigenValues(); - // check decreasing order + // check growing order for (int aK=1 ; aK aCheckEV = aRSEV.OriMatr(); MMVII_INTERNAL_ASSERT_bench(aCheckEV.DIm().L2Dist(aSim.DIm())<1e-5,"Bench unitarity EigenValue"); diff --git a/MMVII/src/BundleAdjustment/cAppliBundAdj.cpp b/MMVII/src/BundleAdjustment/cAppliBundAdj.cpp index 88642a58fd..e6b1892c41 100644 --- a/MMVII/src/BundleAdjustment/cAppliBundAdj.cpp +++ b/MMVII/src/BundleAdjustment/cAppliBundAdj.cpp @@ -304,8 +304,10 @@ int cAppliBundlAdj::Exe() if (IsInit(&mTopoFilePath)) { - bool aTopoOk = mBA.AddTopo(mTopoFilePath); + // Unused in mode release + [[maybe_unused]] bool aTopoOk = mBA.AddTopo(mTopoFilePath); MMVII_INTERNAL_ASSERT_tiny(aTopoOk,"Error reading topo obs file "+mTopoFilePath); + } MMVII_INTERNAL_ASSERT_User(mMeasureAdded,eTyUEr::eUnClassedError,"Not any measure added"); diff --git a/MMVII/src/CodedTarget/cCircTargetExtract.cpp b/MMVII/src/CodedTarget/cCircTargetExtract.cpp index ac544f9dca..98803f8391 100755 --- a/MMVII/src/CodedTarget/cCircTargetExtract.cpp +++ b/MMVII/src/CodedTarget/cCircTargetExtract.cpp @@ -63,6 +63,7 @@ class cCircTargExtr : public cBaseTE bool mMarked4Test; bool mWithCode; cOneEncoding mEncode; + int mCardDetect; // Number of detection , should be 1 .... }; @@ -71,8 +72,9 @@ cCircTargExtr::cCircTargExtr(const cExtractedEllipse & anEE) : mEllipse (anEE.mEllipse), // mVBlack (anEE.mSeed.mBlack), // mVWhite (anEE.mSeed.mWhite), - mMarked4Test (anEE.mSeed.mMarked4Test), - mWithCode (false) + mMarked4Test (anEE.mSeed.mMarked4Test), + mWithCode (false), + mCardDetect (1) // By default, let be optimistic { } @@ -631,6 +633,7 @@ class cAppliExtractCircTarget : public cMMVII_Appli, cCollecSpecArg2007 & ArgOpt(cCollecSpecArg2007 & anArgOpt) override ; int ExeOnParsedBox() override; + void OnCloseReport(int aNbLine,const std::string & anIdent,const std::string & aNameFile) const override; void MakeImageLabel(); @@ -662,6 +665,8 @@ class cAppliExtractCircTarget : public cMMVII_Appli, bool mDoReportSimul; // At glob level is true iff one the sub process is true std::string mReportSimulDet; std::string mReportSimulGlob; + std::string mReportMutipleDetec; // Name for report of multiple detection in on target + double mRatioDMML; cThresholdCircTarget mThresh; @@ -728,11 +733,14 @@ void cAppliExtractCircTarget::DoExport() std::vector mVSavE; for (const auto & anEE : mVCTE) { - std::string aCode = anEE->mWithCode ? anEE->mEncode.Name() : (MMVII_NONE +"_" + ToStr(aCptUnCoded,3)); - aSetM.AddMeasure(cMesIm1Pt(anEE->mPt,aCode,1.0)); - mVSavE.push_back(cSaveExtrEllipe(*anEE,aCode)); + if (anEE->mCardDetect==1) + { + std::string aCode = anEE->mWithCode ? anEE->mEncode.Name() : (MMVII_NONE +"_" + ToStr(aCptUnCoded,mSpec->NbBits())); + aSetM.AddMeasure(cMesIm1Pt(anEE->mPt,aCode,1.0)); + mVSavE.push_back(cSaveExtrEllipe(*anEE,aCode)); - if (! anEE->mWithCode) aCptUnCoded++; + if (! anEE->mWithCode) aCptUnCoded++; + } } mPhProj.SaveMeasureIm(aSetM); @@ -789,7 +797,7 @@ void cAppliExtractCircTarget::MakeImageFinalEllispe() { aImVisu.DrawEllipse ( - cRGBImage::Green , // anEE.mWithCode ? cRGBImage::Blue : cRGBImage::Red, + (anEE->mCardDetect==1) ? cRGBImage::Green : cRGBImage::Red , // anEE.mWithCode ? cRGBImage::Blue : cRGBImage::Red, anEl.Center(), anEl.LGa()*aMul , anEl.LSa()*aMul , anEl.TetaGa() ); @@ -988,6 +996,33 @@ int cAppliExtractCircTarget::ExeOnParsedBox() } } + if (1) + { + std::map > aMapDetect; + for (const auto & aCT : mVCTE) + { + if (aCT->mWithCode) + { + aMapDetect[aCT->mEncode.Name() ] .push_back(aCT); + } + } + + for (const auto & [aName,aLPtr] : aMapDetect) + { + if (aLPtr.size() !=1) + { + for (const auto & aPtr : aLPtr) + { + cPt2dr aC = aPtr->mEllipse.Center(); + AddOneReportCSV(mReportMutipleDetec,{APBI_NameIm(),aName,ToStr(aLPtr.size()),ToStr(aC.x()),ToStr(aC.y())}); + aPtr->mCardDetect = aLPtr.size(); + } + } + } + // std::set< + // for (const auto & + } + if (mUseSimul) { TestOnSimul(); @@ -1017,6 +1052,16 @@ int cAppliExtractCircTarget::ExeOnParsedBox() +void cAppliExtractCircTarget::OnCloseReport(int aNbLine,const std::string & anIdent,const std::string & aNameFile) const +{ + if (anIdent==mReportMutipleDetec) + { + if (aNbLine>4) // Each target is detected 2 times + { + MMVII_UsersErrror(eTyUEr::eMultipleTargetInOneImage,"Nb Multiple Target = " + ToStr(aNbLine/2)); + } + } +} int cAppliExtractCircTarget::Exe() { @@ -1029,6 +1074,9 @@ int cAppliExtractCircTarget::Exe() mDoReportSimul = true; } + mReportMutipleDetec = "MultipleTarget"; + InitReport(mReportMutipleDetec,"csv",true,{"Image","Target","Mult","x","y"}); + if (mDoReportSimul) { mReportSimulDet = "SimulDetails" ; diff --git a/MMVII/src/CodedTarget/cCompleteUncodeTarget.cpp b/MMVII/src/CodedTarget/cCompleteUncodeTarget.cpp index 387186d5d9..3806af1198 100644 --- a/MMVII/src/CodedTarget/cCompleteUncodeTarget.cpp +++ b/MMVII/src/CodedTarget/cCompleteUncodeTarget.cpp @@ -16,22 +16,6 @@ namespace MMVII { - /* -struct A -{ -}; -struct B -{ - A mA; -}; - -void f () -{ - B aB; - A aA = aB; -} -*/ - /* *********************************************************** */ /* */ @@ -150,6 +134,8 @@ void cAppliCompletUncodedTarget::CompleteOneGCP(const cMes1GCP & aGCP) } // Now test shape of ellispe compared to theoreticall ground pose + + // StdOut() << "NNNNNoOOrmal " << mNormal << " NAME=" << aGCP.mNamePt << std::endl; cPlane3D aPlaneT = cPlane3D::FromPtAndNormal(aGCP.mPt,mNormal); // 3D plane of the ellispe cEllipse aEl = mSensor->EllipseIm2Plane(aPlaneT,anIt_SEE->mEllipse,50); // ellipse in ground coordinate @@ -163,6 +149,7 @@ void cAppliCompletUncodedTarget::CompleteOneGCP(const cMes1GCP & aGCP) AddOneReportCSV(mNameReportEllipse,{mNameIm,aGCP.mNamePt,ToStr(aRMoy),ToStr(aRatio)}); + // StdOut() << "CoooOmmpl " << __LINE__ << "\n"; if ( IsInit(&mThreshRay) && ( (aRatio > mThreshRay[0]) @@ -173,6 +160,7 @@ void cAppliCompletUncodedTarget::CompleteOneGCP(const cMes1GCP & aGCP) { return; } + // StdOut() << "CoooOmmpl " << __LINE__ << "\n"; if (false && (LevelCall()==0)) // print info if was done whith only one image { @@ -201,9 +189,9 @@ int cAppliCompletUncodedTarget::Exe() InitReport(mNameReportEllipse,"csv",true); + AddHeaderReportCSV(mNameReportEllipse,{"Image","Pt","Ray","Ratio"}); if (RunMultiSet(0,0)) // If a pattern was used, run in // by a recall to itself 0->Param 0->Set { - AddOneReportCSV(mNameReportEllipse,{"Image","Pt","Ray","Ratio"}); int aRes = ResultMultiSet(); if (aRes!=EXIT_SUCCESS) return aRes; diff --git a/MMVII/src/ConvertFormat/ImportClino.cpp b/MMVII/src/ConvertFormat/ImportClino.cpp new file mode 100644 index 0000000000..71aa03812a --- /dev/null +++ b/MMVII/src/ConvertFormat/ImportClino.cpp @@ -0,0 +1,149 @@ +#include "MMVII_PCSens.h" +#include "MMVII_MMV1Compat.h" +#include "MMVII_DeclareCste.h" +#include "MMVII_BundleAdj.h" +#include "MMVII_Stringifier.h" + +/** + \file cConvCalib.cpp testgit + + \brief file for conversion between calibration (change format, change model) and tests +*/ + + +namespace MMVII +{ + + /* ********************************************************** */ + /* */ + /* cAppli_CERN_ImportClino */ + /* */ + /* ********************************************************** */ + +class cAppli_CERN_ImportClino : public cMMVII_Appli +{ + public : + cAppli_CERN_ImportClino(const std::vector & aVArgs,const cSpecMMVII_Appli & aSpec); + int Exe() override; + cCollecSpecArg2007 & ArgObl(cCollecSpecArg2007 & anArgObl) override ; + cCollecSpecArg2007 & ArgOpt(cCollecSpecArg2007 & anArgOpt) override ; + private : + + void MakeOneDir(const std::string & aDir,cMMVII_Ofs &) const; + cPhotogrammetricProject mPhProj; + + // Mandatory Arg + std::string mNameRes; + std::vector Samples() const override; + + std::vector mNamesClino; +}; + +cAppli_CERN_ImportClino::cAppli_CERN_ImportClino(const std::vector & aVArgs,const cSpecMMVII_Appli & aSpec) : + cMMVII_Appli (aVArgs,aSpec), + mPhProj (*this), + mNamesClino {"A1","B1","B2","A2"} +{ +} + +cCollecSpecArg2007 & cAppli_CERN_ImportClino::ArgObl(cCollecSpecArg2007 & anArgObl) +{ + return anArgObl + << Arg2007(mNameRes ,"Folder of external project where the calib is to be imported") + ; +} + +cCollecSpecArg2007 & cAppli_CERN_ImportClino::ArgOpt(cCollecSpecArg2007 & anArgFac) +{ + + return anArgFac + // << AOpt2007(mNameGCP,"NameGCP","Name of GCP set") + // << AOpt2007(mNbDigName,"NbDigName","Number of digit for name, if fixed size required (only if int)") + // << AOpt2007(mL0,"NumL0","Num of first line to read",{eTA2007::HDV}) + // << AOpt2007(mLLast,"NumLast","Num of last line to read (-1 if at end of file)",{eTA2007::HDV}) + // << AOpt2007(mPatternTransfo,"PatName","Pattern for transforming name (first sub-expr)") + ; +} + +//template inline Type GetV(std::istringstream & iss); + + +void cAppli_CERN_ImportClino::MakeOneDir(const std::string & aDir,cMMVII_Ofs & anOFS) const +{ + std::string aNameF = aDir + StringDirSeparator() + "ClinoValue.json"; + std::ifstream infile(aNameF); + + std::vector aVFileIm = GetFilesFromDir(aDir+StringDirSeparator(),AllocRegex("043.*")); + + MMVII_INTERNAL_ASSERT_tiny(aVFileIm.size()==1,"cAppli_CERN_ImportClino : bad size for image pattern match"); + anOFS.Ofs() << aVFileIm.at(0) ; + StdOut() << "DDD " << aDir << " " << aVFileIm << "\n"; + + std::string line; + // mNbLineRead = 0; + // int aNumL = 0; + cCarLookUpTable aLUT; + aLUT.InitIdGlob(); + aLUT.Init("[],",' '); + while (std::getline(infile, line)) + { + line = aLUT.Translate(line); + // StdOut() << "DDD=" << aDir << " [" << line << "]\n"; + std::istringstream iss(line); + + for (const auto & aNameClino : mNamesClino) + { + tREAL8 aAvg = GetV(iss); + tREAL8 aStdDev = GetV(iss); + StdOut() << " * " << aNameClino << " " << aAvg << " " << aStdDev << "\n"; + anOFS.Ofs() << " " << aNameClino << " " << aAvg << " " << aStdDev ; + } + } + anOFS.Ofs() << std::endl; +} + + +int cAppli_CERN_ImportClino::Exe() +{ + mPhProj.FinishInit(); + + tNameSelector aSelec = AllocRegex("Calibration_Clino_.*"); + std::vector aLD = GetSubDirFromDir("./",aSelec); + std::sort(aLD.begin(),aLD.end()); + + cMMVII_Ofs anOFS(mNameRes,eFileModeOut::CreateText); + for (const auto & aDir : aLD) + MakeOneDir(aDir,anOFS); + + + return EXIT_SUCCESS; +} + + +std::vector cAppli_CERN_ImportClino::Samples() const +{ + return {"MMVII V2ImportCalib ../../Pannel/ BA_725 CalibInit725"}; +} + + +tMMVII_UnikPApli Alloc_CERN_ImportClino(const std::vector & aVArgs,const cSpecMMVII_Appli & aSpec) +{ + return tMMVII_UnikPApli(new cAppli_CERN_ImportClino(aVArgs,aSpec)); +} + +cSpecMMVII_Appli TheSpec_CERN_ImportClino +( + "CERN_ImportClino", + Alloc_CERN_ImportClino, + "A temporary command to arrange clino format", + {eApF::Ori}, + {eApDT::Ori}, + {eApDT::Ori}, + __FILE__ +); +/* +*/ + + +}; // MMVII + diff --git a/MMVII/src/Geom2D/GeomsBase2D.cpp b/MMVII/src/Geom2D/GeomsBase2D.cpp index 58ba7b5d03..e4faaa2a55 100755 --- a/MMVII/src/Geom2D/GeomsBase2D.cpp +++ b/MMVII/src/Geom2D/GeomsBase2D.cpp @@ -46,6 +46,12 @@ template cSegment2DCompiled::cSegment2DCompiled(const tPt& aP { } +template cSegment2DCompiled::cSegment2DCompiled(const cSegment& aSeg) : + cSegment2DCompiled(aSeg.P1(),aSeg.P2()) +{ +} + + template cPtxd cSegment2DCompiled::ToCoordLoc(const tPt& aPt) const { tPt aV1P = aPt - this->mP1; diff --git a/MMVII/src/Geom3D/GeomsBase3D.cpp b/MMVII/src/Geom3D/GeomsBase3D.cpp index 77d2e357ea..9caf23e6fd 100755 --- a/MMVII/src/Geom3D/GeomsBase3D.cpp +++ b/MMVII/src/Geom3D/GeomsBase3D.cpp @@ -1,4 +1,4 @@ -#include "MMVII_Matrix.h" +#include "MMVII_SysSurR.h" #include "MMVII_Geom3D.h" namespace MMVII @@ -282,6 +282,7 @@ cPlane3D cPlane3D::FromPtAndNormal(const cPt3dr & aP0,const cPt3dr& aNormal) const cPt3dr& cPlane3D::AxeI() const {return mAxeI;} const cPt3dr& cPlane3D::AxeJ() const {return mAxeJ;} const cPt3dr& cPlane3D::AxeK() const {return mAxeK;} +const cPt3dr& cPlane3D::P0() const {return mP0; } cPt3dr cPlane3D::ToLocCoord(const cPt3dr & aPGlob) const { @@ -320,8 +321,165 @@ std::vector cPlane3D::RandParam() return std::vector{aP0,v1,v2}; } +/** Compute the direction of intersection, algorithm : + * + * - compute the quadratic form E(Pt) = Sum(D^2(Plk,Pt)) + * - search the minimum on unity sphere + * - the minimum is reached for the eigen vector corresponding to the lowest eigen-value + */ + + +cPt3dr cPlane3D::DirInterPlane(const std::vector& aVPlanes,int aSzMin) +{ + MMVII_INTERNAL_ASSERT_tiny((int)aVPlanes.size()>=aSzMin,"DirInterPlane not enough planes"); + + // compute the quadratic form + cStrStat2 aCov(3); + for (const auto & aPlanePtr : aVPlanes) + { + aCov.Add(aPlanePtr->AxeK().ToVect()); + } + + // extract the diagonalisation + const cResulSymEigenValue & aResE = aCov.DoEigen(); + + // extract the eigen-vector corresponding to lowest eigen value (they are in growing order) + cPt3dr aRes; + GetCol(aRes,aResE.EigenVectors(),0); + + return aRes; +} + +cPt3dr cPlane3D::DirInterPlane(const std::vector& aVPlanes,int aSzMin) +{ + return DirInterPlane(VecObj2VecPtr(aVPlanes),aSzMin); +} +/** Compute the line of intersection of N Plane , Method : + * + * - 1 compute the direction "DIR" + * - 2 compute "the" point + * + * The problem arrise when the direction of intersection is almost perfect, in this + * case the position is undetermined. This is obviously the case when N=2. This here + * where the stabilizer is used, it fix with some weight, the position on "DIR" to be + * closed to average of P0() of all plane. + */ + +tSeg3dr cPlane3D::InterPlane(const std::vector& aVPlanes,int aSzMin,tREAL8 aWeightStabRel) +{ + cPt3dr aDir = DirInterPlane(aVPlanes,aSzMin); + int aNbPl = aVPlanes.size(); + + if (aNbPl<=1) + { + cPt3dr aP0 = aVPlanes.empty() ? cPt3dr::PRandC() : aVPlanes.at(0)->P0(); + return tSeg3dr(aP0,aP0+aDir); + } + + cLeasSqtAA aSys(3); + + cPt3dr aAvgP0(0,0,0); + tREAL8 aSomDPl = 0; + for (const auto & aPlanePtr : aVPlanes) + { + const cPt3dr & aK = aPlanePtr->AxeK(); + aSys.PublicAddObservation(1.0,aK.ToVect(),Scal(aPlanePtr->P0(),aK)); + aAvgP0 += aPlanePtr->P0(); + aSomDPl += std::abs(Scal(aK,aDir)); + } + + if (aWeightStabRel != 0) + { + aAvgP0 = aAvgP0 / tREAL8(aNbPl); + aSomDPl /= aNbPl; + + tREAL8 aWeightStab = aWeightStabRel / (aSomDPl+aWeightStabRel); + aSys.PublicAddObservation(aWeightStab,aDir.ToVect(),Scal(aDir,aAvgP0)); + } + + cPt3dr aP0 = cPt3dr::FromVect(aSys.Solve()); + return tSeg3dr(aP0,aP0+aDir); +} + +tSeg3dr cPlane3D::InterPlane(const std::vector& aVPlanes,int aSzMin,tREAL8 aWeightStabRel) +{ + return InterPlane(VecObj2VecPtr(aVPlanes),aSzMin,aWeightStabRel); +} + + +void BenchPlaneInter() +{ + for (int aKPlane=0 ; aKPlane<100 ; aKPlane++) + { + cPt3dr aAxeSym = cPt3dr::PRandUnit(); + tRotR aR = tRotR::CompleteRON(aAxeSym ); + int aNbTeta = 0 + (aKPlane%7); + tREAL8 aTeta0 = RandUnif_C() *10.0; + std::vector aVPlanes; + + cPt3dr aP0 = cPt3dr::PRandC(); + + tREAL8 aEps = 0.1 * RandUnif_C_NotNull(0.1); + // force a perfect intersec to test stabilization + if ( (aNbTeta>2) && (aKPlane%3==0)) + aEps = 0; + + for (int aKTeta=0 ; aKTeta Test that the intersection is orthog to normal + MMVII_INTERNAL_ASSERT_bench(aVCos<1e-5,"Dir Inter Plane, Case 2"); + // Test point P1 and P2 belongs to all plane + MMVII_INTERNAL_ASSERT_bench((aZ1<1e-5) && (aZ2<1e-5),"Z-Inter Plane, Case <= 2"); + } + else + { + // just test that inter is not perfect + // StdOut() << "CCCc" << aVCos << " " << aDirInter << aPl.AxeK() << "\n"; + + if (aEps>0) + { + MMVII_INTERNAL_ASSERT_bench(aVCos>std::abs(aEps/2.0),"Dir Inter Plane, Case > 2"); + } + // Test point P1 belongs to all plane + MMVII_INTERNAL_ASSERT_bench((aZ1<1e-5) ,"Z-Inter Plane, Case 2"); + } + } + if (aNbTeta>2) + { + tREAL8 aDist = Norm2(aDirInter - aAxeSym); + MMVII_INTERNAL_ASSERT_bench(aDist<1e-5,"Dir Inter Plane, Case > 2"); + } + + } +} + + void BenchPlane3D() { + BenchPlaneInter(); + for (int aK=0 ;aK<100 ;aK++) { std::vector aVP = cPlane3D::RandParam(); diff --git a/MMVII/src/Geom3D/cAppliLine2DTo3D.cpp b/MMVII/src/Geom3D/cAppliLine2DTo3D.cpp new file mode 100755 index 0000000000..9c73d35346 --- /dev/null +++ b/MMVII/src/Geom3D/cAppliLine2DTo3D.cpp @@ -0,0 +1,114 @@ +#include "MMVII_PCSens.h" +#include "MMVII_ImageInfoExtract.h" +#include "MMVII_ExtractLines.h" +#include "MMVII_Matrix.h" + + + +namespace MMVII +{ +/* =============================================== */ +/* */ +/* cAppliLine2DTo3D */ +/* */ +/* =============================================== */ + +class cAppliLine2DTo3D : public cMMVII_Appli +{ + public : + cAppliLine2DTo3D(const std::vector & aVArgs,const cSpecMMVII_Appli & aSpec); + private : + + cPt2dr Redist(const cPt2dr &) const; + cPt2dr Undist(const cPt2dr &) const; + + void DoOneImage(const std::string & aNameIm); + /* + int Exe() override; + cCollecSpecArg2007 & ArgObl(cCollecSpecArg2007 & anArgObl) override ; + cCollecSpecArg2007 & ArgOpt(cCollecSpecArg2007 & anArgOpt) override ; + std::vector Samples() const override; + virtual ~cAppliLine2DTo3D(); + */ + + cPerspCamIntrCalib * mCalib; + +}; + +/* +void DoOneImage(const std::string & aNameIm) +{ +} +*/ + + + + +#if (0) + +cAppliLine2DTo3D::cAppliLine2DTo3D(const std::vector & aVArgs,const cSpecMMVII_Appli & aSpec) : + cMMVII_Appli (aVArgs,aSpec), + mPhProj (*this), + mCalib (nullptr) +{ +} + +cAppliExtractLine::~cAppliExtractLine() +{ + delete mExtrL; + DeleteAllAndClear(mVPS); +} + +cCollecSpecArg2007 & cAppliExtractLine::ArgObl(cCollecSpecArg2007 & anArgObl) +{ + return anArgObl + << Arg2007(mPatImage,"Name of input Image", {eTA2007::FileDirProj,{eTA2007::MPatFile,"0"}}) + << Arg2007(mLineIsWhite," True : its a light line , false dark ") + ; +} + +cCollecSpecArg2007 & cAppliExtractLine::ArgOpt(cCollecSpecArg2007 & anArgOpt) +{ + return anArgOpt + << mPhProj.DPOrient().ArgDirInOpt("","Folder for calibration to integrate distorsion") + << AOpt2007(mAffineMax,"AffineMax","Affinate the local maxima",{eTA2007::HDV}) + << AOpt2007(mShowSteps,"ShowSteps","Show detail of computation steps by steps",{eTA2007::HDV}) + << AOpt2007(mZoomImL,"ZoomImL","Zoom for images of line",{eTA2007::HDV}) + << AOpt2007(mRelThrsCumulLow,"ThrCumLow","Low Thresold relative for cumul in histo",{eTA2007::HDV}) + << AOpt2007(mRelThrsCumulHigh,"ThrCumHigh","Low Thresold relative for cumul in histo",{eTA2007::HDV}) + << mPhProj.DPPointsMeasures().ArgDirInOpt("","Folder for ground truth measure") + ; +} + +std::vector cAppliExtractLine::Samples() const +{ + return { + "MMVII ExtractLine 'DSC_.*.JPG' ShowSteps=1 InOri=FB" + }; +} + +int cAppliExtractLine::Exe() +{ + return EXIT_SUCCESS; +} + + +tMMVII_UnikPApli Alloc_AppliExtractLine(const std::vector & aVArgs,const cSpecMMVII_Appli & aSpec) +{ + return tMMVII_UnikPApli(new cAppliExtractLine(aVArgs,aSpec)); +} + + +cSpecMMVII_Appli TheSpecAppliExtractLine +( + "ExtractLine", + Alloc_AppliExtractLine, + "Extraction of lines", + {eApF::Ori}, + {eApDT::Ori,eApDT::GCP}, + {eApDT::Console}, + __FILE__ +); +#endif + +}; diff --git a/MMVII/src/Geoms/PtsBox.cpp b/MMVII/src/Geoms/PtsBox.cpp index 1afcf6b6b9..91091faa67 100755 --- a/MMVII/src/Geoms/PtsBox.cpp +++ b/MMVII/src/Geoms/PtsBox.cpp @@ -108,6 +108,8 @@ template void cSegment::CompileFoncLinear template const cPtxd& cSegment::P1() const {return mP1;} template const cPtxd& cSegment::P2() const {return mP2;} +template cPtxd& cSegment::P1() {return mP1;} +template cPtxd& cSegment::P2() {return mP2;} template cPtxd cSegment::V12() const {return mP2-mP1;} diff --git a/MMVII/src/ImagesBase/cRGBImage.cpp b/MMVII/src/ImagesBase/cRGBImage.cpp index f13101c598..b56042439b 100755 --- a/MMVII/src/ImagesBase/cRGBImage.cpp +++ b/MMVII/src/ImagesBase/cRGBImage.cpp @@ -144,6 +144,8 @@ bool cRGBImage::InsideBL(const cPt2dr & aPix) const void cRGBImage::SetRGBPixWithAlpha(const cPt2di & aPix,const cPt3di &aCoul,const cPt3dr & aAlpha) { + if (!mImR.DIm().Inside(aPix)) + return; AssertZ1(); cPt3di aCurC = GetRGBPix(aPix); diff --git a/MMVII/src/ImagesInfoExtract/cAppliExtractLine.cpp b/MMVII/src/ImagesInfoExtract/cAppliExtractLine.cpp index db0c2dc413..60a8ad3469 100755 --- a/MMVII/src/ImagesInfoExtract/cAppliExtractLine.cpp +++ b/MMVII/src/ImagesInfoExtract/cAppliExtractLine.cpp @@ -6,118 +6,6 @@ namespace MMVII { -cHoughPS::cHoughPS(const cHoughTransform * aHT,const cPt2dr & aTR,tREAL8 aCumul,const cPt2dr & aP1,const cPt2dr & aP2) : - mHT (aHT), - mTetaRho (aTR), - mCumul (aCumul), - mSegE (aP1,aP2) -{ - InitMatch(); -} - - - - -tREAL8 cHoughPS::DistAnglAntiPar(const cHoughPS& aPS2) const -{ - return diff_circ(Teta()+M_PI,aPS2.Teta(),2*M_PI); -} - -tREAL8 cHoughPS::DY(const cHoughPS & aHPS) const -{ - return mSegE.ToCoordLoc(aHPS.mSegE.PMil()) .y() ; -} - -const cSegment2DCompiled & cHoughPS::Seg() const {return mSegE;} -const cPt2dr & cHoughPS::TetaRho() const {return mTetaRho;} -const tREAL8 & cHoughPS::Teta() const {return mTetaRho.x();} -const tREAL8 & cHoughPS::Rho() const {return mTetaRho.y();} -const tREAL8 & cHoughPS::Cumul() const {return mCumul;} -cHoughPS * cHoughPS::Matched() const {return mMatched;} - -cPt2dr cHoughPS::IndTetaRho() const -{ - return cPt2dr(mHT->Teta2RInd(Teta()),mHT->Rho2RInd(Rho())); -} - -tREAL8 cHoughPS::Dist(const cHoughPS& aPS2,const tREAL8 &aFactTeta) const -{ - return std::abs(Rho()-aPS2.Rho()) - + DistAnglAntiPar(aPS2) * (aFactTeta * mHT->RhoMax()) - ; -} - -void cHoughPS::Test(const cHoughPS & aHPS) const -{ - StdOut() << "LARG " << mSegE.ToCoordLoc(aHPS.mSegE.PMil()) .y() - << " RMDistAng " << DistAnglAntiPar(aHPS) * mHT->RhoMax() - << " DistAng " << DistAnglAntiPar(aHPS) - // << " T1=" << Teta()<< " T2=" aHPS.Teta() << " "<< diff_circ(Teta(),aHPS.Teta(),2*M_PI) - << "\n"; -} - -bool cHoughPS::Match(const cHoughPS & aPS2,bool IsLight,tREAL8 aMaxTeta,tREAL8 aDMin,tREAL8 aDMax) const -{ - tREAL8 aDY1 = DY(aPS2 ); - tREAL8 aDY2 = aPS2.DY(*this); - - // Test the coherence of left/right position - if ( ((aDY1>0) ==IsLight) || ((aDY2>0) ==IsLight)) return false; - - if ( DistAnglAntiPar(aPS2) > aMaxTeta) return false; - - tREAL8 aDYAbs1 = std::abs(aDY1); - tREAL8 aDYAbs2 = std::abs(aDY2); - - return (aDYAbs1>aDMin) && (aDYAbs1aDMin) && (aDYAbs2 & mVPS,bool IsLight,tREAL8 aMaxTeta,tREAL8 aDMin,tREAL8 aDMax) -{ - // Reset matches - for (auto & aPtr : mVPS) - aPtr->InitMatch(); - - // compute best match - for (size_t aK1=0 ; aK1Match(*mVPS[aK2],IsLight,aMaxTeta,aDMin,aDMax)) - { - tREAL8 aD12 = mVPS[aK1]->Dist(*mVPS[aK2],2.0); - mVPS[aK1]->UpdateMatch(mVPS[aK2],aD12); - mVPS[aK2]->UpdateMatch(mVPS[aK1],aD12); - } - } - } - - // Test if reciproc match - for (auto & aPtr : mVPS) - { - if (aPtr->mMatched && (aPtr->mMatched->mMatched!=aPtr)) - { - aPtr->mMatched->mMatched =nullptr; - aPtr->mMatched =nullptr; - } - } -} - /* =============================================== */ /* */ /* cAppliExtractLine */ @@ -137,6 +25,7 @@ class cAppliExtractLine : public cMMVII_Appli typedef tREAL4 tIm; cPt2dr Redist(const cPt2dr &) const; + cPt2dr Undist(const cPt2dr &) const; int Exe() override; cCollecSpecArg2007 & ArgObl(cCollecSpecArg2007 & anArgObl) override ; @@ -152,6 +41,7 @@ class cAppliExtractLine : public cMMVII_Appli std::string mPatImage; bool mLineIsWhite; bool mShowSteps; + // bool mShowImages; std::vector mVParams; cPerspCamIntrCalib * mCalib; bool mAffineMax; @@ -160,8 +50,16 @@ class cAppliExtractLine : public cMMVII_Appli cExtractLines* mExtrL; int mZoomImL; std::vector mVPS; - std::string mNameReport; - tREAL8 mRelThrsCum; + std::vector mMatchedVPS; + std::string mNameReportByLine; + std::string mNameReportByIm; + tREAL8 mRelThrsCumulLow; + tREAL8 mRelThrsCumulHigh; + tREAL8 mHoughSeuilAng; + + bool mWithGT; ///< Is there a ground truth of "handcrafted" segment + bool mGTEmpty; ///< Does the GT "says" that here is no valid segment + std::vector mVPtsGT; }; @@ -176,8 +74,13 @@ cAppliExtractLine::cAppliExtractLine(const std::vector & aVArgs,con mTransparencyCont (0.5), mExtrL (nullptr), mZoomImL (1), - mNameReport ("LineExtract"), - mRelThrsCum (0.3) + mNameReportByLine ("LineMulExtract"), + mNameReportByIm ("LineByIm"), + mRelThrsCumulLow (0.10), + mRelThrsCumulHigh (0.30), + mHoughSeuilAng (0.20), + mWithGT (false), + mGTEmpty (true) { } @@ -192,6 +95,7 @@ cCollecSpecArg2007 & cAppliExtractLine::ArgObl(cCollecSpecArg2007 & anArgObl) return anArgObl << Arg2007(mPatImage,"Name of input Image", {eTA2007::FileDirProj,{eTA2007::MPatFile,"0"}}) << Arg2007(mLineIsWhite," True : its a light line , false dark ") + << mPhProj.DPPointsMeasures().ArgDirOutMand() ; } @@ -202,7 +106,9 @@ cCollecSpecArg2007 & cAppliExtractLine::ArgOpt(cCollecSpecArg2007 & anArgOpt) << AOpt2007(mAffineMax,"AffineMax","Affinate the local maxima",{eTA2007::HDV}) << AOpt2007(mShowSteps,"ShowSteps","Show detail of computation steps by steps",{eTA2007::HDV}) << AOpt2007(mZoomImL,"ZoomImL","Zoom for images of line",{eTA2007::HDV}) - << AOpt2007(mRelThrsCum,"ThrCum","Thresold relative for cumul in histo",{eTA2007::HDV}) + << AOpt2007(mRelThrsCumulLow,"ThrCumLow","Low Thresold relative for cumul in histo",{eTA2007::HDV}) + << AOpt2007(mRelThrsCumulHigh,"ThrCumHigh","Low Thresold relative for cumul in histo",{eTA2007::HDV}) + << AOpt2007(mHoughSeuilAng,"HoughThrAng","Angular threshold for hough acummulator",{eTA2007::HDV}) << mPhProj.DPPointsMeasures().ArgDirInOpt("","Folder for ground truth measure") ; } @@ -219,37 +125,163 @@ cPt2dr cAppliExtractLine::Redist(const cPt2dr & aP) const return mCalib ? mCalib->Redist(aP) : aP; } +cPt2dr cAppliExtractLine::Undist(const cPt2dr & aP) const +{ + return mCalib ? mCalib->Undist(aP) : aP; +} void cAppliExtractLine::DoOneImage(const std::string & aNameIm) { + tREAL8 aMulTeta = 1.0/M_PI; // aMulTeta = 1.0; bool mShow = true; + + // [1] Eventually init calibration for correction distorsion mCalib = nullptr; if (mPhProj.DPOrient().DirInIsInit()) mCalib = mPhProj.InternalCalibFromImage(aNameIm); + else + { + } + + + // [2] Eventually init ground truth 2D-points + if (mPhProj.DPPointsMeasures().DirInIsInit() && mPhProj.HasMeasureIm(aNameIm)) + { + mWithGT = true; + cSetMesPtOf1Im aSetMes = mPhProj.LoadMeasureIm(aNameIm); + + if (aSetMes.NameHasMeasure("Line1") && aSetMes.NameHasMeasure("Line2")) + { + mGTEmpty = false; + mVPtsGT.push_back(Undist(aSetMes.MeasuresOfName("Line1").mPt)); + mVPtsGT.push_back(Undist(aSetMes.MeasuresOfName("Line2").mPt)); + } + } + + cIm2D anIm = cIm2D::FromFile(aNameIm); - tREAL8 aTrhsCum = mRelThrsCum * Norm2(anIm.DIm().Sz()); + tREAL8 aTrhsCumulLow = mRelThrsCumulLow * Norm2(anIm.DIm().Sz()); + tREAL8 aTrhsCumulHigh = mRelThrsCumulHigh * Norm2(anIm.DIm().Sz()); mExtrL = new cExtractLines (anIm); + // Compute Gradient and extract max-loc in gradient direction mExtrL->SetDericheGradAndMasq(2.0,10.0,2,mShow); // aAlphaDerich,aRayMaxLoc,aBorder - mExtrL->SetHough(cPt2dr(aMulTeta,1.0),0.1,mCalib,mAffineMax,mShow); + // Compute Hough-Transform + mExtrL->SetHough(cPt2dr(aMulTeta,1.0),mHoughSeuilAng,mCalib,mAffineMax,mShow); + + // Extract Local Maxima in hough space + std::vector aVMaxLoc = mExtrL->Hough().ExtractLocalMax(10,5.0,10.0,0.1); + StdOut() << "VMAXLoc " << aVMaxLoc.size() << "\n"; - std::vector aVMaxLoc = mExtrL->Hough().ExtractLocalMax(10,4.0,10.0,0.1); + // Select Maxima with Cum > aTrhsCumulLow + labelize the quality of seg + int aRank=0; for (const auto & aPMax : aVMaxLoc) { cHoughPS * aPS = mExtrL->Hough().PtToLine(aPMax); - if (aPS->Cumul() > aTrhsCum) + if (aPS->Cumul() > aTrhsCumulLow) + { + if (aPS->Cumul() < aTrhsCumulHigh) + aPS->SetCode(eCodeHPS::LowCumul); + else if (aRank !=0) + aPS->SetCode(eCodeHPS::NotFirst); mVPS.push_back(aPS); + } else delete aPS; + aRank++; } - // mVPS[0]->Test(*mVPS[1]); - // mVPS[1]->Test(*mVPS[0]); + StdOut() << "VPSINIT " << mVPS.size() << "\n"; cHoughPS::SetMatch(mVPS,mLineIsWhite,mVParams.at(0),mVParams.at(1),mVParams.at(2)); + for (auto & aHS1 : mVPS) + { + cHoughPS *aHS2 = aHS1->Matched(); + if ((aHS2!=nullptr) && (! BoolFind(mMatchedVPS,aHS2))) + { + mMatchedVPS.push_back(aHS1); + } + } + + // StdOut() << "NbMatchHHHHHH " << mMatchedVPS.size() << "\n"; + + // Compute the quality and save it in report + { + // Intrinsic evaluation + std::string aStringQual = "OK"; + + if (mMatchedVPS.empty()) + aStringQual = "Pb_Empty"; + else if ((mMatchedVPS.size()>=2) && (mMatchedVPS.at(1)->Code() == eCodeHPS::Ok)) + aStringQual = "Pb_AmbNOK"; + else if ((mMatchedVPS.size()>=2) && ( (mMatchedVPS.at(1)->Cumul()/mMatchedVPS.at(0)->Cumul() ) > 0.5)) + aStringQual = "Pb_AmbRatio12"; + else if (mMatchedVPS.at(0)->Code() != eCodeHPS::Ok) + aStringQual = "Pb_LowCumul"; + + + // modification if there is a ground truth + if (mWithGT) + { + if (mGTEmpty) + { + aStringQual = mMatchedVPS.empty() ? "Ok_Empty" : "Pb_NotEmpty"; + } + else + { + if (mMatchedVPS.empty()) + { + } + else + { + // Test is the 2 ground-truth points are "almost" inside the two lines + bool OkGT= true; + for (const auto & aPt : mVPtsGT) + { + for (bool isSeg2 : {false,true}) + { + cHoughPS * aSeg = mMatchedVPS.at(0); + if (isSeg2) + aSeg = aSeg->Matched(); + cPt2dr aPLoc = aSeg->Seg().ToCoordLoc(aPt); + if (aPLoc.y() > 2.0) + OkGT=false; + } + } + aStringQual = OkGT ? "OK_ByGT" : "PB_ByGT"; + } + } + } + + // register the result in a report + AddOneReportCSV(mNameReportByIm,{aNameIm,aStringQual}); + } + + + // make a report for each lines + cLinesAntiParal1Im aExAllLines; + aExAllLines.mNameIm = aNameIm; + if (mPhProj.DPOrient().DirInIsInit()) + aExAllLines.mDirCalib = mPhProj.DPOrient().DirIn(); + + for (cHoughPS * aHS1 : mMatchedVPS) + { + cHoughPS *aHS2 = aHS1->Matched(); + cOneLineAntiParal aEx1L; + aEx1L.mAng = aHS1->DistAnglAntiPar(*aHS2) * mExtrL->Hough().RhoMax() ; + aEx1L.mWidth = -( aHS1->DY(*aHS2) + aHS2->DY(*aHS1) ) / 2.0; + aEx1L.mCumul = (aHS1->Cumul()+aHS2->Cumul())/2.0; + aEx1L.mSeg = aHS1->SegMoyAntiParal(*aHS2); + AddOneReportCSV(mNameReportByLine,{aNameIm,ToStr(aEx1L.mAng),ToStr(aEx1L.mWidth),ToStr(aEx1L.mCumul)}); + + aExAllLines.mLines.push_back(aEx1L); + } + mPhProj.SaveLines(aExAllLines); + // SaveInFile(aExAllLines,mPhProj.DPPointsMeasures().FullDirOut() + "Segs-"+aNameIm + "."+ GlobTaggedNameDefSerial()); + if (mShowSteps) MakeVisu(aNameIm); } @@ -314,7 +346,7 @@ void cAppliExtractLine::MakeVisu(const std::string & aNameIm) // [4] Visu of Image + Lines { cRGBImage aVisIm = cRGBImage::FromFile(aNameIm,mZoomImL); // Initialize with image - const auto & aDIm = aVisIm.ImR().DIm(); + // const auto & aDIm = aVisIm.ImR().DIm(); for (size_t aKH=0 ; aKH=2) aCoul = cRGBImage::Green; - // if (aKH>=4) aCoul = cRGBImage::Blue; - if (isOk && (aHS1> aHS2)) - { - tREAL8 aDAng = aHS1->DistAnglAntiPar(*aHS2) * mExtrL->Hough().RhoMax() ; - tREAL8 aLarg = aHS1->DY(*aHS2) ; - tREAL8 aCumul = (aHS1->Cumul()+aHS2->Cumul())/2.0; - AddOneReportCSV(mNameReport,{aNameIm,ToStr(aDAng),ToStr(aLarg),ToStr(aCumul)}); - } // Compute Hough-Point -> line cSegment aSeg = mVPS[aKH]->Seg(); @@ -339,7 +362,18 @@ void cAppliExtractLine::MakeVisu(const std::string & aNameIm) cPt2dr aC = Redist(aSeg.PMil() +VUnit(aSeg.V12()*cPt2dr(0,-1))* aRay); aVisIm.DrawCircle(aCoul,aC ,aRay); + MMVII_INTERNAL_ASSERT_tiny(mCalib!=nullptr,"Calib mandatory for now in line detect"); + + cSegment2DCompiled aSegC (mCalib->ExtenSegUndistIncluded(aSeg)); + for (tREAL8 aC=0 ; aC< aSegC.N2() ; aC+= 1.0) + { + cPt2dr aQ = Redist(aSegC.FromCoordLoc(cPt2dr(aC,0.0))); ; // eventulay make invert distorsion correcion + aVisIm.SetRGBPoint(aQ,aCoul); // print point + } + + // write point by point, in two direction + /* for (tREAL8 aSign : {-1.0,1.0}) { cPt2dr aPt = aSeg.PMil(); @@ -352,6 +386,7 @@ void cAppliExtractLine::MakeVisu(const std::string & aNameIm) aQ = Redist(aPt); // eventulay make invert distorsion correcion } } + */ } std::string aNameLine = mPhProj.DirVisu() + "Lines_" + aNameTif; // convert dont handle well big file, so generate jpg only if zoom=1 @@ -368,11 +403,13 @@ void cAppliExtractLine::MakeVisu(const std::string & aNameIm) int cAppliExtractLine::Exe() { mPhProj.FinishInit(); - InitReport(mNameReport,"csv",true); + InitReport(mNameReportByLine,"csv",true,{"NameIm","Paral","Larg","Cumul"}); + InitReport(mNameReportByIm,"csv",true,{"NameIm","CodeResult"}); + // AddHeaderReportCSV(mNameReportByLine,{"NameIm","Paral","Larg","Cumul"}); + // AddHeaderReportCSV(mNameReportByIm,{"NameIm","CodeResult"}); if (RunMultiSet(0,0)) { - AddOneReportCSV(mNameReport,{"NameIm","Paral","Larg","Cumul"}); return ResultMultiSet(); } DoOneImage(UniqueStr(0)); diff --git a/MMVII/src/ImagesInfoExtract/cHoughTransform.cpp b/MMVII/src/ImagesInfoExtract/cHoughTransform.cpp index b2ee2eb5e4..a89379cda6 100755 --- a/MMVII/src/ImagesInfoExtract/cHoughTransform.cpp +++ b/MMVII/src/ImagesInfoExtract/cHoughTransform.cpp @@ -7,6 +7,139 @@ namespace MMVII { +/* ************************************************************************ */ +/* */ +/* cHoughPS */ +/* */ +/* ************************************************************************ */ + +cHoughPS::cHoughPS(const cHoughTransform * aHT,const cPt2dr & aTR,tREAL8 aCumul,const cPt2dr & aP1,const cPt2dr & aP2) : + mHT (aHT), + mTetaRho (aTR), + mCumul (aCumul), + mSegE (aP1,aP2), + mCode (eCodeHPS::Ok) +{ + InitMatch(); +} + + + + +tREAL8 cHoughPS::DistAnglAntiPar(const cHoughPS& aPS2) const +{ + return diff_circ(Teta()+M_PI,aPS2.Teta(),2*M_PI); +} + +tSeg2dr cHoughPS::SegMoyAntiParal(const cHoughPS& aPS2) const +{ + cPt2dr aP0 = (mSegE.PMil() + aPS2.mSegE.PMil() ) / 2.0; + cPt2dr aTgt = (mSegE.Tgt() - aPS2.mSegE.Tgt() ) / 2.0; + + return tSeg2dr(aP0-aTgt,aP0+aTgt); +} + + +tREAL8 cHoughPS::DY(const cHoughPS & aHPS) const +{ + return mSegE.ToCoordLoc(aHPS.mSegE.PMil()) .y() ; +} + +const cSegment2DCompiled & cHoughPS::Seg() const {return mSegE;} +const cPt2dr & cHoughPS::TetaRho() const {return mTetaRho;} +const tREAL8 & cHoughPS::Teta() const {return mTetaRho.x();} +const tREAL8 & cHoughPS::Rho() const {return mTetaRho.y();} +const tREAL8 & cHoughPS::Cumul() const {return mCumul;} +cHoughPS * cHoughPS::Matched() const {return mMatched;} +eCodeHPS cHoughPS::Code() const {return mCode;} +void cHoughPS::SetCode(eCodeHPS aCode) { mCode = aCode;} + +cPt2dr cHoughPS::IndTetaRho() const +{ + return cPt2dr(mHT->Teta2RInd(Teta()),mHT->Rho2RInd(Rho())); +} + +tREAL8 cHoughPS::Dist(const cHoughPS& aPS2,const tREAL8 &aFactTeta) const +{ + return std::abs(Rho()-aPS2.Rho()) + + DistAnglAntiPar(aPS2) * (aFactTeta * mHT->RhoMax()) + ; +} + +void cHoughPS::Test(const cHoughPS & aHPS) const +{ + StdOut() << "LARG " << mSegE.ToCoordLoc(aHPS.mSegE.PMil()) .y() + << " RMDistAng " << DistAnglAntiPar(aHPS) * mHT->RhoMax() + << " DistAng " << DistAnglAntiPar(aHPS) + // << " T1=" << Teta()<< " T2=" aHPS.Teta() << " "<< diff_circ(Teta(),aHPS.Teta(),2*M_PI) + << "\n"; +} + +bool cHoughPS::Match(const cHoughPS & aPS2,bool IsLight,tREAL8 aMaxTeta,tREAL8 aDMin,tREAL8 aDMax) const +{ + tREAL8 aDY1 = DY(aPS2 ); + tREAL8 aDY2 = aPS2.DY(*this); + + // Test the coherence of left/right position + if ( ((aDY1>0) ==IsLight) || ((aDY2>0) ==IsLight)) return false; + + if ( DistAnglAntiPar(aPS2) > aMaxTeta) return false; + + tREAL8 aDYAbs1 = std::abs(aDY1); + tREAL8 aDYAbs2 = std::abs(aDY2); + + return (aDYAbs1>aDMin) && (aDYAbs1aDMin) && (aDYAbs2 & aVPS,bool IsLight,tREAL8 aMaxTeta,tREAL8 aDMin,tREAL8 aDMax) +{ + // Reset matches + for (auto & aPtr : aVPS) + aPtr->InitMatch(); + + // compute best match + for (size_t aK1=0 ; aK1Match(*aVPS[aK2],IsLight,aMaxTeta,aDMin,aDMax)) + { + tREAL8 aD12 = aVPS[aK1]->Dist(*aVPS[aK2],2.0); + aVPS[aK1]->UpdateMatch(aVPS[aK2],aD12); + aVPS[aK2]->UpdateMatch(aVPS[aK1],aD12); + } + } + } + + // Test if reciproc match + for (auto & aPtr : aVPS) + { + if (aPtr->mMatched && (aPtr->mMatched->mMatched!=aPtr)) + { + aPtr->mMatched->mMatched =nullptr; + aPtr->mMatched =nullptr; + } + } +} + + + /* ************************************************************************ */ /* */ /* cHoughTransform */ @@ -67,6 +200,13 @@ cHoughPS* cHoughTransform::PtToLine(const cPt3dr & aPt) const return new cHoughPS(this,cPt2dr(aTeta,aRho),aPt.z(),aP0-aTgt,aP0+aTgt); } +/* +cPt2dr cHoughTransform::Line2Pt(const tSeg2dr &) const +{ + + // cPt2dr aTgt(-sin(aTeta),cos(aTeta)); +} +*/ void cHoughTransform::AccumulatePtAndDir(const cPt2dr & aPt,tREAL8 aTetaC,tREAL8 aWeight) @@ -136,6 +276,82 @@ tREAL8 cHoughTransform::GetValueBlob(cPt2di aPt,int aMaxNeigh) const return aRes; } +#if (1) +std::vector cHoughTransform::ExtractLocalMax(size_t aNbMax,tREAL8 aDist,tREAL8 aThrAvg,tREAL8 aThrMax) const +{ + std::vector aVNeigh = SortedVectOfRadius(0.5,aDist,false); + + // [1] Compute average , max and threshold + // [1.A] : max & avg + tREAL8 aAvg = 0; + tREAL8 aVMax = 0; + for (const auto & aPix : mDAccum) + { + tREAL8 aVal = mDAccum.GetV(aPix); + aAvg += aVal; + UpdateMax(aVMax,aVal); + } + aAvg /= mDAccum.NbElem(); + + // [1.B] Threshlod is the stricter of both + tREAL8 aThrHold = std::max(aAvg*aThrAvg,aVMax*aThrMax); + + + std::vector aVPMaxLoc; + int aY0 = 1+round_up(aDist); + int aY1 = mNbRho - aY0; + for (const auto & aPix : mDAccum) + { + const tREAL4 & aVPix = mDAccum.GetV(aPix); + if ( (aVPix>aThrHold) + && (aPix.y() > aY0) && (aVPix >= mDAccum.GetV(aPix-cPt2di(0,1))) + && (aPix.y() < aY1) && (aVPix > mDAccum.GetV(aPix+cPt2di(0,1))) + ) + { + bool IsMaxLoc=true; + for (size_t aKNeigh=0 ; (aKNeighaVPix) + { + IsMaxLoc = false; + } + else if (aVNeigh==aVPix) + { + if ((aDX>0) || ((aDX==0) && (aDY>0))) + IsMaxLoc = false; + } + } + if (IsMaxLoc) + aVPMaxLoc.push_back(aPix); + } + } + + // [4] Refine the point and give a value to the max + + std::vector aRes; + cAffineExtremum aAffin(mDAccum,1.5); // 1.5 => radius , 8-neighboorhood + for (const auto aPt : aVPMaxLoc) + { + cPt2dr aPAff = aAffin.OneIter(ToR(aPt)); + if ( mDAccum.InsideBL(aPAff)) + aRes.push_back(cPt3dr(aPAff.x(),aPAff.y(),GetValueBlob(aPt,7))); + } + + // [5] Sort with highest value first, then select NbMax + SortOnCriteria(aRes,[](const auto & aP) {return -aP.z();}); + while (aRes.size() > aNbMax) + aRes.pop_back(); + + // StdOut() << "NBMAXLOC " << aRes << "\n"; + + return aRes; +} + +#else std::vector cHoughTransform::ExtractLocalMax(size_t aNbMax,tREAL8 aDist,tREAL8 aThrAvg,tREAL8 aThrMax) const { @@ -191,5 +407,6 @@ std::vector cHoughTransform::ExtractLocalMax(size_t aNbMax,tREAL8 aDist return aRes; } +#endif }; diff --git a/MMVII/src/ImagesInfoExtract/cImGradWithN.cpp b/MMVII/src/ImagesInfoExtract/cImGradWithN.cpp index fbad28132b..25861f66af 100755 --- a/MMVII/src/ImagesInfoExtract/cImGradWithN.cpp +++ b/MMVII/src/ImagesInfoExtract/cImGradWithN.cpp @@ -99,7 +99,12 @@ template cPt2dr cImGradWithN::OneRefinePos(const cPt2dr & aP if (! mDataNG.InsideBL(aP1)) return aP1; - cPt2dr aGr = VUnit(ToR(this->GradBL(aP1))); + cPt2dr aGr = ToR(this->GradBL(aP1)); + tREAL8 aNorm = Norm2(aGr); + + if (aNorm==0) + return aP1; + aGr = aGr / aNorm; // extract point "before" cPt2dr aP0 = aP1- aGr; diff --git a/MMVII/src/Instrumental/cClinoInit.cpp b/MMVII/src/Instrumental/cClinoInit.cpp index 3ec0b649b4..6a2b1f4c36 100644 --- a/MMVII/src/Instrumental/cClinoInit.cpp +++ b/MMVII/src/Instrumental/cClinoInit.cpp @@ -222,6 +222,7 @@ class cAppli_ClinoInit : public cMMVII_Appli cPhotogrammetricProject mPhProj; ///< Classical structure for photogrammetric project std::string mNameClino; ///< Pattern of xml file + std::string mFormat; std::vector mPrePost; ///< Pattern of xml file int mNbStep0; ///< Number of step in initial first round int mNbStepIter; ///< Number of step in each iteration @@ -236,7 +237,9 @@ class cAppli_ClinoInit : public cMMVII_Appli */ std::vector mComputedClino; + std::string mNameRel12; ///< relative orientation of Clino1/Clino2 stored as "i-kj" + bool isOkNoCam; ///< Is it OK if cam does not exist sometime ? std::vector mOriRelClin; ///< vector of relative orientations Clino[0]/Clino[K] bool mShowAll; ///< Do we show all the msg relative to residuals cCalibSetClino mCalibSetClino; ///< Result of the calibration @@ -253,6 +256,7 @@ cAppli_ClinoInit::cAppli_ClinoInit mNbStepIter (10), mNbIter (50), mNameRel12 ("i-kj"), + isOkNoCam (false), mShowAll (false) { } @@ -262,7 +266,7 @@ cCollecSpecArg2007 & cAppli_ClinoInit::ArgObl(cCollecSpecArg2007 & anArgObl) { return anArgObl << Arg2007(mNameClino,"Name of inclination file") // ,{eTA2007::FileDirProj}) - << Arg2007(mPrePost,"[Prefix,PostFix] to compute image name",{{eTA2007::ISizeV,"[2,2]"}}) + << Arg2007(mFormat,"Format of file like ISFSSFSSFSSFS ") << Arg2007(mVKClino,"Index of clinometer",{{eTA2007::ISizeV,"[1,2]"}}) << mPhProj.DPOrient().ArgDirInMand() << mPhProj.DPClinoMeters().ArgDirOutMand() @@ -278,7 +282,9 @@ cCollecSpecArg2007 & cAppli_ClinoInit::ArgOpt(cCollecSpecArg2007 & anArgOpt) << AOpt2007(mNbIter,"NbIter","Number of iteration",{eTA2007::HDV}) << AOpt2007(mASim,"AmplSim","Amplitude of rotation is simul [W,P,K,BS]",{{eTA2007::ISizeV,"[5,5]"}}) << AOpt2007(mNameRel12,"Rel12","orientation relative 2 to 1, if several clino",{eTA2007::HDV}) - << mPhProj.DPClinoMeters().ArgDirInOpt() // Just for temporart test we can re-read, to supress later + << AOpt2007(isOkNoCam,"OkNoCam","is it OK if some cam dont exist",{eTA2007::HDV}) + << mPhProj.DPClinoMeters().ArgDirInOpt() // Just for temporart test we can re-read, to supress later + << AOpt2007(mPrePost,"PrePost","[Prefix,PostFix] to compute image name",{{eTA2007::ISizeV,"[2,2]"}}) ; } @@ -399,7 +405,7 @@ int cAppli_ClinoInit::Exe() // --------- Read formated file ---------------- - std::string mFormat = "ISFSF"; + // std::string mFormat = "ISFSF"; cReadFilesStruct aRFS(mNameClino,mFormat,0,-1,'#'); aRFS.Read(); size_t aNbMeasures = aRFS.NbRead(); @@ -450,18 +456,24 @@ int cAppli_ClinoInit::Exe() } else { - std::string aNameIm = mPrePost[0] + aRFS.VNameIm().at(aKLine) + mPrePost[1]; - cSensorCamPC * aCam = mPhProj.ReadCamPC(aNameIm,true); - mVMeasures.push_back(cClinoCalMes1Cam(aCam,aRFS.VNums().at(aKLine))); + std::string aNameIm = aRFS.VNameIm().at(aKLine) ; + if (IsInit(&mPrePost)) + aNameIm = mPrePost[0] + aNameIm + mPrePost[1]; + + cSensorCamPC * aCam = mPhProj.ReadCamPC(aNameIm,true,isOkNoCam); + if (aCam != nullptr) + { + mVMeasures.push_back(cClinoCalMes1Cam(aCam,aRFS.VNums().at(aKLine))); - aCalib = aCam->InternalCalib(); - aNameCalibCam = aCalib->Name(); + aCalib = aCam->InternalCalib(); + aNameCalibCam = aCalib->Name(); - // We cannnot have multiple camera for now - if ((mCalibSetClino.mNameCam !="") && (mCalibSetClino.mNameCam != aNameCalibCam)) - MMVII_UnclasseUsEr("Multiple camera not handled"); + // We cannnot have multiple camera for now + if ((mCalibSetClino.mNameCam !="") && (mCalibSetClino.mNameCam != aNameCalibCam)) + MMVII_UnclasseUsEr("Multiple camera not handled"); - mCalibSetClino.mNameCam = aNameCalibCam; + mCalibSetClino.mNameCam = aNameCalibCam; + } } } diff --git a/MMVII/src/Matrix/cLinearConstraint.cpp b/MMVII/src/Matrix/cLinearConstraint.cpp index ea1bf0de50..25d261bbbd 100755 --- a/MMVII/src/Matrix/cLinearConstraint.cpp +++ b/MMVII/src/Matrix/cLinearConstraint.cpp @@ -184,11 +184,14 @@ template void cDSVec::Reset() template void cDSVec::TestEmpty() { +// put in #if else get warning unused error +#if (The_MMVII_DebugLevel>=The_MMVII_DebugLevel_InternalError_tiny ) for (const auto & aV : mVec.ToStdVect()) MMVII_INTERNAL_ASSERT_tiny(aV==0.0,"Vec Test Empty"); MMVII_INTERNAL_ASSERT_tiny(mSet.mVIndOcc.empty(),"Occ Test Empty"); for (const auto & aV : mSet.mOccupied) MMVII_INTERNAL_ASSERT_tiny(aV==false,"Vec Test Empty"); +#endif } template void cDSVec::Show() diff --git a/MMVII/src/OrientReport/TiePQuality.cpp b/MMVII/src/OrientReport/TiePQuality.cpp index 8c3599f9ec..c4765c08e6 100644 --- a/MMVII/src/OrientReport/TiePQuality.cpp +++ b/MMVII/src/OrientReport/TiePQuality.cpp @@ -93,7 +93,8 @@ void cAppli_TiePReport::MakeStatByImage() for (const auto& aPairKC : aLInd) { size_t aKImLoc = aPairKC.first; - const auto & aConfig = aPairKC.second->first; + // Unused in mode release + [[maybe_unused]] const auto & aConfig = aPairKC.second->first; // a litle check on indexe for these complexe structures MMVII_INTERNAL_ASSERT_tiny(aKImGlob==(size_t)aConfig.at(aKImLoc),"Check nums in cAppli_TiePReport::MakeStatByImage"); diff --git a/MMVII/src/Sensors/Measures.cpp b/MMVII/src/Sensors/Measures.cpp index ae72308f06..026c83b863 100644 --- a/MMVII/src/Sensors/Measures.cpp +++ b/MMVII/src/Sensors/Measures.cpp @@ -13,6 +13,34 @@ namespace MMVII { +/* ********************************************* */ +/* */ +/* cOneLineAntiParal */ +/* */ +/* ********************************************* */ + +cOneLineAntiParal::cOneLineAntiParal() : + mSeg (cPt2dr(0,0),cPt2dr(1,0)) // Diff else error (cstr check not identic) +{ +} + +void AddData(const cAuxAr2007 & anAux,cOneLineAntiParal & anEx) +{ + AddData(cAuxAr2007("P1",anAux),anEx.mSeg.P1()); + AddData(cAuxAr2007("P2",anAux),anEx.mSeg.P2()); + AddData(cAuxAr2007("ParalAng",anAux),anEx.mAng); + AddData(cAuxAr2007("Width",anAux),anEx.mWidth); + AddData(cAuxAr2007("Cumul",anAux),anEx.mCumul); +} + +void AddData(const cAuxAr2007 & anAux,cLinesAntiParal1Im & anEx) +{ + AddData(cAuxAr2007("Calib",anAux),anEx.mDirCalib); + AddData(cAuxAr2007("Lines",anAux),anEx.mLines); +} + + + /* ********************************************* */ /* */ /* cHomogCpleIm */ diff --git a/MMVII/src/Sensors/cCentralPerspCam.cpp b/MMVII/src/Sensors/cCentralPerspCam.cpp index 54855eacb4..b20adf5c57 100644 --- a/MMVII/src/Sensors/cCentralPerspCam.cpp +++ b/MMVII/src/Sensors/cCentralPerspCam.cpp @@ -862,6 +862,33 @@ cPerspCamIntrCalib * cPerspCamIntrCalib::RandomCalib(eProjPC aTypeProj,int aKDeg return aCam; } +tSeg2dr cPerspCamIntrCalib::ExtenSegUndistIncluded + ( + const tSeg2dr & aSegInit, + tREAL8 aStepInitRel, + tREAL8 aStepEnd, + tREAL8 aRetract + ) const +{ + std::vector aVPts; + for (tREAL8 aSign : {-1.0,1.0}) + { + cPt2dr aPt = aSegInit.PMil(); + cPt2dr aTgt = VUnit(aSegInit.V12()) * aSign; + tREAL8 aStep= aStepInitRel * Norm2(SzPix()); + while (aStep >= aStepEnd) + { + while (DegreeVisibilityOnImFrame(Redist(aPt))>=0) + aPt += aTgt* aStep; + aPt += aTgt* (-aStep); + aStep /= 2.0; + } + aPt += aPt * (-aRetract); + aVPts.push_back(aPt); + } + return tSeg2dr(aVPts.at(0),aVPts.at(1)); +} + void BenchCentralePerspective(cParamExeBench & aParam,eProjPC aTypeProj) diff --git a/MMVII/src/Sensors/cPhotogrammetricProject.cpp b/MMVII/src/Sensors/cPhotogrammetricProject.cpp index d115d89e4a..807a24859a 100644 --- a/MMVII/src/Sensors/cPhotogrammetricProject.cpp +++ b/MMVII/src/Sensors/cPhotogrammetricProject.cpp @@ -698,6 +698,13 @@ std::string cPhotogrammetricProject::NameMeasureGCPIm(const std::string & aNameI return mDPPointsMeasures.FullDirInOut(isIn) + cSetMesPtOf1Im::StdNameFileOfIm(FileOfPath(aNameIm,false)) ; } + +bool cPhotogrammetricProject::HasMeasureIm(const std::string & aNameIm,bool InDir) const +{ + return ExistFile(NameMeasureGCPIm(aNameIm,InDir)); +} + + cSetMesPtOf1Im cPhotogrammetricProject::LoadMeasureIm(const std::string & aNameIm,bool isIn) const { // std::string aDir = mDPPointsMeasures.FullDirInOut(isIn); @@ -855,6 +862,30 @@ void cPhotogrammetricProject::SaveAndFilterAttrEll(const cSetMesPtOf1Im & aSetM aVSEEOut.push_back(aSEE); SaveInFile(aVSEEOut,cSaveExtrEllipe::NameFile(*this,aSetM,false)); } + // ============================ LINES ============================================== + +std::string cPhotogrammetricProject::NameFileLines(const std::string & aNameIm) const +{ + return DPPointsMeasures().FullDirOut() + "SegsAntiParal-"+ aNameIm + "."+ GlobTaggedNameDefSerial(); +} + +bool cPhotogrammetricProject::HasFileLines(const std::string & aNameIm) const +{ + return ExistFile(NameFileLines(aNameIm)); +} + +void cPhotogrammetricProject::SaveLines(const cLinesAntiParal1Im &aLAP1I) const +{ + SaveInFile(aLAP1I,NameFileLines(aLAP1I.mNameIm)); +} + +cLinesAntiParal1Im cPhotogrammetricProject::ReadLines(const std::string & aNameIm) const +{ + cLinesAntiParal1Im aRes; + ReadFromFile(aRes,NameFileLines(aNameIm)); + return aRes; +} + // ============= Multiple Tie Points ================= @@ -1019,6 +1050,7 @@ std::list cPhotogrammetricProject::ReadBlocCams() const return aRes; } + // ============= Meta Data ================= // see cMetaDataImages.cpp diff --git a/MMVII/src/Serial/ElemStrToVal.cpp b/MMVII/src/Serial/ElemStrToVal.cpp index fd97a65997..9f44daa6ea 100644 --- a/MMVII/src/Serial/ElemStrToVal.cpp +++ b/MMVII/src/Serial/ElemStrToVal.cpp @@ -337,6 +337,7 @@ template<> cE2Str::tMapE2Str cE2Str::mE2S {eTyUEr::eNoFocaleEqui35,"NoFocaleEqui35"}, {eTyUEr::eNoNumberPixel,"NoNumberPixel"}, {eTyUEr::eNoCameraName,"NoCameraName"}, + {eTyUEr::eMultipleTargetInOneImage,"MultipleTargetInOneImage,"}, {eTyUEr::eUnClassedError,"UnClassedError"} }; diff --git a/MMVII/src/Utils/uti_files.cpp b/MMVII/src/Utils/uti_files.cpp index e94971d636..77449ffef3 100755 --- a/MMVII/src/Utils/uti_files.cpp +++ b/MMVII/src/Utils/uti_files.cpp @@ -187,6 +187,7 @@ void cMMVII_Ifs::Read(std::string & aVal ) /** Low level read of file containing nums in fixed format */ +/* static std::string CurFile; /// global var to get context, not proud of that static int CurLine; /// global var to get context, not proud of that template inline Type GetV(std::istringstream & iss) @@ -199,6 +200,7 @@ template inline Type GetV(std::istringstream & iss) } return aNum; } +*/ int CptOccur(const std::string & aStr,char aC0) { @@ -277,6 +279,15 @@ void cReadFilesStruct::Read() CurFile = mNameFile; + /* + char aLut[256]; + for (int aK=0 ; aK<256 ; aK++) + { + aLut[aK] = aK; + } + cCarLookUpTable aLUT; + */ + mVNameIm.clear(); mVNamePt.clear(); mVXYZ.clear(); @@ -301,6 +312,11 @@ void cReadFilesStruct::Read() MMVII_DEV_WARNING("Dont understand why must add \" \" at end of line ReadFilesStruct"); line += " "; CurLine = aNumL+1; // editor begin at line 1, non 0 + /* + for (size_t aK=0 ; aK=mL0) && (aNumL(iss); initPt++; break; case 'I' : aNameIm = GetV(iss); initIm++; break; case 'S' : aLString.push_back(GetV(iss)); initString++; break; + case '#' : GetV(iss); break; default : MMVII_INTERNAL_ERROR(std::string(("Unhandled car in cReadFilesStruct::Read=") + aCar)+"]"); diff --git a/MMVII/src/Utils/uti_set_sel.cpp b/MMVII/src/Utils/uti_set_sel.cpp index d1cd1e9a2e..0d69a3fe42 100755 --- a/MMVII/src/Utils/uti_set_sel.cpp +++ b/MMVII/src/Utils/uti_set_sel.cpp @@ -453,6 +453,7 @@ cPatternTransfo::cPatternTransfo(const std::vector & aVec) : GetDef(aVec,1,std::string("$0")) ) { + // JOE if ( (aVec.size()!=0) && (aVec.size() != 2)) MMVII_UnclasseUsEr("cPatternTransfo bad size"); } diff --git a/MMVII/src/Utils/uti_string.cpp b/MMVII/src/Utils/uti_string.cpp index da9cc0bd2f..d25a99e9f0 100755 --- a/MMVII/src/Utils/uti_string.cpp +++ b/MMVII/src/Utils/uti_string.cpp @@ -97,6 +97,12 @@ cCarLookUpTable::cCarLookUpTable() : MEM_RAZ(&mDTable,1); } +void cCarLookUpTable::InitIdGlob() +{ + InitId(std::numeric_limits::min(),std::numeric_limits::max()-1); +} + + /* ************************************************* */ /* */ /* MMVII */ diff --git a/MMVII/todo.txt b/MMVII/todo.txt index 3560e8ab8d..ed63ac5b09 100644 --- a/MMVII/todo.txt +++ b/MMVII/todo.txt @@ -1,3 +1,13 @@ +CERN : + + * detection cibles sur nouvelles acquisitions + * fils : + - recalage image + - quali detection image + - 3D !! + + +=========================================================== Documentation/ COmmenta Reengeneerin : TieP Fomat @@ -29,8 +39,6 @@ terminate called after throwing an instance of 'std::filesystem::__cxx11::filesy what(): filesystem error: directory iterator cannot open directory: No such file or directory [./MMVII-PhgrProj/PointsMeasure/xx/] Abandon (core dumped) - - ================ DONE ================================ ImortGCP => Pts Mult ; diff --git a/include/XML_MicMac/SaisieLine.xml b/include/XML_MicMac/SaisieLine.xml index fbaec7e869..68578b2018 100755 --- a/include/XML_MicMac/SaisieLine.xml +++ b/include/XML_MicMac/SaisieLine.xml @@ -9,6 +9,8 @@ Antipasti ~/micmac/include/XML_MicMac/SaisieLine.xml DirectoryChantier="/home/ma Image=IMG_557[2-7].tif Ori=Test-7 Dir=/home/marc/TMP/ExempleDoc/Boudha/ + Gama=1.0 + SzWx=800 SzWy=800 @@ -60,8 +62,7 @@ Antipasti ~/micmac/include/XML_MicMac/SaisieLine.xml DirectoryChantier="/home/ma ${Image} ${ForceGray} ${Ori} - - + ${Gama} diff --git a/src/uti_phgrm/CPP_SaisieBasc.cpp b/src/uti_phgrm/CPP_SaisieBasc.cpp index bba9ddf9b0..bf58e08169 100755 --- a/src/uti_phgrm/CPP_SaisieBasc.cpp +++ b/src/uti_phgrm/CPP_SaisieBasc.cpp @@ -49,7 +49,8 @@ void SaisieBasc(int argc, char ** argv, std::string &anOut, Pt2di &aSzW, Pt2di &aNbFen, - bool &aForceGray) + bool &aForceGray, + double & aGama) { MMD_InitArgcArgv(argc,argv); @@ -62,6 +63,7 @@ void SaisieBasc(int argc, char ** argv, LArgMain() << EAM(aSzW,"SzW",true,"Total size of windows") << EAM(aNbFen,"NbF",true,"Number of Windows (def depend of number of images") << EAM(aForceGray,"ForceGray",true," Force gray image, def =true") + << EAM(aGama,"Gama",true," Gama correction, def=1.0") ); if(!MMVisualMode) @@ -117,8 +119,10 @@ int SaisieBasc_main_Gen(int argc,char ** argv,int aMode) Pt2di aNbFen(-1,-1); std::string aFullName,anOri,anOut, aDir, aName; bool aForceGray = true; + double aGama = 1.0; - SaisieBasc(argc, argv, aFullName, aDir, aName, anOri, anOut, aSzW, aNbFen, aForceGray); + + SaisieBasc(argc, argv, aFullName, aDir, aName, anOri, anOut, aSzW, aNbFen, aForceGray,aGama); std::string aCom = MMDir() +"bin/mm3d SaisiePts " + MMDir() +"include/XML_MicMac/SaisieLine.xml " @@ -138,6 +142,12 @@ int SaisieBasc_main_Gen(int argc,char ** argv,int aMode) if (EAMIsInit(&aForceGray)) aCom = aCom + " +ForceGray=" + ToString(aForceGray); + if (EAMIsInit(&aGama)) + { + aCom = aCom + " +Gama=" + ToString(aGama) + " "; + } + + std::cout << aCom << "\n";