From b778d1bbd76ba2d63ff836217a742d8be580d425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaros=C5=82aw=20Wieczorek?= Date: Sat, 20 Mar 2021 17:56:06 +0100 Subject: [PATCH] Zadanie 4 --- 04/do_sprawdzenia/cpp/blur_gaussian.cpp | 46 +++++ 04/do_sprawdzenia/cpp/blur_linear.cpp | 40 ++++ 04/do_sprawdzenia/cpp/blur_uniform.cpp | 25 +++ 04/do_sprawdzenia/cpp/convolution.cpp | 173 ++++++++++++++++++ .../core/transformations/blur_gaussian.cpp | 13 +- .../src/core/transformations/blur_linear.cpp | 18 +- .../src/core/transformations/blur_uniform.cpp | 9 +- .../src/core/transformations/convolution.cpp | 108 ++++++++++- .../core/transformations/transformation.cpp | 58 +++++- 9 files changed, 474 insertions(+), 16 deletions(-) create mode 100644 04/do_sprawdzenia/cpp/blur_gaussian.cpp create mode 100644 04/do_sprawdzenia/cpp/blur_linear.cpp create mode 100644 04/do_sprawdzenia/cpp/blur_uniform.cpp create mode 100644 04/do_sprawdzenia/cpp/convolution.cpp diff --git a/04/do_sprawdzenia/cpp/blur_gaussian.cpp b/04/do_sprawdzenia/cpp/blur_gaussian.cpp new file mode 100644 index 0000000..d4d97c4 --- /dev/null +++ b/04/do_sprawdzenia/cpp/blur_gaussian.cpp @@ -0,0 +1,46 @@ +#include "blur_gaussian.h" + +BlurGaussian::BlurGaussian(PNM* img) : + Convolution(img) +{ +} + +BlurGaussian::BlurGaussian(PNM* img, ImageViewer* iv) : + Convolution(img, iv) +{ +} + +PNM* BlurGaussian::transform() +{ + emit message("Blurring..."); + + int size = getParameter("size").toInt(); + radius = (size/2)+1; + sigma = getParameter("sigma").toDouble(); + + return convolute(getMask(size, Normalize), RepeatEdge); +} + +math::matrix BlurGaussian::getMask(int size, Mode) +{ + math::matrix mask(size, size); + + for (int i = 0; i < size; i++) + { + for (int j = 0; j < size; j++) + { + mask(i,j) = getGauss(i-radius, j-radius, sigma); + } + } + + + return mask; +} + +float BlurGaussian::getGauss(int x, int y, float sigma) +{ + // Calculate a two-dimensional Gaussian function: + return (1 / (2 * M_PI * pow(sigma, 2))) * exp(-(pow(x, 2) + pow(y, 2)) / (2 * pow(sigma, 2))); + +} + diff --git a/04/do_sprawdzenia/cpp/blur_linear.cpp b/04/do_sprawdzenia/cpp/blur_linear.cpp new file mode 100644 index 0000000..11ddc59 --- /dev/null +++ b/04/do_sprawdzenia/cpp/blur_linear.cpp @@ -0,0 +1,40 @@ +#include "blur_linear.h" + +BlurLinear::BlurLinear(PNM* img) : + Convolution(img) +{ +} + +BlurLinear::BlurLinear(PNM* img, ImageViewer* iv) : + Convolution(img, iv) +{ +} + +PNM* BlurLinear::transform() +{ + int maskSize = getParameter("size").toInt(); + QList tmpMask = getParameter("mask").toList(); + bool normalize = getParameter("normalize").toBool(); + + math::matrix mask(maskSize, maskSize); + + int maskValCount = 0; + + for (int i=0; i < maskSize; i++) + { + for (int j=0; j < maskSize; j++) + { + if (normalize) + { + mask[i][j] = tmpMask.at(maskValCount).toDouble() / Convolution::sum(mask); + maskValCount++; + } + else + { + mask[i][j] = tmpMask.at(maskValCount).toDouble(); + maskValCount++; + } + } + } + return convolute(mask, RepeatEdge); +} diff --git a/04/do_sprawdzenia/cpp/blur_uniform.cpp b/04/do_sprawdzenia/cpp/blur_uniform.cpp new file mode 100644 index 0000000..71a3c85 --- /dev/null +++ b/04/do_sprawdzenia/cpp/blur_uniform.cpp @@ -0,0 +1,25 @@ +#include "blur_uniform.h" + +BlurUniform::BlurUniform(PNM* img) : + Convolution(img) +{ +} + +BlurUniform::BlurUniform(PNM* img, ImageViewer* iv) : + Convolution(img, iv) +{ +} + +math::matrix BlurUniform::getMask(int size, Mode) +{ + math::matrix mask(size, size); + + for (int i=0; i < size; i++) + { + for (int j=0; j < size; j++) + { + mask[i][j] = 1; + } + } + return mask; +} diff --git a/04/do_sprawdzenia/cpp/convolution.cpp b/04/do_sprawdzenia/cpp/convolution.cpp new file mode 100644 index 0000000..a35e9e1 --- /dev/null +++ b/04/do_sprawdzenia/cpp/convolution.cpp @@ -0,0 +1,173 @@ +#include "convolution.h" + +/** Overloaded constructor */ +Convolution::Convolution(PNM* img) : + Transformation(img) +{ +} + +Convolution::Convolution(PNM* img, ImageViewer* iv) : + Transformation(img, iv) +{ +} + +/** Returns a convoluted form of the image */ +PNM* Convolution::transform() +{ + return convolute(getMask(3, Normalize), RepeatEdge); +} + +/** Returns a sizeXsize matrix with the center point equal 1.0 */ +math::matrix Convolution::getMask(int size, Mode mode = Normalize) +{ + math::matrix mask(size, size); + + // Get center of image + int center = size/2; + + // Get mask + for (int i=0; i < size; i++) + { + for (int j=0; j < size; j++) + { + if (i==j && i == center && j == center) + { + mask[i][j] = 1; + } + else + { + mask[i][j] = 0; + } + } + } + return mask; +} + +/** Does the convolution process for all pixels using the given mask. */ +PNM* Convolution::convolute(math::matrix mask, Mode mode = RepeatEdge) +{ + int width = image->width(), + height = image->height(); + + PNM* newImage = new PNM(width, height, image->format()); + + float weight = Convolution::sum(mask); + + math::matrix reflection = Convolution::reflection(mask); + for (int x=0; x < width ; x++) + { + for (int y=0; y < height; y++) + { + math::matrix rAcc = Convolution::join(getWindow(x, y, mask.rowno(), Transformation::RChannel, mode), reflection); + math::matrix gAcc = Convolution::join(getWindow(x, y, mask.rowno(), Transformation::GChannel, mode), reflection); + math::matrix bAcc = Convolution::join(getWindow(x, y, mask.rowno(), Transformation::BChannel, mode), reflection); + + float rAccSum = Convolution::sum(rAcc); + float gAccSum = Convolution::sum(gAcc); + float bAccSum = Convolution::sum(bAcc); + + + if (weight != 0) + { + rAccSum = rAccSum / weight; + gAccSum = gAccSum / weight; + bAccSum = bAccSum / weight; + } + + // Calculate Red Accumulate Sum + if (rAccSum < 0) + { + rAccSum = 0; + } + else if (rAccSum > 255) + { + rAccSum = 255; + } + + // Calculate Green Accumulate Sum + if (gAccSum < 0) + { + gAccSum = 0; + } + else if (gAccSum > 255) + { + gAccSum = 255; + } + + // Calculate Blue Accumulate Sum + if (bAccSum < 0) + { + bAccSum = 0; + } + else if(bAccSum > 255) + { + bAccSum = 255; + } + + // Create pixel + QColor newPixel = QColor(rAccSum, gAccSum, bAccSum); + + // Set pixel + newImage->setPixel(x,y, newPixel.rgb()); + } + } + return newImage; +} + +/** Joins to matrices by multiplying the A[i,j] with B[i,j]. + * Warning! Both Matrices must be squares with the same size! + */ +const math::matrix Convolution::join(math::matrix A, math::matrix B) +{ + int size = A.rowno(); + math::matrix C(size, size); + + + for (int i=0; i < size; i++) + { + for (int j=0; j < size; j++) + { + // Multiplication + C[i][j] = A[i][j] * B[i][j]; + } + } + + return C; +} + +/** Sums all of the matrixes elements */ +const float Convolution::sum(const math::matrix A) +{ + float sum = 0.0; + + int size = A.rowno(); + + for (int i=0; i Convolution::reflection(const math::matrix A) +{ + int size = A.rowno(); + math::matrix C(size, size); + + + for (int i=0; i < size; i++) + { + for (int j=0; j < size; j++) + { + C[i][j] = A[size-i-1][size-j-1]; + } + } + + return C; +} diff --git a/app/cpp/mysimplegimp/src/core/transformations/blur_gaussian.cpp b/app/cpp/mysimplegimp/src/core/transformations/blur_gaussian.cpp index 3eba6e4..d4d97c4 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/blur_gaussian.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/blur_gaussian.cpp @@ -25,15 +25,22 @@ math::matrix BlurGaussian::getMask(int size, Mode) { math::matrix mask(size, size); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + for (int i = 0; i < size; i++) + { + for (int j = 0; j < size; j++) + { + mask(i,j) = getGauss(i-radius, j-radius, sigma); + } + } + return mask; } float BlurGaussian::getGauss(int x, int y, float sigma) { - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + // Calculate a two-dimensional Gaussian function: + return (1 / (2 * M_PI * pow(sigma, 2))) * exp(-(pow(x, 2) + pow(y, 2)) / (2 * pow(sigma, 2))); - return 0; } diff --git a/app/cpp/mysimplegimp/src/core/transformations/blur_linear.cpp b/app/cpp/mysimplegimp/src/core/transformations/blur_linear.cpp index c24f9e8..11ddc59 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/blur_linear.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/blur_linear.cpp @@ -18,7 +18,23 @@ PNM* BlurLinear::transform() math::matrix mask(maskSize, maskSize); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + int maskValCount = 0; + for (int i=0; i < maskSize; i++) + { + for (int j=0; j < maskSize; j++) + { + if (normalize) + { + mask[i][j] = tmpMask.at(maskValCount).toDouble() / Convolution::sum(mask); + maskValCount++; + } + else + { + mask[i][j] = tmpMask.at(maskValCount).toDouble(); + maskValCount++; + } + } + } return convolute(mask, RepeatEdge); } diff --git a/app/cpp/mysimplegimp/src/core/transformations/blur_uniform.cpp b/app/cpp/mysimplegimp/src/core/transformations/blur_uniform.cpp index 36604c4..71a3c85 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/blur_uniform.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/blur_uniform.cpp @@ -14,7 +14,12 @@ math::matrix BlurUniform::getMask(int size, Mode) { math::matrix mask(size, size); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; - + for (int i=0; i < size; i++) + { + for (int j=0; j < size; j++) + { + mask[i][j] = 1; + } + } return mask; } diff --git a/app/cpp/mysimplegimp/src/core/transformations/convolution.cpp b/app/cpp/mysimplegimp/src/core/transformations/convolution.cpp index 71864b7..a35e9e1 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/convolution.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/convolution.cpp @@ -22,8 +22,24 @@ math::matrix Convolution::getMask(int size, Mode mode = Normalize) { math::matrix mask(size, size); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + // Get center of image + int center = size/2; + // Get mask + for (int i=0; i < size; i++) + { + for (int j=0; j < size; j++) + { + if (i==j && i == center && j == center) + { + mask[i][j] = 1; + } + else + { + mask[i][j] = 0; + } + } + } return mask; } @@ -35,8 +51,66 @@ PNM* Convolution::convolute(math::matrix mask, Mode mode = RepeatEdge) PNM* newImage = new PNM(width, height, image->format()); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + float weight = Convolution::sum(mask); + math::matrix reflection = Convolution::reflection(mask); + for (int x=0; x < width ; x++) + { + for (int y=0; y < height; y++) + { + math::matrix rAcc = Convolution::join(getWindow(x, y, mask.rowno(), Transformation::RChannel, mode), reflection); + math::matrix gAcc = Convolution::join(getWindow(x, y, mask.rowno(), Transformation::GChannel, mode), reflection); + math::matrix bAcc = Convolution::join(getWindow(x, y, mask.rowno(), Transformation::BChannel, mode), reflection); + + float rAccSum = Convolution::sum(rAcc); + float gAccSum = Convolution::sum(gAcc); + float bAccSum = Convolution::sum(bAcc); + + + if (weight != 0) + { + rAccSum = rAccSum / weight; + gAccSum = gAccSum / weight; + bAccSum = bAccSum / weight; + } + + // Calculate Red Accumulate Sum + if (rAccSum < 0) + { + rAccSum = 0; + } + else if (rAccSum > 255) + { + rAccSum = 255; + } + + // Calculate Green Accumulate Sum + if (gAccSum < 0) + { + gAccSum = 0; + } + else if (gAccSum > 255) + { + gAccSum = 255; + } + + // Calculate Blue Accumulate Sum + if (bAccSum < 0) + { + bAccSum = 0; + } + else if(bAccSum > 255) + { + bAccSum = 255; + } + + // Create pixel + QColor newPixel = QColor(rAccSum, gAccSum, bAccSum); + + // Set pixel + newImage->setPixel(x,y, newPixel.rgb()); + } + } return newImage; } @@ -48,7 +122,15 @@ const math::matrix Convolution::join(math::matrix A, math::matrix< int size = A.rowno(); math::matrix C(size, size); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + + for (int i=0; i < size; i++) + { + for (int j=0; j < size; j++) + { + // Multiplication + C[i][j] = A[i][j] * B[i][j]; + } + } return C; } @@ -58,10 +140,17 @@ const float Convolution::sum(const math::matrix A) { float sum = 0.0; - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + int size = A.rowno(); + for (int i=0; i Convolution::reflection(const math::matrix A) int size = A.rowno(); math::matrix C(size, size); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + + for (int i=0; i < size; i++) + { + for (int j=0; j < size; j++) + { + C[i][j] = A[size-i-1][size-j-1]; + } + } return C; } diff --git a/app/cpp/mysimplegimp/src/core/transformations/transformation.cpp b/app/cpp/mysimplegimp/src/core/transformations/transformation.cpp index 18a3e0a..cf1aca0 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/transformation.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/transformation.cpp @@ -103,8 +103,14 @@ QRgb Transformation::getPixel(int x, int y, Mode mode) */ QRgb Transformation::getPixelCyclic(int x, int y) { - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + int width = image->width(); + int height = image->height(); + // Return a pixel by looping the image + x = x % width; + y = y % height; + + // Return pixel return image->pixel(x,y); } @@ -114,8 +120,15 @@ QRgb Transformation::getPixelCyclic(int x, int y) */ QRgb Transformation::getPixelNull(int x, int y) { - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + int width = image->width(); + int height = image->height(); + // Return black as a pixel when out of range + if (x > width || x < 0 || y > height || y < 0){ + return Qt::black; + } + + // Return pixel return image->pixel(x,y); } @@ -126,7 +139,19 @@ QRgb Transformation::getPixelNull(int x, int y) */ QRgb Transformation::getPixelRepeat(int x, int y) { - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + int width = image->width(); + int height = image->height(); + + // Copy nearest edge pixel + if (x<0 && y<0) return image->pixel(0,0); + else if (x>=width && y<0) return image->pixel(width-1,0); + else if (x>=width && y>=height) return image->pixel(width-1,height-1); + else if (x<0 && y>=height) return image->pixel(0,height-1); + else if (x<0) return image->pixel(0,y); + else if (y<0) return image->pixel(x,0); + else if (x>=width) return image->pixel(width-1,y); + else if (y>=height) return image->pixel(x,height-1); + else return image->pixel(x,y); return image->pixel(x,y); } @@ -138,8 +163,33 @@ math::matrix Transformation::getWindow(int x, int y, int size, { math::matrix window(size,size); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + // Calculate center + int center = size/2; + // Get window + for (int i=0; i < size; i++) + { + for (int j=0; j < size; j++) + { + QRgb pixelVal = getPixel(x-center+i, y-center+j, mode); + if (channel == RChannel) + { + window[i][j] = qRed(pixelVal); + } + else if (channel == GChannel) + { + window[i][j] = qGreen(pixelVal); + } + else if (channel == BChannel) + { + window[i][j] = qBlue(pixelVal); + } + else if (channel == LChannel) + { + window[i][j] = qGray(pixelVal); + } + } + } return window; }