From 3528cdf2f736a92ecf4bdd3e314f6066511e54c5 Mon Sep 17 00:00:00 2001 From: deseilligny Date: Sun, 26 May 2024 15:48:31 +0200 Subject: [PATCH 1/4] Doc, chg ordi. --- MMVII/Doc/Programmer/ImagesClasses.tex | 256 ++++++++++++++++++++++--- MMVII/include/MMVII_Images.h | 13 +- 2 files changed, 241 insertions(+), 28 deletions(-) diff --git a/MMVII/Doc/Programmer/ImagesClasses.tex b/MMVII/Doc/Programmer/ImagesClasses.tex index 869047e80..62f7607cb 100755 --- a/MMVII/Doc/Programmer/ImagesClasses.tex +++ b/MMVII/Doc/Programmer/ImagesClasses.tex @@ -9,8 +9,10 @@ \chapter{Classes for images} \section{Introduction} -Also \PPP is not specificamly an image processing library, there are several part where -image are used to extract information and, at the end, image processing is a non neglectable part +Also \PPP is not specifically an image processing library, there are several parts where +image are used to extract information (for example target detection) or as data helpfull +for other processing (for example tabulating function for fast access) and, +at the end, image manipulation is a non neglectable part of the code. This chapter describe the general organization of image processing code. @@ -20,41 +22,42 @@ \section{Introduction} -%--------------------------------------------- +%--------------------------------------------- +%--------------------------------------------- +%--------------------------------------------- \section{Files organization } We begin by a description of files and folder related to images. - % - - - - - - - - - - - - - - - +%---------------------------------------------------------------------------------------- \subsection{Connected files} Note the following files that are not directly image files, but are strongly connected : \begin{itemize} - \item {\tt MMVII\_Ptxd.h} contain the definition of points, and consquently of pixels (point + \item {\tt MMVII\_Ptxd.h} contain the definition of points, and consequently of pixels (point with integers coordinates), contains the definition of boxes (and images inherit of boxes); \item {\tt MMVII\_Matrix.h} dense vector and dense matrix can be regarded as images ($1$ or $2$ dim), so in \PPP they are implemented as a shell arround images of dimension $1$ or $2$ - - \end{itemize} - % - - - - - - - - - - - - - - - + +%---------------------------------------------------------------------------------------- \subsection{Header files} -The file containing class representing images are essentially : +The file containing classes for representing images are essentially : \begin{itemize} \item {\tt MMVII\_Images.h} this file contain the classes for representing generic images indepently of their dimension; it contains also the classes specific to images of dimension $1$ and $3$, - which play a minor role: + which play a role less important then $2d$ images; \item {\tt MMVII\_Image2D.h} this file contain the classes specific to $2$-dimensionnal images which obviously are the more frequent and more devlopped. @@ -81,7 +84,7 @@ \subsection{Header files} \end{itemize} -The following files contains direcly the code of the function they implemant : +The following header files contains direcly the code of the function they implemant : \begin{itemize} \item {\tt MMVII\_TplGradImFilter.h} contains code for gradient with optimization @@ -103,7 +106,7 @@ \subsection{Header files} \end{itemize} - % - - - - - - - - - - - - - - - +%---------------------------------------------------------------------------------------- \subsection{Cpp files} @@ -149,36 +152,243 @@ \section{Numerical types} \section{General image organization} +%---------------------------------------------------------------------------------------- + \subsection{Parameter of image classes} -A class of image is parametrized by $2$ value : +A class of image is parametrized by $2$ elements : \begin{itemize} - \item the type on which is code each elements , it must be one of the numerical types - defined in \label{NumericalType} + \item the type on which is coded each elements , it must be one of the numerical types + defined in \label{NumericalType}; - \item the dimension of the image, the value can be $1$, $2$ or $3$ (there exist + \item the dimension of the image, the value can be $1$, $2$ or $3$ for now (there exist also unlimited dimension image, see ~\ref{UlimDimIm} , but less efficient); \end{itemize} -For maximal efficient manipulation, the code must "know" the type and the dimension +For maximal efficiency manipulation, the code must "know" the type and the dimension of the image. For example if we manipulate $2d$ images with integer element -include in $[0,255]$: , we will use images of type {\tt cDataIm2D}, -and this class will contain a field {\tt mRawData} of type {\tt tU\_INT1} +include in $[0,255]$: we will use images of type {\tt cDataIm2D}, +and this class will contain a field {\tt mRawData2D} of type {\tt tU\_INT1 **} such that the reference to the value of $1$ pixel can be extracted by {\tt mRawData[y][x]}. +There exist aslo class {\tt cDataIm3D} containing a field {\tt mRawData3D} of type {\tt Type ***}, + and {\tt cDataIm1D} containing a field {\tt mRawData1D} of type {\tt Type *}. Also some time it is interesting for limitating the size of code to maninuplate images independantly of their dimension or type. Sometime because this can be done as efficiently -as when we now the type and dimension, or sometime because effficiency is just not our priority. +as when we now the type and dimension, or sometime because effficiency is just not our priority. In +both case we avoid code duplication. This is the role of classes {\tt cDataTypedIm} and {\tt cDataGenUnTypedIm}. + + +The class {\tt cDataTypedIm} implement the code that can be written generically without using +the value of {\tt mRawData1D, mRawData2D, mRawData3D}. Then {\tt cDataIm1D} inherits of {\tt cDataTypedIm}, +{\tt cDataIm2D} inherits of {\tt cDataTypedIm} an {\tt cDataIm3D} inherits of class {\tt cDataTypedIm}. + + +The class {\tt cDataGenUnTypedIm} implement de functionnality of images that can be written +independantly of the type of element used to store numerical values. The class {\tt cDataTypedIm} +inherits from {\tt cDataGenUnTypedIm}. + + +%---------------------------------------------------------------------------------------- + +\subsection{Classes {\tt cDataGenUnTypedIm}} + + + % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- + +\subsubsection{{\tt cDataGenUnTypedIm} as rectangular objects } + +The class {\tt cDataGenUnTypedIm} is at the highest level in image inheritance +hierachy. Each {\tt cDataGenUnTypedIm} is defined on a "rectangular" footprint +and consequently they inherit from class {\tt cPixBox}. + +As a {\tt cPixBox}, all the pixels of a {\tt cDataGenUnTypedIm} can be parsed +using iterators, and code likes this one are current in {\tt MMVII} library : + +\lstset {language=C++} +\begin{lstlisting} + // iterate all the pixel + for (const auto & aP : aIm) + { + // do something with all pixel of image + } + + // iterate all the pixel execpt bordder 3 + for (const auto & aPix : cRect2(mDIm.Dilate(-3))) + { + // do something with all pixel of image except border + } + + // iterate all the pixel on the border + cBorderPixBox aBorder(mIBoxIn,2); + for (const auto& aPix : aBorder) + { + // do something with border + } +\end{lstlisting} + + % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- + +\subsubsection{Generic access to pixel-values} + +\label{GenPixVal} + +It is possible to manipulate the value of {\tt cDataGenUnTypedIm} pixel by pixel. As +we do not know the type, the method are pure virtual method that will be defined in +inheriting classes (in the {\tt cDataImXD}) : + +\begin{itemize} + \item {\tt VI\_GetV} and {\tt VD\_GetV} for reading the value of an \emph{integer} pixel + in integer or floating point value; + + \item {\tt VI\_SetV} and {\tt VD\_SetV} for setting the value of an \emph{integer} pixel + from an integer or floating point value; + + \item {\tt GetVBL} for reading the value of a \emph{real} pixel using a N-Linear method + (aka bilinear for $2d$ images). +\end{itemize} + +%---------------------------------------------------------------------------------------- + +\subsection{Classes {\tt cDataTypedIm}} + + % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- + +\subsubsection{Generalities} + +This class is used for implemanting all what can be done without +knowing the pointers {\tt mRawData1D, mRawData2D, mRawData3D}. +The {\tt cDataTypedIm} contain a field {\tt mRawDataLin} of +type {\tt Type *} that contain the actual data of the image. +In the derived classes the fields {\tt mRawDataXD} will point +to {\tt mRawDataLin} as illustrated with figure~\ref{fig:Ptr2D}. + + + +\begin{figure} +\centering +\includegraphics[width=6cm]{Programmer/ImagesProg/PtrIm2D.jpg} +\caption{Structure for {\tt mRawDataXD} vs {\tt mRawDataLin}} +\label{fig:Ptr2D} +\end{figure} + +Here is an extract of the initalization of class {\tt cDataIm2D} to better understand +the way it works. + + +\lstset {language=C++} +\begin{lstlisting} + for (int aY=Y0() ; aY -%template class cDataIm2D : public cDataTypedIm %--------------------------------------------- %--------------------------------------------- diff --git a/MMVII/include/MMVII_Images.h b/MMVII/include/MMVII_Images.h index 663380eac..57a142222 100755 --- a/MMVII/include/MMVII_Images.h +++ b/MMVII/include/MMVII_Images.h @@ -294,21 +294,24 @@ template class cDataGenUnTypedIm : public cPixBox, typedef cPixBox tPB; const tPB & RO() {return *this;} + typedef cPtxd tPixI + typedef cPtxd tPixR +; cDataGenUnTypedIm(const cPtxd & aP0,const cPtxd & aP1); // Get Value, integer coordinates /// Pixel -> Integrer Value - virtual int VI_GetV(const cPtxd & aP) const =0; + virtual int VI_GetV(const tPixI & aP) const =0; /// Pixel -> float Value - virtual double VD_GetV(const cPtxd & aP) const =0; + virtual double VD_GetV(const tPixI & aP) const =0; // Set Value, integer coordinates /// Set Pixel Integrer Value - virtual void VI_SetV(const cPtxd & aP,const int & aV) =0; + virtual void VI_SetV(const tPixI & aP,const int & aV) =0; /// Set Pixel Float Value - virtual void VD_SetV(const cPtxd & aP,const double & aV)=0 ; + virtual void VD_SetV(const tPixI & aP,const double & aV)=0 ; - virtual double GetVBL(const cPtxd & aP) const = 0; + virtual double GetVBL(const tPixR & aP) const = 0; }; From ac4fa272516d648af53be4c088cefcfba400c5f4 Mon Sep 17 00:00:00 2001 From: deseilligny Date: Sun, 26 May 2024 15:55:19 +0200 Subject: [PATCH 2/4] better when it compiles some files --- MMVII/include/MMVII_Images.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MMVII/include/MMVII_Images.h b/MMVII/include/MMVII_Images.h index 57a142222..5cf683bb9 100755 --- a/MMVII/include/MMVII_Images.h +++ b/MMVII/include/MMVII_Images.h @@ -294,8 +294,8 @@ template class cDataGenUnTypedIm : public cPixBox, typedef cPixBox tPB; const tPB & RO() {return *this;} - typedef cPtxd tPixI - typedef cPtxd tPixR + typedef cPtxd tPixI; + typedef cPtxd tPixR; ; cDataGenUnTypedIm(const cPtxd & aP0,const cPtxd & aP1); From 5f90017b4e9f6e270214992c8f2cc613bfe6490d Mon Sep 17 00:00:00 2001 From: deseilligny Date: Mon, 27 May 2024 09:52:17 +0200 Subject: [PATCH 3/4] Add fig missing --- MMVII/Doc/Programmer/ImagesProg/PtrIm2D.jpg | Bin 0 -> 40407 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 MMVII/Doc/Programmer/ImagesProg/PtrIm2D.jpg diff --git a/MMVII/Doc/Programmer/ImagesProg/PtrIm2D.jpg b/MMVII/Doc/Programmer/ImagesProg/PtrIm2D.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5a2382425a4638b7e89cb238105c76f5a9c44e0e GIT binary patch literal 40407 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 Date: Mon, 27 May 2024 17:52:11 +0200 Subject: [PATCH 4/4] Doc images --- MMVII/Doc/Programmer/ImagesClasses.tex | 45 ++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/MMVII/Doc/Programmer/ImagesClasses.tex b/MMVII/Doc/Programmer/ImagesClasses.tex index 62f7607cb..131c02def 100755 --- a/MMVII/Doc/Programmer/ImagesClasses.tex +++ b/MMVII/Doc/Programmer/ImagesClasses.tex @@ -267,6 +267,7 @@ \subsubsection{Generalities} + \begin{figure} \centering \includegraphics[width=6cm]{Programmer/ImagesProg/PtrIm2D.jpg} @@ -370,7 +371,7 @@ \subsection{Elementary access} %---------------------------------------------------------------------------------------- \subsection{Raw pointer and data organization} -Note also that the class export also access to raw pointer and {\tt mRawDataXD} , {\tt mRawDataLin} +Note also that the class exports also access to raw pointer and {\tt mRawDataXD} , {\tt mRawDataLin} or a specific line with {\tt GetLine}, these access can be usefull for : @@ -383,12 +384,29 @@ \subsection{Raw pointer and data organization} \end{itemize} +Regarding the data organisation for image with dimension $\geq 2$, the convention +is to access {\tt mRawData2D[y][x]} or {\tt mRawData3D[z][y][x]} . This convention +comes from the fact that in image file formats the consecutive pixel are on the same +line (vs the same column). For {\tt mRawDataLin}, the organization is the generalization +of convention of figure~\ref{fig:Ptr2D}, for example : + +\begin{equation} + mRawData3D[z][y][x] = mRawDataLin[x + y * Sz_x + z * Sz_x * Sz_y] \label{EqIm3D} +\end{equation} %---------------------------------------------------------------------------------------- -\subsection{Memory management} +\subsection{Memory managementi and {\tt cDataImXD} vs {\tt cImXD} } +For safety consideration, it is not possible to creat directly or to copy +the objects of type {\tt cDataImXD} . The way it work is : + +\begin{itemize} + \item the object that can be created are {\tt cImXD} (i.e {\tt cIm1D, cIm2D, cIm3D }) + \item the {\tt cImXD} are shared pointer to {\tt cDataImXD}, the reference to the {\tt cDataImXD} can + be extracted via the method {\tt DIm()}. +\end{itemize} %--------------------------------------------- %--------------------------------------------- @@ -397,7 +415,28 @@ \subsection{Memory management} \section{Unlimited dimension image} \label{UlimDimIm} -Classe {\tt cDataGenDimTypedIm} +\PPP propose also a class for images of any dimension. The manipulation is +certainly slower than the specialized version {\tt cDataImXD}, but can be usefull +for image of dimension $4,5 \dots 10$ for creating a prototype or when performance +is not the main issue. + +Basically for these images : + +\begin{itemize} + \item the constructor take as argument the dimension of the image (i.e. the dimension + is not contained in the type, but is a value of the object) + + \item the access to "pixels" is done via dense vector of type int ({\tt cDenseVect}) , + internaly the data is stored on a linear vector and the conversion is done via + the generalization of formula like equation \ref{EqIm3D} ; + + \item access to linear interpolation can also be done via ({\tt cDenseVect)}), by the + way it can be intrinsiqually slow (form dimension D, i.e. there $2^D$ values to access). +\end{itemize} + + + +