diff --git a/010/do_sprawdzenia/cpp/edge_canny.cpp b/010/do_sprawdzenia/cpp/edge_canny.cpp new file mode 100644 index 0000000..24e63df --- /dev/null +++ b/010/do_sprawdzenia/cpp/edge_canny.cpp @@ -0,0 +1,289 @@ +#include "edge_canny.h" + +#include "blur_gaussian.h" +#include "conversion_grayscale.h" +#include "edge_sobel.h" + +EdgeCanny::EdgeCanny(PNM* img) : + Convolution(img) +{ +} + +EdgeCanny::EdgeCanny(PNM* img, ImageViewer* iv) : + Convolution(img, iv) +{ +} + + +void EdgeCanny::Calculate_XY(int i, int j, enum directions dir, int* x1, int* y1, int* x2, int* y2) +{ + switch (dir) + { + + case TOP_MIDDLE_BOTTOM_MIDDLE: + { + *x1 = i - 1; + *y1 = j; + *x2 = i + 1; + *y2 = j; + break; + } + + case LEFT_MIDDLE_RIGHT_MIDDLE: + { + *x1 = i; + *y1 = j - 1; + *x2 = i; + *y2 = j + 1; + break; + } + + case TOP_RIGHT_BOTTOM_LEFT: + { + *x1 = i - 1; + *y1 = j - 1; + *x2 = i + 1; + *y2 = j + 1; + break; + } + + case TOP_LEFT_BOTTOM_RIGHT: + { + *x1 = i - 1; + *y1 = j + 1; + *x2 = i + 1; + *y2 = j - 1; + break; + } + + } +} + +PNM* EdgeCanny::transform() +{ + int width = image->width(); + int height = image->height(); + + + int upper_thresh = getParameter("upper_threshold").toInt(); + int lower_thresh = getParameter("lower_threshold").toInt(); + + PNM* newImage = new PNM(width, height, image->format()); + + // Create grayscale + ConversionGrayscale* grayscale = new ConversionGrayscale(image); + PNM* gray_image = grayscale->transform(); + + // Blur grayscale + BlurGaussian* blur_gaussian = new BlurGaussian(gray_image); + blur_gaussian->setParameter("size", 3); + blur_gaussian->setParameter("sigma", 1.6); + PNM* blur_image = blur_gaussian->transform(); + + // Calculate Gx and Gy used EdgeSobel + EdgeSobel *es = new EdgeSobel(blur_image); + + math::matrixGx = *es->rawHorizontalDetection(); + math::matrixGy = *es->rawVerticalDetection(); + + // Define directions + + + // Matrix of pixel power + math::matrix pixelPower(width, height); + + // Marix od pixel Angle + math::matrix pixelAngle(width, height); + + // Matrix of pixel directions + math::matrix pixelDirection(width, height); + + // Matrix of edges + math::matrix edges(width, height); + + + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + // Calculate current pixel angle + pixelAngle[i][j] = atan2(Gy[i][j], Gx[i][j]) * 180 / M_PI; + + // Calculate current pixel power + pixelPower[i][j] = sqrt(pow(Gx[i][j], 2) + pow(Gy[i][j], 2)); + + // Set current pixel direction + if ((pixelAngle[i][j] > 22.5 && pixelAngle[i][j] <= 67.5) || + (pixelAngle[i][j] > 202.5 && pixelAngle[i][j] <= 247.5)) + { + pixelDirection[i][j] = TOP_LEFT_BOTTOM_RIGHT; + } + else if ((pixelAngle[i][j] > 67.5 && pixelAngle[i][j] <= 112.5) || + (pixelAngle[i][j] > 247.5 && pixelAngle[i][j] <= 292.5)) + { + pixelDirection[i][j] = TOP_MIDDLE_BOTTOM_MIDDLE; + } + else if ((pixelAngle[i][j] > 112.5 && pixelAngle[i][j] <= 157.5) || + (pixelAngle[i][j] > 292.5 && pixelAngle[i][j] <= 337.5)) + { + pixelDirection[i][j] = TOP_RIGHT_BOTTOM_LEFT; + } + else + { + pixelDirection[i][j] = LEFT_MIDDLE_RIGHT_MIDDLE; + } + + } + } + + // Detect edges + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + if (pixelDirection[i][j] == TOP_MIDDLE_BOTTOM_MIDDLE) + { + if (pixelPower[i][j] > pixelPower[i-1][j] && + pixelPower[i][j] > pixelPower[i+1][j] && + pixelPower[i][j] > upper_thresh) + { + edges[i][j] = true; + } + } + else if (pixelDirection[i][j] == LEFT_MIDDLE_RIGHT_MIDDLE) + { + if (pixelPower[i][j] > pixelPower[i][j-1] && + pixelPower[i][j] > pixelPower[i][j+1] && + pixelPower[i][j] > upper_thresh) + { + edges[i][j]=true; + } + } + else if (pixelDirection[i][j] == TOP_LEFT_BOTTOM_RIGHT) + { + if (pixelPower[i][j] > pixelPower[i-1][j+1] && + pixelPower[i][j] > pixelPower[i+1][j-1] && + pixelPower[i][j] > upper_thresh) + { + edges[i][j]=true; + } + } + else if (pixelDirection[i][j] == TOP_RIGHT_BOTTOM_LEFT) + { + if (pixelPower[i][j] > pixelPower[i+1][j+1] && + pixelPower[i][j] > pixelPower[i-1][j-1] && + pixelPower[i][j] > upper_thresh) + { + edges[i][j]=true; + } + } + } + } + + // Set variables + int x1 = 0; + int y1 = 0; + + int x2 = 0; + int y2 = 0; + + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + if (edges[i][j] == true) + { + Calculate_XY(i, j, pixelDirection[i][j], &x1, &y1, &x2, &y2); + + if (x1 < width && y1 < height && edges[x1][y1] != true) + { + if (pixelPower[x1][y1] > lower_thresh && pixelDirection[x1][y1] == pixelDirection[i][j]) + { + int x11 = 0; + int y11 = 0; + int x12 = 0; + int y12 = 0; + + Calculate_XY(x1, y1, pixelDirection[x1][y1], &x11, &y11, &x12, &y12); + + if (x11 < width && y11 < height && x12 < width && y12 < height) + { + if (pixelPower[x11][y11] < pixelPower[x1][y1] && pixelPower[x12][y12] < pixelPower[x1][y1]) + { + edges[x1][y1] = true; + } + } + else if (x11 < width && y11 < height) + { + if (pixelPower[x11][y11] < pixelPower[x1][y1]) + { + edges[x1][y1] = true; + } + } + else if (x12 < width && y12 < height) + { + if (pixelPower[x12][y12] < pixelPower[x1][y1]) + { + edges[x1][y1] = true; + } + } + + } + } + + if (x2 < width && y2 < height && edges[x2][y2] != true) + { + if (pixelPower[x2][y2] > lower_thresh && pixelDirection[x2][y2] == pixelDirection[i][j]) + { + int x21 = 0; + int y21 = 0; + int x22 = 0; + int y22 = 0; + + Calculate_XY(x2, y2, pixelDirection[x2][y2], &x21, &y21, &x22, &y22); + + if (x21 < width && y21 < height && x22 < width && y22 < height) + { + if (pixelPower[x21][y21] < pixelPower[x2][y2] && pixelPower[x22][y22] < pixelPower[x2][y2]) + { + edges[x2][y2] = true; + } + } + else if (x21 < width && y21 < height) + { + if (pixelPower[x21][y21] < pixelPower[x2][y2]) + { + edges[x2][y2] = true; + } + } + else if (x22 < width && y22 < height) + { + if (pixelPower[x22][y22] < pixelPower[x2][y2]) + { + edges[x2][y2] = true; + } + } + } + } + } + } + } + + // Prepare new image + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + if (edges[i][j] == true) + { + newImage->setPixel(i, j, 255); + } + else + { + newImage->setPixel(i, j, 0); + } + } + } + + return newImage; +} diff --git a/010/do_sprawdzenia/cpp/edge_canny.h b/010/do_sprawdzenia/cpp/edge_canny.h new file mode 100644 index 0000000..71f1e9c --- /dev/null +++ b/010/do_sprawdzenia/cpp/edge_canny.h @@ -0,0 +1,26 @@ +#ifndef EDGECANNY_H +#define EDGECANNY_H + +#include "convolution.h" + +class EdgeCanny : public Convolution +{ +public: + EdgeCanny(PNM*); + EdgeCanny(PNM*, ImageViewer*); + + virtual PNM* transform(); + enum directions { + TOP_LEFT_BOTTOM_RIGHT, + TOP_RIGHT_BOTTOM_LEFT, + TOP_MIDDLE_BOTTOM_MIDDLE, + LEFT_MIDDLE_RIGHT_MIDDLE + }; + + void Calculate_XY(int i, int j, enum directions dir, int* x1, int* y1, int* x2, int* y2); + +private: + +}; + +#endif // EDGECANNY_H diff --git a/010/do_sprawdzenia/cpp/image1.png b/010/do_sprawdzenia/cpp/image1.png new file mode 100644 index 0000000..7241306 Binary files /dev/null and b/010/do_sprawdzenia/cpp/image1.png differ diff --git a/app/cpp/mysimplegimp/src/core/transformations/edge_canny.cpp b/app/cpp/mysimplegimp/src/core/transformations/edge_canny.cpp index b52129f..3daeffc 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/edge_canny.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/edge_canny.cpp @@ -14,17 +14,276 @@ EdgeCanny::EdgeCanny(PNM* img, ImageViewer* iv) : { } + +void EdgeCanny::Calculate_XY(int i, int j, enum directions dir, int* x1, int* y1, int* x2, int* y2) +{ + switch (dir) + { + + case TOP_MIDDLE_BOTTOM_MIDDLE: + { + *x1 = i - 1; + *y1 = j; + *x2 = i + 1; + *y2 = j; + break; + } + + case LEFT_MIDDLE_RIGHT_MIDDLE: + { + *x1 = i; + *y1 = j - 1; + *x2 = i; + *y2 = j + 1; + break; + } + + case TOP_RIGHT_BOTTOM_LEFT: + { + *x1 = i - 1; + *y1 = j - 1; + *x2 = i + 1; + *y2 = j + 1; + break; + } + + case TOP_LEFT_BOTTOM_RIGHT: + { + *x1 = i - 1; + *y1 = j + 1; + *x2 = i + 1; + *y2 = j - 1; + break; + } + + } +} + PNM* EdgeCanny::transform() { - int width = image->width(), - height = image->height(); + int width = image->width(); + int height = image->height(); - int upper_thresh = getParameter("upper_threshold").toInt(), - lower_thresh = getParameter("lower_threshold").toInt(); - PNM* newImage = new PNM(width, height, QImage::Format_Grayscale8); + int upper_thresh = getParameter("upper_threshold").toInt(); + int lower_thresh = getParameter("lower_threshold").toInt(); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + PNM* newImage = new PNM(width, height, image->format()); + + // Create grayscale + ConversionGrayscale* grayscale = new ConversionGrayscale(image); + PNM* gray_image = grayscale->transform(); + + // Blur grayscale + BlurGaussian* blur_gaussian = new BlurGaussian(gray_image); + blur_gaussian->setParameter("size", 3); + blur_gaussian->setParameter("sigma", 1.6); + PNM* blur_image = blur_gaussian->transform(); + + // Calculate Gx and Gy used EdgeSobel + EdgeSobel *es = new EdgeSobel(blur_image); + + math::matrixGx = *es->rawHorizontalDetection(); + math::matrixGy = *es->rawVerticalDetection(); + + // Define directions + + + // Matrix of pixel power + math::matrix pixelPower(width, height); + + // Marix od pixel Angle + math::matrix pixelAngle(width, height); + + // Matrix of pixel directions + math::matrix pixelDirection(width, height); + + // Matrix of edges + math::matrix edges(width, height); + + + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + // Calculate current pixel angle + pixelAngle[i][j] = atan2(Gy[i][j], Gx[i][j]) * 180 / M_PI; + + // Calculate current pixel power + pixelPower[i][j] = sqrt(pow(Gx[i][j], 2) + pow(Gy[i][j], 2)); + + // Set current pixel direction + if ((pixelAngle[i][j] > 22.5 && pixelAngle[i][j] <= 67.5) || + (pixelAngle[i][j] > 202.5 && pixelAngle[i][j] <= 247.5)) + { + pixelDirection[i][j] = TOP_LEFT_BOTTOM_RIGHT; + } + else if ((pixelAngle[i][j] > 67.5 && pixelAngle[i][j] <= 112.5) || + (pixelAngle[i][j] > 247.5 && pixelAngle[i][j] <= 292.5)) + { + pixelDirection[i][j] = TOP_MIDDLE_BOTTOM_MIDDLE; + } + else if ((pixelAngle[i][j] > 112.5 && pixelAngle[i][j] <= 157.5) || + (pixelAngle[i][j] > 292.5 && pixelAngle[i][j] <= 337.5)) + { + pixelDirection[i][j] = TOP_RIGHT_BOTTOM_LEFT; + } + else + { + pixelDirection[i][j] = LEFT_MIDDLE_RIGHT_MIDDLE; + } + + } + } + + // Detect edges + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + if (pixelDirection[i][j] == TOP_MIDDLE_BOTTOM_MIDDLE) + { + if (pixelPower[i][j] > pixelPower[i-1][j] && + pixelPower[i][j] > pixelPower[i+1][j] && + pixelPower[i][j] > upper_thresh) + { + edges[i][j] = true; + } + } + else if (pixelDirection[i][j] == LEFT_MIDDLE_RIGHT_MIDDLE) + { + if (pixelPower[i][j] > pixelPower[i][j-1] && + pixelPower[i][j] > pixelPower[i][j+1] && + pixelPower[i][j] > upper_thresh) + { + edges[i][j]=true; + } + } + else if (pixelDirection[i][j] == TOP_LEFT_BOTTOM_RIGHT) + { + if (pixelPower[i][j] > pixelPower[i-1][j+1] && + pixelPower[i][j] > pixelPower[i+1][j-1] && + pixelPower[i][j] > upper_thresh) + { + edges[i][j]=true; + } + } + else if (pixelDirection[i][j] == TOP_RIGHT_BOTTOM_LEFT) + { + if (pixelPower[i][j] > pixelPower[i+1][j+1] && + pixelPower[i][j] > pixelPower[i-1][j-1] && + pixelPower[i][j] > upper_thresh) + { + edges[i][j]=true; + } + } + } + } + + // Set variables + int x1 = 0; + int y1 = 0; + + int x2 = 0; + int y2 = 0; + + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + if (edges[i][j] == true) + { + Calculate_XY(i, j, pixelDirection[i][j], &x1, &y1, &x2, &y2); + + if (x1 < width && y1 < height && edges[x1][y1] != true) + { + if (pixelPower[x1][y1] > lower_thresh && pixelDirection[x1][y1] == pixelDirection[i][j]) + { + int x11 = 0; + int y11 = 0; + int x12 = 0; + int y12 = 0; + + Calculate_XY(x1, y1, pixelDirection[x1][y1], &x11, &y11, &x12, &y12); + + if (x11 < width && y11 < height && x12 < width && y12 < height) + { + if (pixelPower[x11][y11] < pixelPower[x1][y1] && pixelPower[x12][y12] < pixelPower[x1][y1]) + { + edges[x1][y1] = true; + } + } + else if (x11 < width && y11 < height) + { + if (pixelPower[x11][y11] < pixelPower[x1][y1]) + { + edges[x1][y1] = true; + } + } + else if (x12 < width && y12 < height) + { + if (pixelPower[x12][y12] < pixelPower[x1][y1]) + { + edges[x1][y1] = true; + } + } + + } + } + + if (x2 < width && y2 < height && edges[x2][y2] != true) + { + if (pixelPower[x2][y2] > lower_thresh && pixelDirection[x2][y2] == pixelDirection[i][j]) + { + int x21 = 0; + int y21 = 0; + int x22 = 0; + int y22 = 0; + + Calculate_XY(x2, y2, pixelDirection[x2][y2], &x21, &y21, &x22, &y22); + + if (x21 < width && y21 < height && x22 < width && y22 < height) + { + if (pixelPower[x21][y21] < pixelPower[x2][y2] && pixelPower[x22][y22] < pixelPower[x2][y2]) + { + edges[x2][y2] = true; + } + } + else if (x21 < width && y21 < height) + { + if (pixelPower[x21][y21] < pixelPower[x2][y2]) + { + edges[x2][y2] = true; + } + } + else if (x22 < width && y22 < height) + { + if (pixelPower[x22][y22] < pixelPower[x2][y2]) + { + edges[x2][y2] = true; + } + } + } + } + } + } + } + + // Prepare new image + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + if (edges[i][j] == true) + { + newImage->setPixel(i, j, QColor(Qt::white).rgb()); + } + else + { + newImage->setPixel(i, j, QColor(Qt::black).rgb()); + } + } + } return newImage; } diff --git a/app/cpp/mysimplegimp/src/core/transformations/edge_canny.h b/app/cpp/mysimplegimp/src/core/transformations/edge_canny.h index 9bf344d..71f1e9c 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/edge_canny.h +++ b/app/cpp/mysimplegimp/src/core/transformations/edge_canny.h @@ -10,7 +10,14 @@ public: EdgeCanny(PNM*, ImageViewer*); virtual PNM* transform(); + enum directions { + TOP_LEFT_BOTTOM_RIGHT, + TOP_RIGHT_BOTTOM_LEFT, + TOP_MIDDLE_BOTTOM_MIDDLE, + LEFT_MIDDLE_RIGHT_MIDDLE + }; + void Calculate_XY(int i, int j, enum directions dir, int* x1, int* y1, int* x2, int* y2); private: