From 664d4e19f9d409bf10f1b7a336e8acbac23c3d7a Mon Sep 17 00:00:00 2001 From: Damian Kowalski Date: Sun, 7 Apr 2024 12:07:24 +0200 Subject: [PATCH] histogram refactor + fixes --- src/core/histogram.cpp | 66 +++++++++---------- src/core/histogram.h | 1 + .../histogram_equalization.cpp | 39 ++++++++++- 3 files changed, 69 insertions(+), 37 deletions(-) diff --git a/src/core/histogram.cpp b/src/core/histogram.cpp index bef28e1..c548eda 100644 --- a/src/core/histogram.cpp +++ b/src/core/histogram.cpp @@ -23,26 +23,14 @@ Histogram::~Histogram() } void Histogram::generate(QImage* image) { - R->clear(); - G->clear(); - B->clear(); - L->clear(); + for (int x = 0; x < image->width(); ++x) { + for (int y = 0; y < image->height(); ++y) { + QRgb p = image->pixel(x, y); - if (image == nullptr) { - qDebug() << "Invalid image provided."; - return; - } - - for (int y = 0; y < image->height(); ++y) { - for (int x = 0; x < image->width(); ++x) { - QColor pixelColor = image->pixelColor(x, y); - - R->insert(pixelColor.red(), R->value(pixelColor.red()) + 1); - G->insert(pixelColor.green(), G->value(pixelColor.green()) + 1); - B->insert(pixelColor.blue(), B->value(pixelColor.blue()) + 1); - - int luminance = qRound(0.299 * pixelColor.red() + 0.587 * pixelColor.green() + 0.114 * pixelColor.blue()); - L->insert(luminance, L->value(luminance) + 1); + Histogram::R->insert(qRed(p), Histogram::R->value(qRed(p)) + 1); + Histogram::G->insert(qGreen(p), Histogram::G->value(qGreen(p)) + 1); + Histogram::B->insert(qBlue(p), Histogram::B->value(qBlue(p)) + 1); + Histogram::L->insert(qGray(p), Histogram::L->value(qGray(p)) + 1); } } } @@ -51,27 +39,37 @@ int Histogram::maximumValue(Channel selectedChannel) { int maxVal = 0; - if (selectedChannel == RGB) { - int maxR = maximumValue(RChannel); - int maxG = maximumValue(GChannel); - int maxB = maximumValue(BChannel); - maxVal = std::max(maxR, std::max(maxG, maxB)); + if(Histogram::getMaxChannel(R) > maxVal) { + maxVal = Histogram::getMaxChannel(R); } - else { - QHash* hist = get(selectedChannel); - QHash::const_iterator cit = hist->constBegin(); - while (cit != hist->constEnd()) { - if (cit.value() > maxVal) { - maxVal = cit.value(); - } - ++cit; - } + if(Histogram::getMaxChannel(G) > maxVal) { + maxVal = Histogram::getMaxChannel(G); + } + + if(Histogram::getMaxChannel(B) > maxVal) { + maxVal = Histogram::getMaxChannel(B); + } + + if(Histogram::getMaxChannel(L) > maxVal) { + maxVal = Histogram::getMaxChannel(L); } return maxVal; } +int Histogram::getMaxChannel(QHash* channel) { + int maxValue = 0; + + for(int i = 0; i < channel->size(); i++) + { + if(channel->value(i) > maxValue) + maxValue = channel->value(i); + } + + return maxValue; +} + QHash* Histogram::get(Channel channel = LChannel) { if (channel==LChannel) return L; @@ -91,7 +89,7 @@ QImage Histogram::getImage(Channel channel = LChannel, QBrush pen = Qt::gray) QImage histImage(255, 100, QImage::Format_ARGB32); histImage.fill(0); QPainter painter(&histImage); - painter.setBrush(Qt::transparent); + painter.setBrush(Qt::transparent); painter.setPen(Qt::transparent); painter.drawRect(0,0,255,100); diff --git a/src/core/histogram.h b/src/core/histogram.h index dc5052c..6cb0374 100644 --- a/src/core/histogram.h +++ b/src/core/histogram.h @@ -19,6 +19,7 @@ public: private: void generate(QImage*); // iterates all parent image pixels and set the Hashes + int getMaxChannel(QHash*); QHash* R; QHash* G; diff --git a/src/core/transformations/histogram_equalization.cpp b/src/core/transformations/histogram_equalization.cpp index ab76cd3..9425e2c 100644 --- a/src/core/transformations/histogram_equalization.cpp +++ b/src/core/transformations/histogram_equalization.cpp @@ -1,6 +1,6 @@ #include "histogram_equalization.h" - #include "../histogram.h" +#include // Dla funkcji round HistogramEqualization::HistogramEqualization(PNM* img) : Transformation(img) @@ -17,10 +17,43 @@ PNM* HistogramEqualization::transform() int width = image->width(); int height = image->height(); + // Tworzymy nowy obiekt PNM do przechowywania przetworzonego obrazu PNM* newImage = new PNM(width, height, image->format()); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + // Tworzymy histogram dla obecnego obrazu + Histogram* hist = image->getHistogram(); // Nie przekazujemy argumentów + + // Pobieramy łączną liczbę pikseli na obrazie + int totalPixels = width * height; + + // Tworzymy dystrybuantę + QVector cdf(256, 0.0); // Inicjalizujemy wszystkie wartości na 0.0 + double sum = 0.0; + for (int i = 0; i < 256; ++i) { + sum += hist->get(Histogram::LChannel)->value(i) / static_cast(totalPixels); // Używamy kanału luminancji + cdf[i] = sum; + } + + // Normalizujemy dystrybuantę do przedziału [0, 255] + QVector lookupTable(256, 0); + for (int i = 0; i < 256; ++i) { + lookupTable[i] = round(cdf[i] * 255); + } + + // Przeprowadzamy wyrównywanie histogramu + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + QRgb pixel = image->pixel(x, y); + int grayValue = qGray(pixel); // Pobieramy wartość odcienia szarości + + // Używamy wartości z lookupTable jako nowej wartości odcienia szarości + int newGrayValue = lookupTable[grayValue]; + QRgb newPixel = qRgb(newGrayValue, newGrayValue, newGrayValue); // Ustawiamy nową wartość dla każdego kanału RGB + + // Ustawiamy nowy piksel na obrazie docelowym + newImage->setPixel(x, y, newPixel); + } + } return newImage; } -