(C++) HistogramEqualization
February 24, 2017 · View on GitHub
(C++)
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; } //------------------------------------------------------------