Commit f9acacb9 authored by Julien Michel's avatar Julien Michel

Ajout des histogrammes dans le viewer base et dans le viewer

Correction d'un bug dans RoadExtraction
Correction des applications pour prendre en compte le nouveau viewer
Il manque l'évolution de l'ICD, en cours
parent 4cfab6ef
......@@ -65,7 +65,7 @@ FixedSizeFullImageWidget<TPixel>
}
else
{
// this->GetInput()->Update();
Superclass::Init(x,y,w,h,l);
this->SetViewedRegion(this->GetInput()->GetLargestPossibleRegion());
this->label(l);
this->resize(x, y, w, h);
......@@ -102,7 +102,7 @@ bool
FixedSizeFullImageWidget<TPixel>
::UpdateOpenGlBufferedRegionRequested(void)
{
if(m_ImageLoaded)
if(m_ImageLoaded && this->GetBufferedRegion().GetNumberOfPixels()!=0)
{
return false;
}
......
......@@ -55,12 +55,14 @@ void
FullResolutionImageWidget<TPixel>
::Init(int x, int y, int w, int h, const char * l)
{
if(!this->GetInput())
{
itkExceptionMacro("No input image!");
}
else
{
Superclass::Init(x,y,w,h,l);
if(this->GetImageOverlayVisible())
{
if(!this->GetInputOverlay())
......
......@@ -20,9 +20,11 @@ PURPOSE. See the above copyright notices for more information.
#include "itkProcessObject.h"
#include "itkFixedArray.h"
#include "otbImageWidgetTransfertFunction.h"
#include "FL/Fl_Gl_Window.H"
#include "otbMacro.h"
namespace otb
{
/** \class HistogramAndTransfertFunctionWidget
......@@ -31,7 +33,7 @@ namespace otb
* \ingroup
* \ingroup
*/
template <class THistogram>
template <class THistogram, class TPixel>
class ITK_EXPORT HistogramAndTransfertFunctionWidget
: public Fl_Gl_Window, public itk::ProcessObject
{
......@@ -49,15 +51,28 @@ class ITK_EXPORT HistogramAndTransfertFunctionWidget
itkTypeMacro(HistogramAndTransfertFunctionWidget,ProcessObject);
/** Template parameters typedefs */
typedef TPixel PixelType;
typedef THistogram HistogramType;
typedef typename HistogramType::ValueType::ValueType ValueType;
typedef typename HistogramType::ConstPointer HistogramConstPointerType;
typedef typename HistogramType::ConstIterator HistogramIteratorType;
typedef itk::FixedArray<double,3> ColorType;
typedef otb::ImageWidgetTransfertFunction<PixelType> TransfertFunctionType;
typedef typename TransfertFunctionType::Pointer TransfertFunctionPointerType;
typedef otb::ImageWidgetAffineTransfertFunction<PixelType> AffineTransfertFunctionType;
itkSetMacro(Histogram,HistogramConstPointerType);
itkGetMacro(Histogram,HistogramConstPointerType);
itkGetMacro(TransfertFunction,TransfertFunctionPointerType);
virtual void SetTransfertFunction(TransfertFunctionType * function)
{
m_TransfertFunction = function;
this->Modified();
}
itkSetMacro(HistogramColor,ColorType);
itkGetMacro(HistogramColor,ColorType);
itkSetMacro(BackgroundColor,ColorType);
......@@ -66,14 +81,20 @@ class ITK_EXPORT HistogramAndTransfertFunctionWidget
itkGetMacro(AxisColor,ColorType);
itkSetMacro(TextColor,ColorType);
itkGetMacro(TextColor,ColorType);
itkSetMacro(TransfertFunctionColor,ColorType);
itkGetMacro(TransfertFunctionColor,ColorType);
itkSetMacro(Label,std::string);
itkGetMacro(Label,std::string);
itkSetMacro(TransfertFunctionLabel,std::string);
itkGetMacro(TransfertFunctionLabel,std::string);
itkSetMacro(MarginX,double);
itkGetMacro(MarginX,double);
itkSetMacro(MarginY,double);
itkGetMacro(MarginY,double);
itkSetMacro(OutputHistogramMargin,double);
itkGetMacro(OutputHistogramMargin,double);
itkSetMacro(GridSizeX,unsigned int);
itkGetMacro(GridSizeX,unsigned int);
......@@ -100,7 +121,15 @@ protected:
virtual void HistogramRendering(double binWidth, double binHeightRatio, double maxFrequency);
virtual void LegendRendering(double gridXSpacing, double gridYSpacing, double maxFrequency);
virtual void TransfertFunctionRendering(void);
virtual void OutputHistogramRendering(void);
virtual void BoundRendering(void);
virtual void TransfertFunctionLabelRendering(void);
private:
HistogramAndTransfertFunctionWidget(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
......@@ -108,20 +137,33 @@ private:
/** The histogram to draw */
HistogramConstPointerType m_Histogram;
/** The transfert function */
TransfertFunctionPointerType m_TransfertFunction;
/** Colors */
ColorType m_HistogramColor;
ColorType m_BackgroundColor;
ColorType m_AxisColor;
ColorType m_GridColor;
ColorType m_TextColor;
ColorType m_TransfertFunctionColor;
ColorType m_BoundColor;
/** Margin around histogram */
double m_MarginX;
double m_MarginY;
double m_OutputHistogramMargin;
/** Set grid spatial frequency */
unsigned int m_GridSizeX;
unsigned int m_GridSizeY;
/** Percentage of the max frequency beeing thresholded */
double m_HistogramClamping;
/** Updating flag */
bool m_Updating;
/** Label of the histogram */
std::string m_Label;
/** Label of the histogram */
std::string m_TransfertFunctionLabel;
};
}// End namespace otb
#ifndef OTB_MANUAL_INSTANTIATION
......
......@@ -21,16 +21,18 @@ PURPOSE. See the above copyright notices for more information.
#include "otbHistogramAndTransfertFunctionWidget.h"
#include "otbGluPolygonDrawingHelper.h"
#include <FL/gl.h>
#include <FL/Fl.H>
namespace otb
{
template <class THistogram>
HistogramAndTransfertFunctionWidget<THistogram>
template <class THistogram, class TPixel>
HistogramAndTransfertFunctionWidget<THistogram,TPixel>
::HistogramAndTransfertFunctionWidget()
: Fl_Gl_Window(0,0,0,0,0)
{
m_Label = "Default label";
m_TransfertFunctionLabel = "Function label";
m_HistogramColor[0]=0.5;
m_HistogramColor[1]=0.5;
m_HistogramColor[2]=0.5;
......@@ -46,17 +48,27 @@ HistogramAndTransfertFunctionWidget<THistogram>
m_GridColor[0]=0.75;
m_GridColor[1]=0.75;
m_GridColor[2]=0.75;
m_TransfertFunctionColor[0]=1;
m_TransfertFunctionColor[1]=0;
m_TransfertFunctionColor[2]=0;
m_BoundColor[0]=0;
m_BoundColor[1]=1;
m_BoundColor[2]=0;
m_TransfertFunction = NULL;
m_Histogram = NULL;
m_MarginX = 25;
m_MarginX = 30;
m_MarginY = 30;
m_GridSizeX=5;
m_GridSizeY=5;
m_OutputHistogramMargin = 100;
m_HistogramClamping = 1;
m_Updating = false;
}
template <class THistogram>
template <class THistogram, class TPixel>
void
HistogramAndTransfertFunctionWidget<THistogram>
HistogramAndTransfertFunctionWidget<THistogram,TPixel>
::OpenGlSetup()
{
if (!this->valid())
......@@ -79,9 +91,9 @@ HistogramAndTransfertFunctionWidget<THistogram>
glDisable(GL_BLEND);
}
template <class THistogram>
template <class THistogram, class TPixel>
void
HistogramAndTransfertFunctionWidget<THistogram>
HistogramAndTransfertFunctionWidget<THistogram,TPixel>
::GridRendering(double gridXSpacing, double gridYSpacing)
{
double x,y;
......@@ -102,15 +114,15 @@ HistogramAndTransfertFunctionWidget<THistogram>
y=static_cast<double>(i)*gridYSpacing+m_MarginY;
x=m_MarginX;
glVertex2d(x,y);
x = static_cast<double>(this->w())-m_MarginX;
x = static_cast<double>(this->w())-m_MarginX-m_OutputHistogramMargin;
glVertex2d(x,y);
}
glEnd();
}
template <class THistogram>
template <class THistogram, class TPixel>
void
HistogramAndTransfertFunctionWidget<THistogram>
HistogramAndTransfertFunctionWidget<THistogram,TPixel>
::AxisRendering(void)
{
glBegin(GL_LINES);
......@@ -118,13 +130,13 @@ HistogramAndTransfertFunctionWidget<THistogram>
glVertex2d(m_MarginX,m_MarginY);
glVertex2d(m_MarginX,static_cast<double>(this->h())-m_MarginY/2);
glVertex2d(m_MarginX,m_MarginY);
glVertex2d(static_cast<double>(this->w())-m_MarginX/2,m_MarginY);
glVertex2d(static_cast<double>(this->w())-m_MarginX/2-m_OutputHistogramMargin,m_MarginY);
glEnd();
}
template <class THistogram>
template <class THistogram, class TPixel>
void
HistogramAndTransfertFunctionWidget<THistogram>
HistogramAndTransfertFunctionWidget<THistogram,TPixel>
::HistogramRendering(double binWidth, double binHeightRatio, double maxFrequency)
{
HistogramIteratorType it;
......@@ -142,7 +154,7 @@ HistogramAndTransfertFunctionWidget<THistogram>
x =startx;
y = m_MarginY;
drawer.Vertex2d(x,y);
y += binHeightRatio*static_cast<double>(it.GetFrequency());
y += binHeightRatio*static_cast<double>((it.GetFrequency()>maxFrequency/m_HistogramClamping ? maxFrequency/m_HistogramClamping : it.GetFrequency()));
drawer.Vertex2d(x,y);
x += binWidth;
drawer.Vertex2d(x,y);
......@@ -153,9 +165,36 @@ HistogramAndTransfertFunctionWidget<THistogram>
}
}
template <class THistogram>
template <class THistogram, class TPixel>
void
HistogramAndTransfertFunctionWidget<THistogram>
HistogramAndTransfertFunctionWidget<THistogram,TPixel>
::BoundRendering(void)
{
double x,y;
// Rendering bounds
glColor3d(m_BoundColor[0],m_BoundColor[1],m_BoundColor[2]);
glBegin(GL_LINES);
double factor = (m_Histogram->Quantile(0,1.)-m_Histogram->Quantile(0,0.))
/(static_cast<double>(this->w())-2*m_MarginX-m_OutputHistogramMargin);
x = m_MarginX + static_cast<double>(m_TransfertFunction->GetLowerBound())/factor;
y = m_MarginY;
glVertex2d(x,y);
y = static_cast<double>(this->h())-m_MarginY;
glVertex2d(x,y);
x = m_MarginX + static_cast<double>(m_TransfertFunction->GetUpperBound())/factor;
glVertex2d(x,y);
y= m_MarginY;
glVertex2d(x,y);
glEnd();
}
template <class THistogram, class TPixel>
void
HistogramAndTransfertFunctionWidget<THistogram,TPixel>
::LegendRendering(double gridXSpacing, double gridYSpacing, double maxFrequency)
{
double x,y;
......@@ -163,14 +202,13 @@ HistogramAndTransfertFunctionWidget<THistogram>
itk::OStringStream oss;
glColor3d(m_TextColor[0],m_TextColor[1],m_TextColor[2]);
gl_font(FL_COURIER_BOLD,10);
double step = (m_Histogram->Quantile(0,1.)-m_Histogram->Quantile(0,0.))
/static_cast<double>(m_GridSizeX);
for(unsigned int i=0;i<m_GridSizeX;++i)
{
double step = (m_Histogram->Quantile(0,1.)-m_Histogram->Quantile(0,0.))
/static_cast<double>(m_GridSizeX);
ValueType value = static_cast<ValueType>(m_Histogram->Quantile(0,0.)
+static_cast<double>(i)*step);
std::cout<<step<<std::endl;
oss<<value;
oss<<(int)value;
x=static_cast<double>(i)*gridXSpacing+m_MarginX;
y=m_MarginY/2;
gl_draw(oss.str().c_str(),(float)x,(float)y);
......@@ -178,8 +216,8 @@ HistogramAndTransfertFunctionWidget<THistogram>
}
for(unsigned int i=0;i<m_GridSizeY;++i)
{
double value = static_cast<double>(i)
*maxFrequency/static_cast<double>(m_GridSizeY);
unsigned int value = static_cast<unsigned int>(i
*maxFrequency/(m_HistogramClamping*static_cast<double>(m_GridSizeY)));
oss<<value;
y=static_cast<double>(i)*gridYSpacing+m_MarginY;
x=0;
......@@ -192,17 +230,127 @@ HistogramAndTransfertFunctionWidget<THistogram>
}
template <class THistogram>
template <class THistogram, class TPixel>
void
HistogramAndTransfertFunctionWidget<THistogram,TPixel>
::TransfertFunctionRendering()
{
glColor3d(m_TransfertFunctionColor[0],m_TransfertFunctionColor[1],m_TransfertFunctionColor[2]);
glBegin(GL_LINE_STRIP);
double x,y;
double step = (m_Histogram->Quantile(0,1.)-m_Histogram->Quantile(0,0.))
/static_cast<double>(m_Histogram->GetSize()[0]);
double xscale = (static_cast<double>(this->w())-2*m_MarginX-m_OutputHistogramMargin)/static_cast<double>(m_Histogram->GetSize()[0]);
double yscale = (static_cast<double>(this->h())-2*m_MarginY)/255.;
for(unsigned int i=0;i<m_Histogram->Size()+1;++i)
{
PixelType value = static_cast<PixelType>(m_Histogram->Quantile(0,0.)
+static_cast<double>(i)*step);
x = m_MarginX + static_cast<double>(i)*xscale;
y = m_MarginY + yscale * static_cast<double>(m_TransfertFunction->Map(value));
glVertex2d(x,y);
}
glEnd();
}
template <class THistogram, class TPixel>
void
HistogramAndTransfertFunctionWidget<THistogram,TPixel>
::OutputHistogramRendering()
{
std::vector<unsigned int> outputHistogram(256,0);
HistogramIteratorType it;
for(it=m_Histogram->Begin();it!=m_Histogram->End();++it)
{
outputHistogram[m_TransfertFunction->Map(static_cast<PixelType>(it.GetMeasurementVector()[0]))]+=static_cast<unsigned int>(it.GetFrequency());
}
// Setting the extremity to 0 to avoid sides effect
outputHistogram[0]=0;
outputHistogram[255]=0;
std::vector<unsigned int>::iterator vit;
unsigned int maxFrequency = 0;
for(vit=outputHistogram.begin();vit!=outputHistogram.end();++vit)
{
if(maxFrequency<(*vit))
{
maxFrequency=(*vit);
}
}
// Temporary vertex coordinates
double x,y;
if(maxFrequency>0)
{
otb::GluPolygonDrawingHelper drawer;
double binWidth = (static_cast<double>(this->h())-2*m_MarginY)/255.;
double binLengthRatio = m_HistogramClamping*m_OutputHistogramMargin/static_cast<double>(maxFrequency);
double starty = m_MarginY;
// Rendering histogram
for(vit=outputHistogram.begin();vit!=outputHistogram.end();++vit,starty+=binWidth)
{
drawer.Color3d(m_TransfertFunctionColor[0],m_TransfertFunctionColor[1],m_TransfertFunctionColor[2]);
drawer.BeginPolygon();
drawer.BeginContour();
x =static_cast<double>(this->w())-m_OutputHistogramMargin-m_MarginX/2;
y = starty;
drawer.Vertex2d(x,y);
x += binLengthRatio*static_cast<double>((*vit)> maxFrequency/m_HistogramClamping ? maxFrequency/m_HistogramClamping : (*vit));
drawer.Vertex2d(x,y);
y += binWidth;
drawer.Vertex2d(x,y);
x =static_cast<double>(this->w())-m_OutputHistogramMargin-m_MarginX/2;
drawer.Vertex2d(x,y);
drawer.EndContour();
drawer.EndPolygon();
}
}
glBegin(GL_LINE_LOOP);
x = static_cast<double>(this->w())-m_OutputHistogramMargin-m_MarginX/2;
y = m_MarginY;
glVertex2d(x,y);
x+=m_OutputHistogramMargin;
glVertex2d(x,y);
y = static_cast<double>(this->h())-m_MarginY;
glVertex2d(x,y);
x = static_cast<double>(this->w())-m_OutputHistogramMargin-m_MarginX/2;
glVertex2d(x,y);
glEnd();
}
template <class THistogram, class TPixel>
void
HistogramAndTransfertFunctionWidget<THistogram,TPixel>
::TransfertFunctionLabelRendering(void)
{
//rendering label
gl_font(FL_COURIER_BOLD,12);
gl_draw(m_TransfertFunctionLabel.c_str(),static_cast<float>(this->w()-m_MarginX/2-m_OutputHistogramMargin),static_cast<float>(m_MarginY/2));
}
template <class THistogram, class TPixel>
void
HistogramAndTransfertFunctionWidget<THistogram>
HistogramAndTransfertFunctionWidget<THistogram,TPixel>
::draw()
{
if(!m_Histogram)
{
return;
}
std::cout<<"Beginning histogram rendering."<<std::endl;
}
if(m_Updating)
return;
m_Updating = true;
double maxFrequency = 0;
HistogramIteratorType it;
......@@ -216,9 +364,9 @@ HistogramAndTransfertFunctionWidget<THistogram>
}
}
double binWidth = static_cast<double>(this->w()-2*m_MarginX)/static_cast<double>(m_Histogram->GetSize()[0]);
double binHeightRatio = static_cast<double>(this->h()-2*m_MarginY)/static_cast<double>(maxFrequency);
double gridXSpacing = (static_cast<double>(this->w())-2*m_MarginX)/static_cast<double>(m_GridSizeX);
double binWidth = static_cast<double>(this->w()-2*m_MarginX-m_OutputHistogramMargin)/static_cast<double>(m_Histogram->GetSize()[0]);
double binHeightRatio = m_HistogramClamping*static_cast<double>(this->h()-2*m_MarginY)/static_cast<double>(maxFrequency);
double gridXSpacing = (static_cast<double>(this->w())-2*m_MarginX-m_OutputHistogramMargin)/static_cast<double>(m_GridSizeX);
double gridYSpacing = (static_cast<double>(this->h())-2*m_MarginY)/static_cast<double>(m_GridSizeY);
OpenGlSetup();
......@@ -227,12 +375,20 @@ HistogramAndTransfertFunctionWidget<THistogram>
HistogramRendering(binWidth,binHeightRatio,maxFrequency);
LegendRendering(gridXSpacing,gridYSpacing,maxFrequency);
std::cout<<"End of histogram rendering."<<std::endl;
if(m_TransfertFunction)
{
BoundRendering();
TransfertFunctionRendering();
OutputHistogramRendering();
TransfertFunctionLabelRendering();
}
m_Updating = false;
}
template <class THistogram>
template <class THistogram, class TPixel>
void
HistogramAndTransfertFunctionWidget<THistogram>
HistogramAndTransfertFunctionWidget<THistogram,TPixel>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os,indent);
......
......@@ -79,6 +79,7 @@ class ITK_EXPORT ImageViewer
Fl_Window * m_ScrollWindow;
Fl_Window * m_ZoomWindow;
Fl_Window * m_PixLocWindow;
Fl_Window * m_HistogramWindow;
Fl_Multiline_Output * m_PixLocOutput;
};
} // end namespace otb
......
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _otbImageViewer_txx
#define _otbImageViewer_txx
#include "otbImageViewer.h"
......@@ -23,6 +23,7 @@ namespace otb
m_FullWindow=NULL;
m_ZoomWindow=NULL;
m_ScrollWindow=NULL;
m_HistogramWindow=NULL;
m_PixLocWindow=NULL;
m_PixLocOutput=NULL;
}
......@@ -31,36 +32,48 @@ namespace otb
ImageViewer<TPixel,TLabel>
::~ImageViewer()
{
if(m_HistogramWindow!=NULL)
{
m_HistogramWindow->remove(this->GetRedHistogramWidget());
if(this->GetFullWidget()->GetViewModelIsRGB())
{
m_HistogramWindow->remove(this->GetGreenHistogramWidget());
m_HistogramWindow->remove(this->GetBlueHistogramWidget());
}
delete m_HistogramWindow;
m_HistogramWindow = NULL;
}
if (m_FullWindow!=NULL)
{
m_FullWindow->remove(this->GetFullWidget());
delete m_FullWindow;
m_FullWindow = NULL;
}
{
m_FullWindow->remove(this->GetFullWidget());
delete m_FullWindow;
m_FullWindow = NULL;
}
if(m_ZoomWindow!=NULL)
{
m_ZoomWindow->remove(this->GetZoomWidget());
delete m_ZoomWindow;
m_ZoomWindow = NULL;
}
{
m_ZoomWindow->remove(this->GetZoomWidget());
delete m_ZoomWindow;
m_ZoomWindow = NULL;
}
if(m_ScrollWindow!=NULL)
{
m_ScrollWindow->remove(this->GetScrollWidget());
delete m_ScrollWindow;
m_ScrollWindow = NULL;
}
{
m_ScrollWindow->remove(this->GetScrollWidget());
delete m_ScrollWindow;
m_ScrollWindow = NULL;
}
if(m_PixLocWindow!=NULL)
{
m_PixLocWindow->remove(m_PixLocOutput);
delete m_PixLocWindow;
m_PixLocWindow = NULL;
}
{
m_PixLocWindow->remove(m_PixLocOutput);
delete m_PixLocWindow;
m_PixLocWindow = NULL;
}
if(m_PixLocOutput!=NULL)
{
delete m_PixLocOutput;
m_PixLocOutput = NULL;
}
{
delete m_PixLocOutput;
m_PixLocOutput = NULL;
}
}
/// Build the HMI
......@@ -68,26 +81,56 @@ namespace otb
void
ImageViewer<TPixel,TLabel>
::Build(void)
{
Superclass::Build();
itk::OStringStream oss;
int wfull = this->GetFullWidget()->w();
int hfull = this->GetFullWidget()->h();
itk::OStringStream oss;
int wfull = this->GetFullWidget()->w();
int hfull = this->GetFullWidget()->h();
oss.str("");
oss<<this->GetLabel()<<" - Full Window";
m_FullWindow = new Fl_Window(0,0,wfull,hfull,"");
m_FullWindow->copy_label(oss.str().c_str());
m_FullWindow->add(this->GetFullWidget());
m_FullWindow->resizable(this->GetFullWidget());
m_FullWindow->end();