Skip to content

Commit 04bf6e9

Browse files
author
deseilligny
committed
Export OriRel as orient in OriRel2Im
1 parent 942159c commit 04bf6e9

File tree

5 files changed

+246
-3
lines changed

5 files changed

+246
-3
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
\chapter{Point Cloud command}
2+
\label{Chap:PointCloud}
3+
4+
5+
%-----------------------------------------------------------------------
6+
%-----------------------------------------------------------------------
7+
%-----------------------------------------------------------------------
8+
9+
\section{Generalities}
10+
11+
%-----------------------------------------------------------------------
12+
\subsection{Introduction}
13+
14+
This section introduce some command/piece of code that have been devlopped for simulating
15+
images and depth map from lidar data. This simulation was done with the ambition of being usable as
16+
training data set for computing canopy model from photogrammetric acquisition. This
17+
simulation pretend by no way to be physically based, the assumption between this simulation
18+
is that what make the canopy difficult to modelize in photgrammetry is the 3D structure that :
19+
20+
\begin{itemize}
21+
\item make it difficult for modelization via regularization
22+
\item generate highly variable images for small change of point of view
23+
\end{itemize}
24+
25+
26+
So the pitch of this simulation is that, if we create data that reflect this difficulties,
27+
we will able to train the networks. Possibly, the images that we will be generated are "more
28+
challenging" that real images, but be we hope that being a "too tough teacher with a network" is not a problem.
29+
30+
Conversely, a postive point of simulation is that we can generate "perfectly" registered data.
31+
32+
33+
34+
%-----------------------------------------------------------------------
35+
\subsection{MMVII format}
36+
37+
As at this step, it is just a quick and dirty prototype, this mean the
38+
devlopment has been made with the objective of minmizing the effort for what
39+
was projected and absolutlely no idea of long term maintenance and evolution.
40+
For example, we did not think it
41+
was pertinent to add "big" librairies for lidar data reading and manipulation.
42+
The code is then based on internal classes and format.
43+
44+
The class for representing a point cloud is {\tt cPointCloud}, it contains essentially:
45+
46+
\begin{itemize}
47+
\item a vector of $3d$ point
48+
\item different optionnal vector, that are attributes of the point
49+
\item some information useful for computation as : bounding boxes , offset of point,
50+
or dynamic of layer \dots
51+
\end{itemize}
52+
53+
For saving and reading {\tt cPointCloud}, we use {\tt MMVII} facilitie of
54+
automated serialization. As it's very huge data , we use the binary
55+
format that generate {\tt ".dmp"} files.
56+
57+
At the time being, we dont make any effort for maintening historical compatibility
58+
of this format. It will probably evolve with new layer, and at each evolution
59+
previous file will become unusable. Of course, at longer term, if this devlopment
60+
continue, we will change that by : make an evolutive format or adopt a standard format.
61+
62+
%-----------------------------------------------------------------------
63+
%-----------------------------------------------------------------------
64+
%-----------------------------------------------------------------------
65+
66+
\section{Create and viusualizng}
67+
68+
69+
%-----------------------------------------------------------------------
70+
71+
\section{Import data with {\tt ImportTxtCloud}}
72+
73+
We can only import data in ply text format. More precisely , {\tt MMVII} use the general facilities
74+
for parsing text file with identical line structure, and do not interpret the ply "semantic". Any text format
75+
close enough to ply, would be readable.
76+
77+
Example of use :
78+
79+
\begin{verbatim}
80+
MMVII ImportTxtCloud 18355_51565.ply "XYZBla" NumL0=30O OffsetIsP0=true Bytes8=false HELP
81+
\end{verbatim}
82+
83+
This command will generate a file {\tt 18355\_51565.dmp}.
84+
In this command :
85+
86+
\begin{itemize}
87+
\item {\tt "XYZBla"} means that we will read the 3 coordinates at the begining of each line and skip after
88+
\item {\tt NumL0=30O} skip the first lines , probably $300$ is "too much", the important is to skip all the header ;
89+
\item {\tt Bytes8=false } mean that the coordinate are store on $4$ byte (and not $8$);
90+
\item {\tt OffsetIsP0=true } mean that the coordinate are store with an offset, and that thi offset is computed
91+
from first point, this is often required with geographic coordinates to maintain sufficient accuracy.
92+
\end{itemize}
93+
94+
Note that this import, can be quite long .
95+
96+
97+
%-----------------------------------------------------------------------
98+
99+
\section{Cliping data with {\tt CloudMMVIIClip}}
100+
101+
It is often convenient to make test on small point cloud. For this one can use the
102+
command {\tt CloudMMVIIClip} :
103+
104+
105+
\begin{verbatim}
106+
MMVII CloudMMVIIClip 18355_51565.dmp [0.4,0.4,0.6,0.6]
107+
\end{verbatim}
108+
109+
The command will generate a file {\tt Clip\_18355\_51565.dmp}. Note tha the box is relative to the global
110+
box (that is stored in the file).
111+
112+
113+
%-----------------------------------------------------------------------
114+
115+
\section{Visualizing data with {\tt CloudMMVII2Ply}}
116+
117+
As the format {\tt ".dmp"} is purely internal, it cannot be visualized with standard tool.
118+
This is why it possible to create ply version of {\tt dmp} files with the command
119+
{\tt CloudMMVII2Ply}. This is specially usefull with colored point cloud
120+
(see~\ref{Cloud::Colorate}).
121+
122+
The command is pretty basic and obvious , for example:
123+
124+
\begin{verbatim}
125+
MMVII CloudMMVII2Ply Clip_18355_51565.dmp
126+
\end{verbatim}
127+
128+
%-----------------------------------------------------------------------
129+
%-----------------------------------------------------------------------
130+
%-----------------------------------------------------------------------
131+
132+
\section{Colouring point cloud with {\tt CloudMMVIIColorate}}
133+
134+
\label{Cloud::Colorate}
135+
136+
137+
Before generating image, we must compute the "colour" of each point/leave. The hypothesis
138+
we do for this are the following :
139+
140+
141+
\COM{
142+
\begin{itemize}
143+
\item the colour of each leave depend only of the quantity of light/energy it receive taking into account occlusions;
144+
this model is quite simplist because in real tree each leave has a different intrisic
145+
colour (albedo) , but we adpot it because :
146+
\begin{itemize}
147+
\item our intution when observing real tree is that the light occlusion is predominant over the albedo
148+
variation for explaining contrats in images (except maybe trees at the begining of automn,
149+
when there is a mix of green & brown leaves)
150+
\item we have no mean to generate realistic albedo varaiation;
151+
\item ometting albedo variation make the problem rather more difficult, and in the doubt, it's better
152+
to train the networks with data too difficult than to easy.
153+
\end{itemize}
154+
155+
by the way, we dont exclude to add later some randomized albedo;
156+
157+
158+
\item the light is made from $2$ sources : an homogeneous halph sphere corresponding to the \emph{"sky"} and a mono directionnal spot light
159+
corresponding to the \emph{"sun"}
160+
161+
\item leaves are spheres.
162+
163+
\end{itemize}
164+
}
165+
166+
167+
168+
169+
170+
171+

MMVII/Doc/Doc2007.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ \chapter{The Fits method}
278278
\part{Commands reference-documentation}
279279

280280
\include{CommandReferences/MeshCommands}
281+
\include{CommandReferences/PointCloud}
281282
\include{CommandReferences/SysCo}
282283

283284

MMVII/src/ImagesBase/BaseImage.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ template <class Type,const int Dim> void cDataTypedIm<Type,Dim>::InitCste(const
299299
}
300300
else
301301
{
302+
// StdOut() << "xxInitCsteInitCste " << NbElem() << " " << mRawDataLin << "\n";
302303
for (tINT8 aK=0 ; aK< NbElem() ; aK++)
303304
mRawDataLin[aK] = aVal;
304305
}

MMVII/src/Mesh/cColorateCloud.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ void cProjPointCloud::ProcessOneProj
485485

486486
mDImIndex = & (mImIndex.DIm());
487487
mDImIndex->Resize(mSzIm);
488+
// StdOut() << "xxxSZ_IM=" << mSzIm << "\n";
488489
mDImIndex->InitCste(NoIndex);
489490

490491

MMVII/src/PoseEstim/cAppli_OriRel2Im.cpp

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "MMVII_Tpl_Images.h"
55
#include "MMVII_HeuristikOpt.h"
66
#include "MMVII_DeclareAllCmd.h"
7+
#include "MMVII_Random.h"
78

89
namespace MMVII
910
{
@@ -99,6 +100,8 @@ class cEstimatePosRel2Im : public cOptimizeRotAndVUnit // Herit for combinatori
99100

100101
cEstimatePosRel2Im
101102
(
103+
const std::string & aIm1,
104+
const std::string & aIm2,
102105
cPerspCamIntrCalib & aCalib1,
103106
cPerspCamIntrCalib & aCalib12,
104107
const cSetHomogCpleIm & aSetHomFull,
@@ -176,6 +179,8 @@ class cEstimatePosRel2Im : public cOptimizeRotAndVUnit // Herit for combinatori
176179

177180

178181
// -------- Data for camera -------------------
182+
std::string mIm1;
183+
std::string mIm2;
179184
cPerspCamIntrCalib & mCalib1; ///< Calib of first image
180185
tREAL8 mFoc1; ///< Foc first image
181186
cPerspCamIntrCalib & mCalib2; ///< Calib second image
@@ -224,6 +229,8 @@ class cEstimatePosRel2Im : public cOptimizeRotAndVUnit // Herit for combinatori
224229

225230
cEstimatePosRel2Im::cEstimatePosRel2Im
226231
(
232+
const std::string& aIm1,
233+
const std::string& aIm2,
227234
cPerspCamIntrCalib & aCalib1,
228235
cPerspCamIntrCalib & aCalib2,
229236
const cSetHomogCpleIm & aSetHomFull,
@@ -233,6 +240,8 @@ cEstimatePosRel2Im::cEstimatePosRel2Im
233240
cTimerSegm * aTimeSegm
234241
) :
235242
cOptimizeRotAndVUnit(5,4,false),
243+
mIm1 (aIm1),
244+
mIm2 (aIm2),
236245
mCalib1 (aCalib1),
237246
mFoc1 (mCalib1.F()),
238247
mCalib2 (aCalib2),
@@ -604,12 +613,30 @@ cCdtFinalPoseRel2Im cEstimatePosRel2Im::MakeDecision(bool Show)
604613
SortOnCriteria(aVBest,[](const auto & aCdt){return aCdt.mScore;});
605614

606615

616+
if (Show)
617+
{
618+
StdOut() << " ======== Select solution in each mode ================\n";
619+
for (auto & aCdt : aVBest )
620+
{
621+
if (mWithGT)
622+
{
623+
tREAL8 aDTr = Norm2(aCdt.mPose.Tr()-mGTPose.Tr());
624+
tREAL8 aDRot = aCdt.mPose.Rot().Dist(mGTPose.Rot());
625+
aCdt.mScorePixGT = cPt2dr(aDTr,aDRot)*mFocMoy;
626+
}
627+
ShowSol(aCdt.mPose,aCdt.mMsg);
628+
}
629+
}
630+
631+
607632
if (aVBest.back().mMode==eModePE2I::eRansac)
608633
{
609634
// Worst sol in ransac
610635
// in this case, probably the scene is planar and the two planary solution
611636
// can not be separated at this step, we maintain them
612637
aVBest.resize(2);
638+
639+
// if (mWithGT && (aVBest.at(0).
613640
}
614641
else
615642
{
@@ -640,6 +667,17 @@ cCdtFinalPoseRel2Im cEstimatePosRel2Im::MakeDecision(bool Show)
640667
StdOut() << "\n";
641668
}
642669
}
670+
if (mWithGT && (aVBest.size()>=2))
671+
{
672+
tREAL8 aSc0 = Norm2(aVBest.at(0).mScorePixGT.value());
673+
tREAL8 aSc1 = Norm2(aVBest.at(1).mScorePixGT.value());
674+
if (aSc1<aSc0)
675+
{
676+
StdOut() << "===== For Images " << mIm1 << " " << mIm2 << "\n";
677+
for (const auto & aCdt : aVBest)
678+
ShowSol(aCdt.mPose,aCdt.mMsg);
679+
}
680+
}
643681

644682
return aRes;
645683
}
@@ -751,6 +789,7 @@ class cAppli_OriRelPairOfIm : public cMMVII_Appli
751789

752790
cTimerSegm * mTimeSegm ;
753791
std::vector<const tNamePair *> mVecPairs;
792+
int mKSaveOri;
754793

755794
};
756795

@@ -773,7 +812,8 @@ cAppli_OriRelPairOfIm::cAppli_OriRelPairOfIm(const std::vector<std::string> & aV
773812
mUseOri4GT (false),
774813
mGTPose (tPoseR::Identity()),
775814
mPC1GT (nullptr),
776-
mPC2GT (nullptr)
815+
mPC2GT (nullptr),
816+
mKSaveOri (0)
777817
{
778818
}
779819

@@ -811,7 +851,7 @@ cCollecSpecArg2007 & cAppli_OriRelPairOfIm::ArgObl(cCollecSpecArg2007 & anArgObl
811851

812852
cCollecSpecArg2007 & cAppli_OriRelPairOfIm::ArgOpt(cCollecSpecArg2007 & anArgOpt)
813853
{
814-
return anArgOpt
854+
anArgOpt
815855
<< mPhProj.DPTieP().ArgDirInOpt()
816856
<< mPhProj.DPGndPt2D().ArgDirInOpt()
817857
<< mPhProj.DPMulTieP().ArgDirInOpt()
@@ -829,6 +869,14 @@ cCollecSpecArg2007 & cAppli_OriRelPairOfIm::ArgOpt(cCollecSpecArg2007 & anArgOpt
829869
<< AOpt2007(mParamOutLayer,"OutLayers","Param for generating outlayers [Nb,Sigma]",{{eTA2007::ISizeV,"[2,2]"}})
830870
<< AOpt2007(mShow,"Show","Show messages",{eTA2007::HDV})
831871
;
872+
873+
if (mModeCompute==0)
874+
{
875+
anArgOpt << mPhProj.DPOrient().ArgDirOutOpt("OriOut","For saving relative or as orientations")
876+
<< AOpt2007(mKSaveOri,"KSaveOri","Num of sol to save",{eTA2007::HDV}) ;
877+
}
878+
879+
return anArgOpt;
832880
}
833881

834882

@@ -858,6 +906,8 @@ std::vector<std::string> cAppli_OriRelPairOfIm::Samples() const
858906

859907
int cAppli_OriRelPairOfIm::Exe()
860908
{
909+
910+
861911
mTimeSegm = mShow ? new cTimerSegm(this) : nullptr ;
862912
mPhProj.FinishInit();
863913

@@ -923,6 +973,8 @@ int cAppli_OriRelPairOfIm::DoPairsOf1Im()
923973
{
924974
if (aPair->V1() == mIm1)
925975
{
976+
if (mShow)
977+
StdOut() << "====== DoPairsOf1Im, V2=" << aPair->V2() << "========\n";
926978
tRes1Pair aRes = EstimatePose2IM(aPair->V1(), aPair->V2());
927979
aRes.second.mIm1 = mIm1;
928980
aRes.second.mIm2 = aPair->V2();
@@ -951,6 +1003,10 @@ int cAppli_OriRelPairOfIm::DoPairsOf1Im()
9511003
cAppli_OriRelPairOfIm::tRes1Pair
9521004
cAppli_OriRelPairOfIm::EstimatePose2IM(const std::string& aIm1,const std::string& aIm2)
9531005
{
1006+
// For debuging/tuning we must have the same behaviour when we run 1 pair or multiple pair,
1007+
// so to have the same random number in ransac we re initialize the number generator at each pair
1008+
cRandGenerator::TheOne()->setSeed(42);
1009+
9541010
mIm1 = aIm1;
9551011
mIm2 = aIm2;
9561012
OrderMinMax(mIm1,mIm2);
@@ -1024,7 +1080,8 @@ cAppli_OriRelPairOfIm::tRes1Pair
10241080
mCalib1 = mPhProj.InternalCalibFromImage(mIm1);
10251081
mCalib2 = mPhProj.InternalCalibFromImage(mIm2);
10261082

1027-
mEstimatePose = new cEstimatePosRel2Im(*mCalib1,*mCalib2,mCpleHFull,mCpleHAvg,mCpleHSmall,mDensitySol,mTimeSegm);
1083+
mEstimatePose = new cEstimatePosRel2Im
1084+
(aIm1,aIm2,*mCalib1,*mCalib2,mCpleHFull,mCpleHAvg,mCpleHSmall,mDensitySol,mTimeSegm);
10281085
if (mUseOri4GT)
10291086
mEstimatePose->SetGT(mGTPose);
10301087

@@ -1036,6 +1093,18 @@ cAppli_OriRelPairOfIm::tRes1Pair
10361093
if (mDo5Pts)
10371094
Generate5Pts(aCdt.mVCdt.at(0).mPose);
10381095

1096+
if (mPhProj.DPOrient().DirOutIsInit())
1097+
{
1098+
StdOut() << "OUT=" << mPhProj.DPOrient().DirOut() << "\n";
1099+
const auto & aC = aCdt.mVCdt.at(mKSaveOri);
1100+
1101+
cSensorCamPC aCam1(mIm1,tPoseR::Identity(),mCalib1);
1102+
cSensorCamPC aCam2(mIm2,aC.mPose,mCalib2);
1103+
mPhProj.SaveCamPC(aCam1);
1104+
mPhProj.SaveCamPC(aCam2);
1105+
1106+
}
1107+
10391108
/* if (mUseOri4GT && mShow)
10401109
mEstimatePose->ShowSol(mGTPose,"GroundTruh");*/
10411110

0 commit comments

Comments
 (0)