Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) VCL HistogramEqualization

 

HistogramEqualization is a VCL code snippet to perform a histogram equalization.

 

 


//From http://www.richelbilderbeek.nl/CppHistogramEqualization.htm
void HistogramEqualization(const TImage * const source, TImage * const target)
{
  assert(source!=0 && "Source image is NULL");
  assert(target!=0 && "Target image is NULL");
  assert(source->Picture->Bitmap!=0 && "Source bitmap is NULL");
  assert(target->Picture->Bitmap!=0 && "Target bitmap is NULL");
  assert(source->Picture->Bitmap->PixelFormat == pf24bit && "Source bitmap must be 24 bit");
  assert(target->Picture->Bitmap->PixelFormat == pf24bit && "Target bitmap must be 24 bit");
  //Get the width and height from the source
  const int width  = source->Picture->Bitmap->Width;
  const int height = source->Picture->Bitmap->Height;
  //Set the target's width and height
  target->Picture->Bitmap->Width  = width;
  target->Picture->Bitmap->Height = height;
  const int surface = width * height;
  const int nGreyValues = 256; //There are 256 different pixel intensities
  const std::vector<int> histogram = GetImageHistogram(source);
  assert(nGreyValues==static_cast<int>(histogram.size()));
  const std::vector<int> cumulativeHistogram = GetCumulativeHistogram(histogram);
  assert(nGreyValues==static_cast<int>(cumulativeHistogram.size()));
  //Works, but anybody knows how to use std::for_each or std::transform for this?
  std::vector<int> rescaledHistogram(nGreyValues,0);
  for (int i=0; i!=nGreyValues; ++i)
  {
    //'surface + 1' to prevent that rescaledGreyValue == 256
    const int rescaledGreyValue
      = static_cast<int>(
          static_cast<double>(nGreyValues)
        * static_cast<double>(cumulativeHistogram[i])
        / static_cast<double>(surface + 1) );
    assert(rescaledGreyValue >= 0);
    assert(rescaledGreyValue < 256);
    rescaledHistogram[i] = rescaledGreyValue;
  }
  for (int y=0; y!=height; ++y)
  {
    const unsigned char * lineSource
      = static_cast<const unsigned char *>(
        source->Picture->Bitmap->ScanLine[y]);
    unsigned char * lineTarget
      = static_cast<unsigned char *>(
        target->Picture->Bitmap->ScanLine[y]);
    for (int x=0; x!=width; ++x)
    {
      const int greyOriginal
        = (lineSource[x*3+0] + lineSource[x*3+1] + lineSource[x*3+2]) / 3;
      assert(greyOriginal >=   0);
      assert(greyOriginal  < 256);
      const int greyNew = rescaledHistogram[greyOriginal];
      assert(greyNew >= 0);
      assert(greyNew  < 256);
      lineTarget[x*3+0]=greyNew; //Blue
      lineTarget[x*3+1]=greyNew; //Green
      lineTarget[x*3+2]=greyNew; //Red
    }
  }
}
//------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppConvertToGrey.htm
void ConvertToGrey(const TImage * const source, TImage * const target)
{
  assert(source!=0 && "Source image is NULL");
  assert(target!=0 && "Target image is NULL");
  assert(source->Picture->Bitmap!=0 && "Source bitmap is NULL");
  assert(target->Picture->Bitmap!=0 && "Target bitmap is NULL");
  assert(source->Picture->Bitmap->PixelFormat == pf24bit && "Source bitmap must be 24 bit");
  assert(target->Picture->Bitmap->PixelFormat == pf24bit && "Target bitmap must be 24 bit");
  //Get the width and height from the source
  const int width  = source->Picture->Bitmap->Width;
  const int height = source->Picture->Bitmap->Height;
  //Set the target's width and height
  target->Picture->Bitmap->Width  = width;
  target->Picture->Bitmap->Height = height;
  for (int y=0; y!=height; ++y)
  {
    const unsigned char * lineSource
      = static_cast<const unsigned char *>(
        source->Picture->Bitmap->ScanLine[y]);
    unsigned char * lineTarget
      = static_cast<unsigned char *>(
        target->Picture->Bitmap->ScanLine[y]);
    for (int x=0; x!=width; ++x)
    {
      const int grey
        = (lineSource[x*3+0] + lineSource[x*3+1] + lineSource[x*3+2]) / 3;
      assert(grey >= 0 && grey < 256);
      lineTarget[x*3+0]=grey; //Blue
      lineTarget[x*3+1]=grey; //Green
      lineTarget[x*3+2]=grey; //Red
    }
  }
}
//------------------------------------------------------------
//From htpp://www.richelbilderbeek.nl/CppGetImageHistogram.htm
const std::vector<int> GetImageHistogram(const TImage * const image)
{
  assert(image!=0 && "Image is NULL");
  assert(image->Picture->Bitmap!=0 && "Image bitmap is NULL");
  assert(image->Picture->Bitmap->PixelFormat == pf24bit && "Image bitmap must be 24 bit");
  //Get the width and height from the source
  const int width  = image->Picture->Bitmap->Width;
  const int height = image->Picture->Bitmap->Height;
  std::vector<int> histogram(256,0); //There are 256 different color values
  for (int y=0; y!=height; ++y)
  {
    const unsigned char * line
      = static_cast<const unsigned char *>(
        image->Picture->Bitmap->ScanLine[y]);
    for (int x=0; x!=width; ++x)
    {
      const int grey
        = (line[x*3+0] + line[x*3+1] + line[x*3+2]) / 3;
      assert(grey >= 0 && grey < 256);
      ++histogram[grey];
    }
  }
  return histogram;
}
//------------------------------------------------------------
//From htpp://www.richelbilderbeek.nl/CppGetCumulativeHistogram.htm
template <class T> const std::vector<T> GetCumulativeHistogram(const std::vector<T>& histogram)
{
  std::vector<T> v(histogram.begin(),histogram.end() );
  const int size = v.size();
  for (int i=1; i!=size; ++i)
  {
    v[i] += v[i-1];
  }
  return v;
}
//------------------------------------------------------------

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml