diff --git a/MMVII/include/MMVII_ExtractLines.h b/MMVII/include/MMVII_ExtractLines.h index f655d5c37b..1e143a8c1e 100755 --- a/MMVII/include/MMVII_ExtractLines.h +++ b/MMVII/include/MMVII_ExtractLines.h @@ -123,6 +123,7 @@ class cHoughTransform tREAL8 GetValueBlob(cPt2di aP,int aMaxNeigh) const; private : + void ExtendMoreTeta() const; // inline tREAL8 R2Teta(tREAL8 aIndTeta) const {return aIndTeta *mFactI2T;} @@ -133,6 +134,7 @@ class cHoughTransform tREAL8 mSigmTeta; ///< incertitude on teta cPerspCamIntrCalib* mCalib; ///< Potential calibration for distorsion int mNbTeta; ///< Number of Teta for hough-accum + int mMoreTeta; ///< a bit more teta to handle topol struct tREAL8 mFactI2T ; ///< Ratio Teta-Radian / Teta-Index int mNbRho; ///< Number of Rho for hough-accum diff --git a/MMVII/src/ImagesInfoExtract/cAppliExtractLine.cpp b/MMVII/src/ImagesInfoExtract/cAppliExtractLine.cpp index 60a8ad3469..dbbfc23637 100755 --- a/MMVII/src/ImagesInfoExtract/cAppliExtractLine.cpp +++ b/MMVII/src/ImagesInfoExtract/cAppliExtractLine.cpp @@ -60,6 +60,8 @@ class cAppliExtractLine : public cMMVII_Appli bool mWithGT; ///< Is there a ground truth of "handcrafted" segment bool mGTEmpty; ///< Does the GT "says" that here is no valid segment std::vector<cPt2dr> mVPtsGT; + std::vector<tSeg2dr> mVSegsGT; + std::vector<cPt2dr> mVHoughGT; }; @@ -157,6 +159,12 @@ void cAppliExtractLine::DoOneImage(const std::string & aNameIm) mGTEmpty = false; mVPtsGT.push_back(Undist(aSetMes.MeasuresOfName("Line1").mPt)); mVPtsGT.push_back(Undist(aSetMes.MeasuresOfName("Line2").mPt)); + + for (bool IsDir : {false,true}) + { + tSeg2dr aSeg(mVPtsGT.at(IsDir?0:1), mVPtsGT.at(IsDir?1:0)); + mVSegsGT.push_back(aSeg); + } } } @@ -172,6 +180,29 @@ void cAppliExtractLine::DoOneImage(const std::string & aNameIm) // Compute Hough-Transform mExtrL->SetHough(cPt2dr(aMulTeta,1.0),mHoughSeuilAng,mCalib,mAffineMax,mShow); + + if (!mVSegsGT.empty()) + { + for (const auto & aSegInit : mVSegsGT) + { + cSegment2DCompiled<tREAL8> aSeg0(aSegInit); + cPt2dr aPtH0 = mExtrL->Hough().Line2Pt(aSeg0); + mVHoughGT.push_back(aPtH0); + cHoughPS * aSH = mExtrL->Hough().PtToLine(TP3z0(aPtH0)); + cSegment2DCompiled<tREAL8> aSeg1 = aSH->Seg(); + + //StdOut() << " Seg=" << aSeg0.Tgt() << aSeg1.Tgt() << Norm2(aSeg0.Tgt() - aSeg1.Tgt()) << "\n"; + //StdOut() << " DDD=" << aSeg1.Dist(aSeg0.P1()) << " " << aSeg1.Dist(aSeg0.P2()) << "\n"; + + MMVII_INTERNAL_ASSERT_bench(aSeg1.Dist(aSeg0.P1())<1e-5,"Hough check seg"); + MMVII_INTERNAL_ASSERT_bench(aSeg1.Dist(aSeg0.P2())<1e-5,"Hough check seg"); + MMVII_INTERNAL_ASSERT_bench(Norm2(aSeg0.Tgt() - aSeg1.Tgt()) <1e-8,"Hough check seg"); + delete aSH; + + StdOut() << "HOUGH-GT= " << aPtH0 << "\n"; + } + } + // Extract Local Maxima in hough space std::vector<cPt3dr> aVMaxLoc = mExtrL->Hough().ExtractLocalMax(10,5.0,10.0,0.1); StdOut() << "VMAXLoc " << aVMaxLoc.size() << "\n"; diff --git a/MMVII/src/ImagesInfoExtract/cHoughTransform.cpp b/MMVII/src/ImagesInfoExtract/cHoughTransform.cpp index a89379cda6..5ad230b7aa 100755 --- a/MMVII/src/ImagesInfoExtract/cHoughTransform.cpp +++ b/MMVII/src/ImagesInfoExtract/cHoughTransform.cpp @@ -161,13 +161,14 @@ cHoughTransform::cHoughTransform mSigmTeta (aSigmTeta), mCalib (aCalib), mNbTeta (round_up(2*M_PI*mMulTeta * mRhoMax)), + mMoreTeta (5), mFactI2T ((2.0*M_PI)/mNbTeta), mNbRho (2+round_up(2*mMulRho * mRhoMax)), mTabSin (mNbTeta), mDTabSin (mTabSin.DIm()), mTabCos (mNbTeta), mDTabCos (mTabCos.DIm()), - mAccum (cPt2di(mNbTeta,mNbRho),nullptr,eModeInitImage::eMIA_Null), + mAccum (cPt2di(mNbTeta+2*mMoreTeta,mNbRho),nullptr,eModeInitImage::eMIA_Null), mDAccum (mAccum.DIm()) { @@ -200,13 +201,18 @@ 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 cHoughTransform::Line2Pt(const tSeg2dr &aSeg) const { + // Grad = (C,S) + // T (-S,C)= (C,S) * (0,-1) = Grad * (-J) + // Grad = T * J - // cPt2dr aTgt(-sin(aTeta),cos(aTeta)); + cPt2dr aGrad = VUnit(aSeg.V12() * cPt2dr(0,-1)); + tREAL8 aTeta = Teta(aGrad); + tREAL8 aRho = Scal(aGrad,aSeg.PMil() - mMiddle); + + return cPt2dr(Teta2RInd(aTeta),Rho2RInd(aRho)); } -*/ void cHoughTransform::AccumulatePtAndDir(const cPt2dr & aPt,tREAL8 aTetaC,tREAL8 aWeight) @@ -276,9 +282,22 @@ tREAL8 cHoughTransform::GetValueBlob(cPt2di aPt,int aMaxNeigh) const return aRes; } +void cHoughTransform::ExtendMoreTeta() const +{ + cDataIm2D<tREAL4>& aNCAcc = const_cast<cDataIm2D<tREAL4>& > (mDAccum); + + for (int aKTeta=0 ; aKTeta< 2* mMoreTeta ; aKTeta++) + { + for (int aKRho=0 ; aKRho< mNbRho ; aKRho++) + aNCAcc.SetV(cPt2di(aKTeta+mNbTeta,aKRho),mDAccum.GetV(cPt2di(aKTeta,aKRho))); + } +} + + #if (1) std::vector<cPt3dr> cHoughTransform::ExtractLocalMax(size_t aNbMax,tREAL8 aDist,tREAL8 aThrAvg,tREAL8 aThrMax) const { + ExtendMoreTeta(); std::vector<cPt2di> aVNeigh = SortedVectOfRadius(0.5,aDist,false); // [1] Compute average , max and threshold @@ -298,14 +317,18 @@ std::vector<cPt3dr> cHoughTransform::ExtractLocalMax(size_t aNbMax,tREAL8 aDist std::vector<cPt2di> aVPMaxLoc; - int aY0 = 1+round_up(aDist); - int aY1 = mNbRho - aY0; - for (const auto & aPix : mDAccum) + // int aY0 = 1+round_up(aDist); + // int aY1 = mNbRho - aY0; + + // We parse only interoir to avoid Out in Rho and duplication in teta + cRect2 aRecInt(mDAccum.Dilate (-mMoreTeta)); + + for (const auto & aPix : aRecInt) { 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))) + && (aVPix >= mDAccum.GetV(aPix-cPt2di(0,1))) + && (aVPix > mDAccum.GetV(aPix+cPt2di(0,1))) ) { bool IsMaxLoc=true; @@ -314,6 +337,7 @@ std::vector<cPt3dr> cHoughTransform::ExtractLocalMax(size_t aNbMax,tREAL8 aDist const cPt2di & aNeigh = aVNeigh.at(aKNeigh); int aDX = aNeigh.x() ; int aDY = aNeigh.y() ; + // use %, because may be out if Dist>mMoreTeta ... const tREAL8 & aVNeigh = mDAccum.GetV(cPt2di((aPix.x() + mNbTeta + aDX) % mNbTeta,aPix.y() + aDY)); if (aVNeigh>aVPix) { @@ -338,7 +362,12 @@ std::vector<cPt3dr> cHoughTransform::ExtractLocalMax(size_t aNbMax,tREAL8 aDist { cPt2dr aPAff = aAffin.OneIter(ToR(aPt)); if ( mDAccum.InsideBL(aPAff)) - aRes.push_back(cPt3dr(aPAff.x(),aPAff.y(),GetValueBlob(aPt,7))); + { + tREAL8 aTeta = aPAff.x(); + if (aTeta>mNbTeta) + aTeta -= mNbTeta; + aRes.push_back(cPt3dr(aTeta,aPAff.y(),GetValueBlob(aPt,7))); + } } // [5] Sort with highest value first, then select NbMax diff --git a/src/saisieQT/include_QT/saisieQT_main.h b/src/saisieQT/include_QT/saisieQT_main.h index 88b7a685ea..13c5ad91f4 100755 --- a/src/saisieQT/include_QT/saisieQT_main.h +++ b/src/saisieQT/include_QT/saisieQT_main.h @@ -47,7 +47,7 @@ extern void SaisieBasc(int argc, char ** argv, std::string &anOut, Pt2di &aSzW, Pt2di &aNbFen, - bool &aForceGray); + bool &aForceGray, double & aGama); QApplication & getQApplication(); diff --git a/src/saisieQT/main/saisieBascQT_main.cpp b/src/saisieQT/main/saisieBascQT_main.cpp index 937e82f6bb..7fc2c62932 100755 --- a/src/saisieQT/main/saisieBascQT_main.cpp +++ b/src/saisieQT/main/saisieBascQT_main.cpp @@ -69,7 +69,8 @@ int saisieBascQT_main(int argc, char *argv[]) argv[0] = (char*) "SaisieBascQT"; } - SaisieBasc(argc, argv, aFullName, aDir, aName, anOri, anOut, aSzWin, aNbFen, aForceGray); + double aGama=1; + SaisieBasc(argc, argv, aFullName, aDir, aName, anOri, anOut, aSzWin, aNbFen, aForceGray,aGama); if (!MMVisualMode) {