From 1f11a9d648925335666303378cd2c486fcb26fc1 Mon Sep 17 00:00:00 2001
From: aregimbeau <antoine.regimbeau@c-s.fr>
Date: Wed, 5 Jul 2017 18:14:16 +0200
Subject: [PATCH] First draw of the histogram equalisation working on
 black&white pictures and color ones

---
 Modules/Feature/Contrast/CMakeLists.txt       |  15 ++
 .../Contrast/otbContrastEnhancementFilter.cxx |  90 +++++++++++
 .../Contrast/otbContrastEnhancementFilter.h   |   0
 Modules/Filtering/Contrast/CMakeLists.txt     |  22 +++
 .../include/otbContrastEnhancementFilter.h    |   0
 Modules/Filtering/Contrast/otb-module.cmake   |  38 +++++
 .../Filtering/Contrast/test/CMakeLists.txt    |  29 ++++
 .../test/otbContrastEnhancementFilter.cxx     | 141 ++++++++++++++++++
 8 files changed, 335 insertions(+)
 create mode 100644 Modules/Feature/Contrast/CMakeLists.txt
 create mode 100644 Modules/Feature/Contrast/otbContrastEnhancementFilter.cxx
 create mode 100644 Modules/Feature/Contrast/otbContrastEnhancementFilter.h
 create mode 100644 Modules/Filtering/Contrast/CMakeLists.txt
 create mode 100644 Modules/Filtering/Contrast/include/otbContrastEnhancementFilter.h
 create mode 100644 Modules/Filtering/Contrast/otb-module.cmake
 create mode 100644 Modules/Filtering/Contrast/test/CMakeLists.txt
 create mode 100644 Modules/Filtering/Contrast/test/otbContrastEnhancementFilter.cxx

diff --git a/Modules/Feature/Contrast/CMakeLists.txt b/Modules/Feature/Contrast/CMakeLists.txt
new file mode 100644
index 0000000000..87d47ca879
--- /dev/null
+++ b/Modules/Feature/Contrast/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required (VERSION 2.6)
+project (projchambolle)
+
+find_package(OTB REQUIRED)
+include(${OTB_USE_FILE})
+
+
+set(SOURCES otbContrastEnhancementFilter.cxx)
+
+add_executable(Contrast otbContrastEnhancementFilter.cxx)
+
+target_link_libraries(Contrast ${OTB_LIBRARIES})
+
+
+# message(WARNING "Include dirs : ${OTB_INCLUDE_DIRS}")
\ No newline at end of file
diff --git a/Modules/Feature/Contrast/otbContrastEnhancementFilter.cxx b/Modules/Feature/Contrast/otbContrastEnhancementFilter.cxx
new file mode 100644
index 0000000000..37efcc9775
--- /dev/null
+++ b/Modules/Feature/Contrast/otbContrastEnhancementFilter.cxx
@@ -0,0 +1,90 @@
+#include <iostream>
+#include <math.h>
+#include "otbImage.h"
+#include "otbVectorImage.h"
+#include "otbImageFileReader.h"
+#include "otbImageFileWriter.h"
+#include "itkAdditiveGaussianNoiseImageFilter.h"
+#include "otbStreamingStatisticsImageFilter.h"
+#include "itkImageLinearIteratorWithIndex.h"
+#include "itkMultiplyImageFilter.h"
+#include "itkDivideImageFilter.h"
+#include "itkAbsImageFilter.h"
+#include "itkSubtractImageFilter.h"
+#include "itkAddImageFilter.h"
+#include "itkSquareImageFilter.h"
+#include "itkSqrtImageFilter.h"
+#include "itkMaximumImageFilter.h"
+
+typedef float                     PixelType;
+typedef itk::Image< PixelType , 2>  ImageType;
+typedef itk::AddImageFilter<ImageType, ImageType, ImageType>  AddFilterType;
+typedef  otb::StreamingStatisticsImageFilter<ImageType>      StatFilter;
+
+ImageType::Pointer 
+createImagefrom( ImageType::Pointer input )
+{
+  ImageType::Pointer cloneImage( ImageType::New() );
+  cloneImage->SetRegions( input->GetRequestedRegion() ); 
+  cloneImage->Allocate();
+  cloneImage->SetOrigin( input->GetOrigin() );
+  return cloneImage ;
+
+}
+void
+copyAtoB( const ImageType::Pointer input ,
+          ImageType::Pointer output )
+{
+  itk::ImageRegionConstIterator< ImageType > itinp( input , input->GetRequestedRegion() );
+  itk::ImageRegionIterator< ImageType >      itout( output , output->GetRequestedRegion() );
+  itinp.GoToBegin();
+  itout.GoToBegin();
+  while (!itinp.IsAtEnd())
+  {
+    itout.Set( itinp.Get() );
+    ++itout;
+    ++itinp;
+  }
+}
+
+void
+normL( ImageType::Pointer inputX ,
+       ImageType::Pointer inputY ,
+       ImageType::Pointer output )
+{
+  typedef itk::SquareImageFilter< ImageType , ImageType > SquareFilterType;
+  typedef itk::SqrtImageFilter< ImageType , ImageType > SqrtFitlerType;
+  SquareFilterType::Pointer square( SquareFilterType::New() );
+  SqrtFitlerType::Pointer sqrt( SqrtFitlerType::New() );
+  AddFilterType::Pointer add( AddFilterType::New() );
+  square->SetInput( inputX );
+  square->Update();
+  copyAtoB( square->GetOutput() , output );
+  add->SetInput1( output );
+  square->SetInput( inputY );
+  square->Update();
+  add->SetInput2( square->GetOutput() );
+  sqrt->SetInput( add->GetOutput() );
+  sqrt->Update();
+  copyAtoB( sqrt->GetOutput() , output );
+}
+
+int
+main( int argc, 
+      char const *argv[] )
+{
+	const char * inputFilename  = argv[ 1 ];
+  const char * outputFilename = argv[ 2 ];
+
+
+  typedef otb::ImageFileReader< ImageType > ReaderType;
+
+ 	ReaderType::Pointer reader( ReaderType::New() );
+ 	reader->SetFileName( argv[ 1 ] );
+
+  ImageType::Pointer noisyImage( ImageType::New() );
+
+  typedef otb::ImageFileWriter<ImageType>  WriterType;
+ 	WriterType::Pointer writer( WriterType::New());
+  return 0;
+}
\ No newline at end of file
diff --git a/Modules/Feature/Contrast/otbContrastEnhancementFilter.h b/Modules/Feature/Contrast/otbContrastEnhancementFilter.h
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Modules/Filtering/Contrast/CMakeLists.txt b/Modules/Filtering/Contrast/CMakeLists.txt
new file mode 100644
index 0000000000..45a89f243f
--- /dev/null
+++ b/Modules/Filtering/Contrast/CMakeLists.txt
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+#
+# This file is part of Orfeo Toolbox
+#
+#     https://www.orfeo-toolbox.org/
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+project(OTBContrast)
+otb_module_impl()
\ No newline at end of file
diff --git a/Modules/Filtering/Contrast/include/otbContrastEnhancementFilter.h b/Modules/Filtering/Contrast/include/otbContrastEnhancementFilter.h
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Modules/Filtering/Contrast/otb-module.cmake b/Modules/Filtering/Contrast/otb-module.cmake
new file mode 100644
index 0000000000..84da787da6
--- /dev/null
+++ b/Modules/Filtering/Contrast/otb-module.cmake
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+#
+# This file is part of Orfeo Toolbox
+#
+#     https://www.orfeo-toolbox.org/
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+set(DOCUMENTATION "work in progress")
+
+otb_module(OTBContrast
+  DEPENDS
+    OTBITK
+  	OTBCommon
+    OTBImageBase
+    
+
+  TEST_DEPENDS
+    OTBTestKernel
+    OTBImageIO
+    OTBImageBase
+  	
+
+  DESCRIPTION
+    "${DOCUMENTATION}"
+)
diff --git a/Modules/Filtering/Contrast/test/CMakeLists.txt b/Modules/Filtering/Contrast/test/CMakeLists.txt
new file mode 100644
index 0000000000..e6d3bf6920
--- /dev/null
+++ b/Modules/Filtering/Contrast/test/CMakeLists.txt
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+#
+# This file is part of Orfeo Toolbox
+#
+#     https://www.orfeo-toolbox.org/
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+otb_module_test()
+
+set(OTBContrastTests
+otbContrastEnhancementFilter.cxx
+)
+
+add_executable(otbContrastTestDriver ${OTBContrastTests})
+target_link_libraries(otbContrastTestDriver ${OTBContrast-Test_LIBRARIES})
+otb_module_target_label(otbContrastTestDriver)
diff --git a/Modules/Filtering/Contrast/test/otbContrastEnhancementFilter.cxx b/Modules/Filtering/Contrast/test/otbContrastEnhancementFilter.cxx
new file mode 100644
index 0000000000..2ac67c20b9
--- /dev/null
+++ b/Modules/Filtering/Contrast/test/otbContrastEnhancementFilter.cxx
@@ -0,0 +1,141 @@
+#include <iostream>
+#include <math.h>
+#include <vector>
+#include "otbImage.h"
+#include "otbVectorImage.h"
+#include "otbImageFileReader.h"
+#include "otbImageFileWriter.h"
+#include "itkImageLinearIteratorWithIndex.h"
+#include "itkImageToHistogramFilter.h"
+#include "itkVectorIndexSelectionCastImageFilter.h"
+#include "itkMultiplyImageFilter.h"
+
+
+typedef int                   PixelType;
+typedef itk::Image< PixelType , 2 >  ImageType;
+typedef itk::VectorImage< PixelType , 2 >  VectorImageType;
+
+void
+computeLuminance( ImageType::Pointer luminance ,
+                  VectorImageType::Pointer input )
+{
+  itk::ImageRegionIterator< VectorImageType >  itinp( input , input->GetRequestedRegion() );
+  itk::ImageRegionIterator< ImageType >  itlum( luminance , luminance->GetRequestedRegion() );
+  itinp.GoToBegin();
+  itlum.GoToBegin();
+  while ( !itinp.IsAtEnd() )
+  {
+    // 0.3R 0.6G 0.1B
+    itlum.Set( round(0.3 * itinp.Get()[0] + 0.6 * itinp.Get()[1] + 0.1  * itinp.Get()[2]) );
+    ++itinp;
+    ++itlum;
+  }
+}
+
+int
+main( int argc, 
+      char const *argv[] )
+{
+  // const char * inputfilename  = argv[ 1 ];
+  // const char * outputfilename = argv[ 2 ];
+
+
+  typedef otb::ImageFileReader< VectorImageType > ReaderType;
+  typedef itk::Statistics::ImageToHistogramFilter< ImageType > HistogramFilterType;
+  typedef HistogramFilterType::HistogramType HistogramType;
+  typedef itk::VectorIndexSelectionCastImageFilter< VectorImageType , ImageType > VectorToImageFilterType;
+
+
+  ReaderType::Pointer reader( ReaderType::New() );
+  reader->SetFileName( argv[ 1 ] );
+  reader->Update();
+  VectorImageType::Pointer input = reader->GetOutput();
+  ImageType::Pointer lum ( ImageType::New() ); 
+  lum->SetRegions( input->GetRequestedRegion() );
+  lum->Allocate();
+  lum->SetOrigin( input->GetOrigin() );
+  VectorToImageFilterType::Pointer vectorToImageFilter ( VectorToImageFilterType::New() );
+  if ( input->GetVectorLength() == 3 )
+  {
+    computeLuminance(lum, input);
+  }
+  else
+  {
+    // default is a black and white image, if length>3 and is not equal to one
+    // other case :  how to apply the equalization :
+    // - channel per channel?
+    // - with a general luminance?
+    vectorToImageFilter->SetInput( input );
+    vectorToImageFilter->SetIndex( 0 );
+    vectorToImageFilter->Update();
+    lum = vectorToImageFilter->GetOutput();
+  }
+
+
+  HistogramFilterType::Pointer histofilter( HistogramFilterType::New() );
+  histofilter->SetInput( lum );
+  histofilter->Update();
+  // Compute the histogram of the bw image
+  HistogramType * histo = histofilter->GetOutput();
+
+  // Define propertise of the target histogram : nomber of bin, height per bin
+  ImageType::SizeType lumSize = lum->GetLargestPossibleRegion().GetSize(); 
+  int npx = lumSize[0] * lumSize[1];
+  int nbin = histo->GetSize()[0];
+  float height = npx / nbin;
+
+  // The transfer function will be a look up table
+  std::vector< int > lut;
+  float nbOri, nbNew ; 
+  int countnew, countold;
+  countnew = 0;
+  countold = 0;
+  nbNew = height;
+  HistogramType::Iterator it = histo->Begin();
+  nbOri = it.GetFrequency();
+  while ( it != histo->End() )
+  {
+    if (nbOri> nbNew)
+    {
+      nbNew += height;
+      // index[0] += 1; 
+      ++countnew;
+    }
+    else
+    {
+      ++it;
+      nbOri += it.GetFrequency();
+      ++countold;
+      lut.push_back(countnew);
+    }
+  }
+
+  // Here we compute a gain image corresponding to the associated gain of the equalization
+  typedef itk::Image< float , 2 > ImageGainType;
+  ImageGainType::Pointer gainImage ( ImageGainType::New() );
+  gainImage->SetRegions( lum->GetRequestedRegion() );
+  gainImage->Allocate();
+  gainImage->SetOrigin( lum->GetOrigin() );
+  itk::ImageRegionIterator< ImageType > itlum( lum , lum->GetRequestedRegion() );
+  itk::ImageRegionIterator< ImageGainType > itgain( gainImage , gainImage->GetRequestedRegion() );
+  itlum.GoToBegin();
+  itgain.GoToBegin();
+  while( !itlum.IsAtEnd() )
+  {
+    itgain.Set( static_cast<float>(lut[itlum.Get()]) / static_cast<float>( itlum.Get() ) ) ;
+    ++itlum;
+    ++itgain;
+  }
+
+  typedef  itk::MultiplyImageFilter< VectorImageType, ImageGainType, VectorImageType > MultiplyImageFilterType;
+  MultiplyImageFilterType::Pointer gainMultiplyer ( MultiplyImageFilterType::New() );
+  gainMultiplyer->SetInput1( input );
+  gainMultiplyer->SetInput2( gainImage );
+  gainMultiplyer->Update();
+  typedef otb::ImageFileWriter<VectorImageType>  writertype;
+  writertype::Pointer writer( writertype::New());
+  writer->SetFileName( argv[2] );
+  writer->SetInput( gainMultiplyer->GetOutput() );
+  writer->Update();
+  return 0;
+}
-- 
GitLab