diff --git a/specification.doc b/specification.doc index 195055c..e310874 100644 --- a/specification.doc +++ b/specification.doc @@ -1 +1,18 @@ Plik z Dokumentacja do projektu + + +Zadanie 3 +Histogram to wyliczenie ile razy wystepuje dana wartośc koloru w obrazie. +Dla każdego kanału : rgb liczona jest liczba wystąpień każdego odcienia od 0 do 255. + +Rozciągniecie histogramu : +najpierw szukamy lewej (min) i prawej (max) krawędzi histogramu, tzn. od jakiej wartości piksela (idąc od lewej i od prawej) zaczynają się pierwsze niezerowe wartości histogramu, +rozciągamy histogram, czyli każdemu pikselowi na obrazie dajemy nową wartość wg wzoru: + Pixel-new [x,y] = (255/ max-min) * pixel-old[x,y] - min + + Wyrównanie + To wyliczenie dystrybuanty czyli histogramu podzielonego przez sume. Mamy takzwane prawdopobienstwo wystapienia + a nastepnie wyliczenie na podstawie wzoru: + Lut[i] = ( ( D[i] - Dmin) / 1 - Dmin ) ) * k-1 , gdzie k to liczba poziomow odcienia czyli 256 + + \ No newline at end of file diff --git a/src/core/histogram.cpp b/src/core/histogram.cpp index 1287666..2024b14 100644 --- a/src/core/histogram.cpp +++ b/src/core/histogram.cpp @@ -24,15 +24,101 @@ Histogram::~Histogram() void Histogram::generate(QImage* image) { - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + + qDebug() << Q_FUNC_INFO << " Generating histogram !"; + for(int i = 0 ; i < image->height(); i++){ + for(int j = 0 ; j < image->width() ; j++){ + QColor *clrCurrent = new QColor( image->pixel(i,j) ); + + QRgb pixel = image->pixel(i,j); + R->insert(qRed(pixel),R->value(qRed(pixel))+1); + G->insert(qGreen(pixel),G->value(qGreen(pixel))+1); + B->insert(qBlue(pixel),B->value(qBlue(pixel))+1); + L->insert(qAlpha(pixel),L->value(qAlpha(pixel))+1); + } + } } /** Returns the maximal value of the histogram in the given channel */ int Histogram::maximumValue(Channel selectedChannel = RGB) { - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + int max = 0; + if(selectedChannel == LChannel){ + return getMaxFromQHashHelper(get(selectedChannel)); + } - return 0; + max = getMaxFromQHashHelper(R); + + if(getMaxFromQHashHelper(G) > max){ + max = getMaxFromQHashHelper(G); + } + + if(getMaxFromQHashHelper(B) > max){ + max = getMaxFromQHashHelper(B); + } + + return max; +} + +// Return max or -1 when QHash is empty +int Histogram::getMaxFromQHashHelper( QHash * channel ){ + int max = -1; + + QHash::const_iterator iterator = channel->begin(); + while (iterator != channel->end()) + { + if(iterator.value() > max && iterator.value() != 0 ){ + max = iterator.value(); + } + ++iterator; + + } + return max; +} + +int Histogram::getMaxKey( QHash * channel ){ + int max = -1; + + QHash::const_iterator iterator = channel->begin(); + while (iterator != channel->end()) + { + if(iterator.key() > max && iterator.value() != 0){ + max = iterator.key(); + } + ++iterator; + + } + return max; +} + +int Histogram::getMinKey( QHash * channel ){ + int min = 256; + + QHash::const_iterator iterator = channel->begin(); + while (iterator != channel->end()) + { + if(iterator.key() < min && iterator.value() != 0){ + min = iterator.key(); + } + ++iterator; + + } + return min; +} + +//Return min or 256 when qhash is empty +int Histogram::getMinFromQHashHelper( QHash * channel ){ + int min = 256; + + QHash::const_iterator iterator = channel->begin(); + while (iterator != channel->end()) + { + if(iterator.value() < min && iterator.value() != 0){ + min = iterator.value(); + } + ++iterator; + } + return min; } diff --git a/src/core/histogram.h b/src/core/histogram.h index dc5052c..4b62c26 100644 --- a/src/core/histogram.h +++ b/src/core/histogram.h @@ -16,10 +16,15 @@ public: QHash* get(Histogram::Channel); QImage getImage(Histogram::Channel, QBrush); int maximumValue(Channel); + int getMaxFromQHashHelper( QHash *); + int getMinFromQHashHelper( QHash *); + int getMinKey( QHash *); + int getMaxKey( QHash *); private: void generate(QImage*); // iterates all parent image pixels and set the Hashes + QHash* R; QHash* G; QHash* B; diff --git a/src/core/transformations/histogram_equalization.cpp b/src/core/transformations/histogram_equalization.cpp index ab76cd3..a9b43dc 100644 --- a/src/core/transformations/histogram_equalization.cpp +++ b/src/core/transformations/histogram_equalization.cpp @@ -16,11 +16,73 @@ PNM* HistogramEqualization::transform() { int width = image->width(); int height = image->height(); - + int pixelAmounts = width* height; PNM* newImage = new PNM(width, height, image->format()); + double LUTr[256], LUTg[256], LUTb[256], + redHist[256], greenHist[256], blueHist[256], + distRed[256], distGreen[256], distBlue[256]; - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + zeros(redHist,greenHist,blueHist); + zeros(distRed,distGreen,distBlue); + zeros(LUTr,LUTb,LUTg); + for (int x = 0; x < width; x++){ + for (int y = 0; y < height; y++) + { + QRgb pixel = image->pixel(x,y); + redHist[qRed(pixel)]++; + greenHist[qGreen(pixel)]++; + blueHist[qBlue(pixel)]++; + } + } + + double sumR = 0; + double sumG = 0; + double sumB = 0; + + for (int i=0; i<256; i++) + { + sumR += (redHist[i]/pixelAmounts); + sumG += (greenHist[i]/pixelAmounts); + sumB += (blueHist[i]/pixelAmounts); + distRed[i] += sumR; + distGreen[i] += sumG; + distBlue[i] += sumB; + } + + prepareLUTperChannel(distRed, LUTr); + prepareLUTperChannel(distGreen, LUTg ); + prepareLUTperChannel(distBlue, LUTb ); + for (int i = 0; i< width; i++){ + for (int j = 0; j< height; j++) + { + QRgb pixel = image->pixel(i,j); + newImage->setPixel(i,j, QColor( LUTr[qRed(pixel)], LUTg[qGreen(pixel)], LUTb[qBlue(pixel)]).rgba() ); + } + } return newImage; } +void HistogramEqualization::prepareLUTperChannel(double *D, double *LUT) +{ + double Dmin = 0; + for(int i = 0; i < 256 ; i++){ + if(D[i+1] > 0){ + Dmin = D[i+1]; + break; + } + } + + for (int i=0; i<256; i++){ + LUT[i] = ( 255* ((D[i] - Dmin) / (1 - Dmin))) ; + } +} + +void HistogramEqualization::zeros(double * r_tab, double * g_tab, double* b_tab){ + for (int i=0; i<256; i++) + { + r_tab[i] = 0; + g_tab[i] = 0; + b_tab[i] = 0; + } +} diff --git a/src/core/transformations/histogram_equalization.h b/src/core/transformations/histogram_equalization.h index 08057b4..afa3adf 100644 --- a/src/core/transformations/histogram_equalization.h +++ b/src/core/transformations/histogram_equalization.h @@ -8,8 +8,12 @@ class HistogramEqualization : public Transformation public: HistogramEqualization(PNM*); HistogramEqualization(PNM*, ImageViewer*); + QHash prepareDistrubuantPerChannel(QHash * , int); + void prepareLUTperChannel(double *, double * ); + void zeros(double *, double * , double * ); virtual PNM* transform(); + int min(QHash *dist); }; diff --git a/src/core/transformations/histogram_stretching.cpp b/src/core/transformations/histogram_stretching.cpp index 25440de..493b061 100644 --- a/src/core/transformations/histogram_stretching.cpp +++ b/src/core/transformations/histogram_stretching.cpp @@ -14,13 +14,31 @@ HistogramStretching::HistogramStretching(PNM* img, ImageViewer* iv) : PNM* HistogramStretching::transform() { + int width = image->width(); int height = image->height(); - PNM* newImage = new PNM(width, height, image->format()); + Histogram * histogram = image->getHistogram(); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + int maxRed = histogram->getMaxKey(histogram->get(histogram->RChannel)); + int minRed = histogram->getMinKey(histogram->get(histogram->RChannel)); + int maxGreen = histogram->getMaxKey(histogram->get(histogram->GChannel)); + int minGreen = histogram->getMinKey(histogram->get(histogram->GChannel)); + + int maxBlue = histogram->getMaxKey(histogram->get(histogram->BChannel)); + int minBlue = histogram->getMinKey(histogram->get(histogram->BChannel)); + + for(int x = 0 ; x < width; x++){ + for (int y = 0 ; y < height; y++) { + + QRgb pixel = image->pixel(x,y); + int g = (qGreen(pixel) - minGreen) * (MAX_VALUE/(maxGreen-minGreen)); + int r = (qRed(pixel) - minRed) * (MAX_VALUE/(maxRed-minRed)); + int b = (qBlue(pixel) - minBlue) * (MAX_VALUE/(maxBlue-minBlue)); + newImage->setPixel(x,y,QColor(r,g,b).rgba()); + } + } return newImage; } diff --git a/src/core/transformations/histogram_stretching.h b/src/core/transformations/histogram_stretching.h index 0f926db..8ce2757 100644 --- a/src/core/transformations/histogram_stretching.h +++ b/src/core/transformations/histogram_stretching.h @@ -6,6 +6,7 @@ class HistogramStretching : public Transformation { public: + int const MAX_VALUE = 255; HistogramStretching(PNM*); HistogramStretching(PNM*, ImageViewer* iv);