diff --git a/05/do_sprawdzenia/cpp/bin_gradient.cpp b/05/do_sprawdzenia/cpp/bin_gradient.cpp new file mode 100644 index 0000000..a495bc7 --- /dev/null +++ b/05/do_sprawdzenia/cpp/bin_gradient.cpp @@ -0,0 +1,72 @@ +#include "bin_gradient.h" +using namespace std; + +BinarizationGradient::BinarizationGradient(PNM* img) : + Transformation(img) +{ +} + +BinarizationGradient::BinarizationGradient(PNM* img, ImageViewer* iv) : + Transformation(img, iv) +{ +} + +PNM* BinarizationGradient::transform() +{ + int width = image->width(); + int height = image->height(); + + PNM* newImage = new PNM(width, height, QImage::Format_Mono); + + // Create variables + // The pixel value at point (i,j) + float I=0; + + // The first component of the gradient at point (i,j) + float Gx=0; + + // The second component of the gradient at point (i,j) + float Gy=0; + + + for (int x=0; x < width; x++) + { + for(int y=0; y < height; y++) + { + // Get current pixel value + QRgb pixel = image->pixel(x, y); + I = qGray(pixel); + + // Calculate Gx + Gx = Gx + (I * qGray(image->pixel(x+1, y)) - I * qGray(image->pixel(x-1, y))); + + //Calculate Gy + Gy = Gy + (I * qGray(image->pixel(x, y+1)) - I * qGray(image->pixel(x, y-1))); + } + } + + // Calculate T + float T = (max(Gx, Gy) * I) / max(Gx, Gy); + + // Iterate over pixels + for (int x=0; x < width; x++) + { + for (int y=0; y < height; y++) + { + // Get current pixel + QRgb pixel = image->pixel(x, y); + if(qGray(pixel) > T) + { + newImage->setPixel(x, y, Qt::color1); + } + else + { + newImage->setPixel(x, y, Qt::color0); + } + } + } + + return newImage; +} + + diff --git a/05/do_sprawdzenia/cpp/bin_iterbimodal.cpp b/05/do_sprawdzenia/cpp/bin_iterbimodal.cpp new file mode 100644 index 0000000..2b1cc48 --- /dev/null +++ b/05/do_sprawdzenia/cpp/bin_iterbimodal.cpp @@ -0,0 +1,88 @@ +#include "bin_iterbimodal.h" +#include "bin_manual.h" +#include "conversion_grayscale.h" +#include "histogram_equalization.h" +#include "../histogram.h" + + +BinarizationIterBimodal::BinarizationIterBimodal(PNM* img) : + Transformation(img) +{ +} + +BinarizationIterBimodal::BinarizationIterBimodal(PNM* img, ImageViewer* iv) : + Transformation(img, iv) +{ +} + +PNM* BinarizationIterBimodal::transform() +{ + int width = image->width(); + int height = image->height(); + + PNM* newImage = new PNM(width, height, QImage::Format_Mono); + + // Create variables + HistogramEqualization* equalized_histogram = new HistogramEqualization(image); + BinarizationManual* binarization_manual; + + int iter = 1; + + // Threshold + int T = 128; + + // New threshold + int T_new; + + image = equalized_histogram->transform(); + + // Histogram table + hg = image->getHistogram()->get(Histogram::LChannel); + + // Calculate new threshold + T_new = (avg_saturation(0, T-1) + avg_saturation(T, 255)) / 2; + + while (T_new != T) + { + T = T_new; + + T_new = (avg_saturation(0, T-1) + avg_saturation(T, 255)) / 2; + iter ++; + } + + // Use manual binarization to binaryze image + binarization_manual = new BinarizationManual(image); + binarization_manual->setParameter("threshold", T); + + // Return binary image + newImage = binarization_manual->transform(); + + return newImage; + +} + + +int BinarizationIterBimodal::avg_saturation(int start, int end) +{ + int i; + int value; + int sum; + int counter; + int result; + + sum = 1; + counter = 1; + for (i = start; i <= end; i++) + { + // Get value + value = hg->value(i); + sum += value; + counter += value * i; + } + result = counter / sum; + + return result; +} + + + diff --git a/05/do_sprawdzenia/cpp/bin_iterbimodal.h b/05/do_sprawdzenia/cpp/bin_iterbimodal.h new file mode 100644 index 0000000..bd27f50 --- /dev/null +++ b/05/do_sprawdzenia/cpp/bin_iterbimodal.h @@ -0,0 +1,20 @@ +#ifndef BIN_ITERBIMODAL_H +#define BIN_ITERBIMODAL_H + +#include "transformation.h" + + +class BinarizationIterBimodal : public Transformation +{ +public: + BinarizationIterBimodal(PNM*); + BinarizationIterBimodal(PNM*, ImageViewer*); + + virtual PNM* transform(); + + QHash * hg; + + int avg_saturation(int, int); +}; + +#endif // BIN_ITERBIMODAL_H diff --git a/05/do_sprawdzenia/cpp/bin_manual.cpp b/05/do_sprawdzenia/cpp/bin_manual.cpp new file mode 100644 index 0000000..0612e5e --- /dev/null +++ b/05/do_sprawdzenia/cpp/bin_manual.cpp @@ -0,0 +1,45 @@ +#include "bin_manual.h" + +BinarizationManual::BinarizationManual(PNM* img) : + Transformation(img) +{ +} + +BinarizationManual::BinarizationManual(PNM* img, ImageViewer* iv) : + Transformation(img, iv) +{ +} + +PNM* BinarizationManual::transform() +{ + int threshold = getParameter("threshold").toInt(); + + int width = image->width(); + int height = image->height(); + + PNM* newImage = new PNM(width, height, QImage::Format_Mono); + + // Iterate over pixels + for (int x=0; x < width; x++) + { + for (int y=0; y < height; y++) + { + // Get current pixel + QRgb pixel = image->pixel(x, y); + if(qGray(pixel) > threshold) + { + newImage->setPixel(x, y, Qt::color1); + } + else + { + newImage->setPixel(x, y, Qt::color0); + } + } + } + + return newImage; +} + + + + diff --git a/05/do_sprawdzenia/cpp/bin_niblack.cpp b/05/do_sprawdzenia/cpp/bin_niblack.cpp new file mode 100644 index 0000000..9c25676 --- /dev/null +++ b/05/do_sprawdzenia/cpp/bin_niblack.cpp @@ -0,0 +1,69 @@ +#include "bin_niblack.h" +#include "transformation.h" + +BinarizationNiblack::BinarizationNiblack(PNM* img) : + Transformation(img) +{ +} + +BinarizationNiblack::BinarizationNiblack(PNM* img, ImageViewer* iv) : + Transformation(img, iv) +{ +} + +PNM* BinarizationNiblack::transform() +{ + int width = image->width(); + int height = image->height(); + + int r = getParameter("r").toInt(); + double a = getParameter("a").toDouble(); + + double arithmetic_mean = 0; + double variance = 0; + double standard_deviation = 0; + math::matrix window; + int T; + + PNM* newImage = new PNM(width, height, QImage::Format_Mono); + + for (int x=0; x < width; x++) + { + for (int y=0; y < height; y++) + { + // Get current pixel + QRgb pixel = image->pixel(x, y); + + //Get current window + window = getWindow(x, y, r, LChannel, RepeatEdge); + + // Calculate arithmetic mean + arithmetic_mean = window.sum() / pow(r, 2); + + + // Calculate standard_deviation + for (int i = 0; i < r+1; i++){ + for (int j = 0; i < r+1; i++){ + variance += pow(window[i][j] - arithmetic_mean, 2); + } + } + variance /= pow(r, 2); + standard_deviation = sqrt(variance); + + // Calculate threshold T + T = arithmetic_mean + a * standard_deviation; + + if(qGray(pixel) > T) + { + newImage->setPixel(x, y, Qt::color1); + } + else + { + newImage->setPixel(x, y, Qt::color0); + } + + } + } + return newImage; +} + diff --git a/05/do_sprawdzenia/cpp/bin_otsu.cpp b/05/do_sprawdzenia/cpp/bin_otsu.cpp new file mode 100644 index 0000000..c4e0b27 --- /dev/null +++ b/05/do_sprawdzenia/cpp/bin_otsu.cpp @@ -0,0 +1,125 @@ +#include "bin_otsu.h" + +#include "histogram_equalization.h" +#include "../histogram.h" + +BinarizationOtsu::BinarizationOtsu(PNM* img) : + Transformation(img) +{ +} + +BinarizationOtsu::BinarizationOtsu(PNM* img, ImageViewer* iv) : + Transformation(img, iv) +{ +} + +PNM* BinarizationOtsu::transform() +{ + int width = image->width(); + int height = image->height(); + + PNM* newImage = new PNM(width, height, QImage::Format_Mono); + HistogramEqualization* equalized_histogram = new HistogramEqualization(image); + QHash * hg; + + // Number od pixels in image + int N = width * height; + + image = equalized_histogram->transform(); + + // Histogram table + hg = image->getHistogram()->get(Histogram::LChannel); + + + int value; + double bcv[256]; + + int sum_1 = 0; + int sum2 = 0; + + double u_b; + double u_f; + double W_b; + double W_f; + + for (int t=0; t < 255; t++) + { + + for (int j=0; j < t; j++) + { + value = image->getHistogram()->get(Histogram::LChannel)->value(j); + sum_1 += value; + } + + W_b = sum_1 / pow(255, 2); + + for (int j=0; j < t; j++) + { + value = image->getHistogram()->get(Histogram::LChannel)->value(j); + sum2 += value * j; + } + + if (sum_1 == 0) + { + u_b = 0; + } + else + { + u_b = sum2 / sum_1; + } + + sum_1 = 0; + sum2 = 0; + + for (int j=t; j < 255; j++) + { + value = image->getHistogram()->get(Histogram::LChannel)->value(j); + sum_1 += value; + } + + W_f = sum_1 / pow(255, 2); + + for (int j=t; j < 255; j++) + { + value = image->getHistogram()->get(Histogram::LChannel)->value(j); + sum2 += value * j; + } + + if (sum_1 == 0) + { + u_f = 0; + } + else + { + u_f = sum2 / sum_1; + } + + bcv[t]= W_b * W_f * pow(u_b - u_f, 2); + } + + int T = 0; + for (int j=0; j< 255;j++) + { + if (bcv[j] > bcv[T]) + { + T=j; + } + } + + // Iterate over pixels + for (int x=0; xpixel(x, y); + int l = qGray(pixel); + + newImage->setPixel(x,y, l < T ? Qt::color0 : Qt::color1); + } + } + + + return newImage; +} + diff --git a/app/cpp/mysimplegimp/src/core/transformations/bin_gradient.cpp b/app/cpp/mysimplegimp/src/core/transformations/bin_gradient.cpp index d502adb..a495bc7 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/bin_gradient.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/bin_gradient.cpp @@ -1,4 +1,5 @@ #include "bin_gradient.h" +using namespace std; BinarizationGradient::BinarizationGradient(PNM* img) : Transformation(img) @@ -17,7 +18,53 @@ PNM* BinarizationGradient::transform() PNM* newImage = new PNM(width, height, QImage::Format_Mono); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + // Create variables + // The pixel value at point (i,j) + float I=0; + + // The first component of the gradient at point (i,j) + float Gx=0; + + // The second component of the gradient at point (i,j) + float Gy=0; + + + for (int x=0; x < width; x++) + { + for(int y=0; y < height; y++) + { + // Get current pixel value + QRgb pixel = image->pixel(x, y); + I = qGray(pixel); + + // Calculate Gx + Gx = Gx + (I * qGray(image->pixel(x+1, y)) - I * qGray(image->pixel(x-1, y))); + + //Calculate Gy + Gy = Gy + (I * qGray(image->pixel(x, y+1)) - I * qGray(image->pixel(x, y-1))); + } + } + + // Calculate T + float T = (max(Gx, Gy) * I) / max(Gx, Gy); + + // Iterate over pixels + for (int x=0; x < width; x++) + { + for (int y=0; y < height; y++) + { + // Get current pixel + QRgb pixel = image->pixel(x, y); + if(qGray(pixel) > T) + { + newImage->setPixel(x, y, Qt::color1); + } + else + { + newImage->setPixel(x, y, Qt::color0); + } + } + } return newImage; } diff --git a/app/cpp/mysimplegimp/src/core/transformations/bin_iterbimodal.cpp b/app/cpp/mysimplegimp/src/core/transformations/bin_iterbimodal.cpp index 6a562c7..2b1cc48 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/bin_iterbimodal.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/bin_iterbimodal.cpp @@ -1,9 +1,10 @@ #include "bin_iterbimodal.h" - +#include "bin_manual.h" #include "conversion_grayscale.h" #include "histogram_equalization.h" #include "../histogram.h" + BinarizationIterBimodal::BinarizationIterBimodal(PNM* img) : Transformation(img) { @@ -21,9 +22,66 @@ PNM* BinarizationIterBimodal::transform() PNM* newImage = new PNM(width, height, QImage::Format_Mono); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + // Create variables + HistogramEqualization* equalized_histogram = new HistogramEqualization(image); + BinarizationManual* binarization_manual; + + int iter = 1; + + // Threshold + int T = 128; + + // New threshold + int T_new; + + image = equalized_histogram->transform(); + + // Histogram table + hg = image->getHistogram()->get(Histogram::LChannel); + + // Calculate new threshold + T_new = (avg_saturation(0, T-1) + avg_saturation(T, 255)) / 2; + + while (T_new != T) + { + T = T_new; + + T_new = (avg_saturation(0, T-1) + avg_saturation(T, 255)) / 2; + iter ++; + } + + // Use manual binarization to binaryze image + binarization_manual = new BinarizationManual(image); + binarization_manual->setParameter("threshold", T); + + // Return binary image + newImage = binarization_manual->transform(); return newImage; + +} + + +int BinarizationIterBimodal::avg_saturation(int start, int end) +{ + int i; + int value; + int sum; + int counter; + int result; + + sum = 1; + counter = 1; + for (i = start; i <= end; i++) + { + // Get value + value = hg->value(i); + sum += value; + counter += value * i; + } + result = counter / sum; + + return result; } diff --git a/app/cpp/mysimplegimp/src/core/transformations/bin_iterbimodal.h b/app/cpp/mysimplegimp/src/core/transformations/bin_iterbimodal.h index 9ef2f3b..bd27f50 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/bin_iterbimodal.h +++ b/app/cpp/mysimplegimp/src/core/transformations/bin_iterbimodal.h @@ -3,6 +3,7 @@ #include "transformation.h" + class BinarizationIterBimodal : public Transformation { public: @@ -10,6 +11,10 @@ public: BinarizationIterBimodal(PNM*, ImageViewer*); virtual PNM* transform(); + + QHash * hg; + + int avg_saturation(int, int); }; #endif // BIN_ITERBIMODAL_H diff --git a/app/cpp/mysimplegimp/src/core/transformations/bin_manual.cpp b/app/cpp/mysimplegimp/src/core/transformations/bin_manual.cpp index a410dfa..0612e5e 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/bin_manual.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/bin_manual.cpp @@ -19,7 +19,23 @@ PNM* BinarizationManual::transform() PNM* newImage = new PNM(width, height, QImage::Format_Mono); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + // Iterate over pixels + for (int x=0; x < width; x++) + { + for (int y=0; y < height; y++) + { + // Get current pixel + QRgb pixel = image->pixel(x, y); + if(qGray(pixel) > threshold) + { + newImage->setPixel(x, y, Qt::color1); + } + else + { + newImage->setPixel(x, y, Qt::color0); + } + } + } return newImage; } diff --git a/app/cpp/mysimplegimp/src/core/transformations/bin_niblack.cpp b/app/cpp/mysimplegimp/src/core/transformations/bin_niblack.cpp index 418648b..9c25676 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/bin_niblack.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/bin_niblack.cpp @@ -1,4 +1,5 @@ #include "bin_niblack.h" +#include "transformation.h" BinarizationNiblack::BinarizationNiblack(PNM* img) : Transformation(img) @@ -18,9 +19,51 @@ PNM* BinarizationNiblack::transform() int r = getParameter("r").toInt(); double a = getParameter("a").toDouble(); + double arithmetic_mean = 0; + double variance = 0; + double standard_deviation = 0; + math::matrix window; + int T; + PNM* newImage = new PNM(width, height, QImage::Format_Mono); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + for (int x=0; x < width; x++) + { + for (int y=0; y < height; y++) + { + // Get current pixel + QRgb pixel = image->pixel(x, y); + //Get current window + window = getWindow(x, y, r, LChannel, RepeatEdge); + + // Calculate arithmetic mean + arithmetic_mean = window.sum() / pow(r, 2); + + + // Calculate standard_deviation + for (int i = 0; i < r+1; i++){ + for (int j = 0; i < r+1; i++){ + variance += pow(window[i][j] - arithmetic_mean, 2); + } + } + variance /= pow(r, 2); + standard_deviation = sqrt(variance); + + // Calculate threshold T + T = arithmetic_mean + a * standard_deviation; + + if(qGray(pixel) > T) + { + newImage->setPixel(x, y, Qt::color1); + } + else + { + newImage->setPixel(x, y, Qt::color0); + } + + } + } return newImage; } + diff --git a/app/cpp/mysimplegimp/src/core/transformations/bin_otsu.cpp b/app/cpp/mysimplegimp/src/core/transformations/bin_otsu.cpp index 6e4d72a..c4e0b27 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/bin_otsu.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/bin_otsu.cpp @@ -19,8 +19,106 @@ PNM* BinarizationOtsu::transform() int height = image->height(); PNM* newImage = new PNM(width, height, QImage::Format_Mono); + HistogramEqualization* equalized_histogram = new HistogramEqualization(image); + QHash * hg; + + // Number od pixels in image + int N = width * height; + + image = equalized_histogram->transform(); + + // Histogram table + hg = image->getHistogram()->get(Histogram::LChannel); + + + int value; + double bcv[256]; + + int sum_1 = 0; + int sum2 = 0; + + double u_b; + double u_f; + double W_b; + double W_f; + + for (int t=0; t < 255; t++) + { + + for (int j=0; j < t; j++) + { + value = image->getHistogram()->get(Histogram::LChannel)->value(j); + sum_1 += value; + } + + W_b = sum_1 / pow(255, 2); + + for (int j=0; j < t; j++) + { + value = image->getHistogram()->get(Histogram::LChannel)->value(j); + sum2 += value * j; + } + + if (sum_1 == 0) + { + u_b = 0; + } + else + { + u_b = sum2 / sum_1; + } + + sum_1 = 0; + sum2 = 0; + + for (int j=t; j < 255; j++) + { + value = image->getHistogram()->get(Histogram::LChannel)->value(j); + sum_1 += value; + } + + W_f = sum_1 / pow(255, 2); + + for (int j=t; j < 255; j++) + { + value = image->getHistogram()->get(Histogram::LChannel)->value(j); + sum2 += value * j; + } + + if (sum_1 == 0) + { + u_f = 0; + } + else + { + u_f = sum2 / sum_1; + } + + bcv[t]= W_b * W_f * pow(u_b - u_f, 2); + } + + int T = 0; + for (int j=0; j< 255;j++) + { + if (bcv[j] > bcv[T]) + { + T=j; + } + } + + // Iterate over pixels + for (int x=0; xpixel(x, y); + int l = qGray(pixel); + + newImage->setPixel(x,y, l < T ? Qt::color0 : Qt::color1); + } + } - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; return newImage; }