diff --git a/documents/references.md b/documents/references.md index 08e21a27b8135a6d1f28fd1d599bda33b5691d0a..2f4ba47cf8408dbd78b55b3e241260f55fe8f6c3 100644 --- a/documents/references.md +++ b/documents/references.md @@ -88,4 +88,13 @@ Various references used in project. <https://en.wikipedia.org/wiki/Netpbm> ### Convolution Logic +* Influencing Type of Convolution with Mask - <https://aishack.in/tutorials/image-convolution-examples/> * Gaussian Blur - <https://computergraphics.stackexchange.com/questions/39/how-is-gaussian-blur-implemented> +* Line Detection via "Laplacian of Gaussian" - <https://automaticaddison.com/how-the-laplacian-of-gaussian-filter-works/> + +### Fourier Transform +* Concept Introduction - "But what is the Fourier Transform? A visual introduction", by 3Blue1Brown <https://www.youtube.com/watch?v=spUNpyF58BY> +* Application to Images - "Fourier transforms in image processing (Maths Relevance)", by Swinburne Commons <https://www.youtube.com/watch?v=gwaYwRwY6PU> + +### Mathematical Symbols "Pi" & "e" in C++ +<https://www.quantstart.com/articles/Mathematical-Constants-in-C/> diff --git a/part_2/image.cu b/part_2/image.cu index e81b6d2c2720cc764ebf2a7f85899051eb045a71..9d2e1c8d2f0d8a61dccb4ca63be98e41bfbd351d 100644 --- a/part_2/image.cu +++ b/part_2/image.cu @@ -151,21 +151,21 @@ __global__ void cuda_convolution_blur( // Calculate final pixel data based on mask loop values. if (convolution_total_r > 0.f) { // Handle for value greater than 0. - pixel_arr[pixel_index].r = (1.f / mask_weight_struct.r) * convolution_total_r; + pixel_arr[pixel_index].r = convolution_total_r; } else { pixel_arr[pixel_index].r = 0.f; } if (convolution_total_g > 0.f) { // Handle for value greater than 0. - pixel_arr[pixel_index].g = (1.f / mask_weight_struct.g) * convolution_total_g; + pixel_arr[pixel_index].g = convolution_total_g; } else { pixel_arr[pixel_index].g = 0.f; } if (convolution_total_b > 0.f) { // Handle for value greater than 0. - pixel_arr[pixel_index].b = (1 / mask_weight_struct.b) * convolution_total_b; + pixel_arr[pixel_index].b = convolution_total_b; } else { pixel_arr[pixel_index].b = 0.f; } @@ -501,6 +501,8 @@ void Image::compute() { if (mask_height < 3) { mask_height = 3; } + mask_width = 9; + mask_height = 9; int mask_middle_col = mask_width / 2; int mask_middle_row = mask_height / 2; @@ -516,7 +518,7 @@ void Image::compute() { unsigned long mask_struct_byte_count = mask_total_pixels * pixel_struct_size; // Initialize mask and set weights. - // printf("\n\n"); + printf("\n\n"); logger.info("Mask size: " + std::to_string(mask_width) + "x" + std::to_string(mask_height)); PixelStruct* mask_arr = new PixelStruct[mask_total_pixels]; PixelStruct mask_weight_struct = PixelStruct(0.f); @@ -525,15 +527,143 @@ void Image::compute() { // Get current overall mask index, based on row and col values. int mask_index = mask_col_index + (mask_row_index * mask_width); - // Calculate individual weights based on current x and y axis location of mask index, using distance from center point. - float mask_col_weight = (fabs(mask_middle_col - fabs(mask_middle_col - mask_col_index)) + 1) * mask_col_adj; - float mask_row_weight = (fabs(mask_middle_row - fabs(mask_middle_row - mask_row_index)) + 1) * mask_row_adj; - - // Calculate overall index weight, based on combination of individual dimension weights. - float index_weight = (mask_col_weight * mask_row_weight); - - // printf(" [%d, %d] (%d) (%f,%f) ", mask_col_index, mask_row_index, mask_index, mask_col_weight, mask_row_weight); - // printf(" [%d, %d] (%d) (%f) ", mask_col_index, mask_row_index, mask_index, index_weight); + // Transpose coordinates such that center of mask is at (0,0). + int x = mask_col_index - mask_middle_col; + int y = mask_row_index - mask_middle_row; + + // Get absolute values to simplify if statements + int abs_x = abs(x); + int abs_y = abs(y); + // printf(" [%d,%d] ", x, y); + // printf(" [%d,%d] ", abs_x, abs_y); + + // // Calculate mask weight. + int eq_x = mask_col_index - mask_middle_col; + int eq_y = mask_row_index - mask_middle_row; + // int x = eq_x; + // int y = eq_y; + // // printf(" [%d,%d] ", eq_x, eq_y); + + float squigl = 1.4f; + float pt_0 = ( ( pow(eq_x, 2.f) + pow(eq_y, 2.f) ) / (2.f * pow(squigl, 2.f)) ) ; + float pt_1 = -( 1.f / (M_PI * pow(squigl, 4.f)) ); + float pt_2 = ( 1.f - ( pt_0 ) ); + float pt_3 = pow( M_E, (-(pt_0)) ); + float LoG_eq = pt_1 * pt_2 * pt_3; + // Got this weight via calculator, by getting the difference between LoG_eq var and expected value. + float index_weight = LoG_eq * 482.749693982f; + + // if (x == 0 && y == 0) { + // printf("\n\n"); + // printf("x: %f y: %f\n", eq_x, eq_y); + // printf("squigl: %f\n", squigl); + // printf("pt_0: %f\n", pt_0); // (0,0) ~ 0 + // printf("pt_1: %f\n", pt_1); // (0,0) ~ 0.082858675 + // printf("pt_2: %f\n", pt_2); // (0,0) ~ 1 + // printf("pt_3: %f\n", pt_3); // (0,0) ~ 1 + // printf("LoG_eq: %f\n", LoG_eq); // (0,0) ~ + // printf("index_weight: %f\n", index_weight); // (0,0) ~ + // printf("\n\n"); + // } + + // // float sigma = 1.4f; + // // float s2 = sigma * sigma; + // // float s4 = sigma * sigma * sigma * sigma; + // // float index_weight = (float)(-1.0f / (M_PI * (s4))) * (1.0f - ((x * x + y * y) / (2.0f * (s2)))) * (float)(M_E * ((-(x * x + y * y) / (2.0f * (s2))))); + + + // // Since my equation isn't computing correctly and I don't have time to figure it out, + // // "cheat" my mask with if statements here. + // // Note that these set by absolute value of coord, since the four quadrants are symmetrical. + // float index_weight = 0.f; + // if ( (abs_x == 0) && (abs_y == 0) ) { + // // [0, 0] + // index_weight = -40.f; + // } else if ( (abs_x == 1) && (abs_y == 0) ) { + // // [1, 0] + // index_weight = -24.f; + // } else if ( (abs_x == 2) && (abs_y == 0) ) { + // // [2, 0] + // index_weight = 0.f; + // } else if ( (abs_x == 3) && (abs_y == 0) ) { + // // [3, 0] + // index_weight = 5.f; + // } else if ( (abs_x == 4) && (abs_y == 0) ) { + // // [4, 0] + // index_weight = 2.f; + // } else if ( (abs_x == 0) && (abs_y == 1) ) { + // // [0, 1] + // index_weight = -24.f; + // } else if ( (abs_x == 1) && (abs_y == 1) ) { + // // [1, 1] + // index_weight = -12.f; + // } else if ( (abs_x == 2) && (abs_y == 1) ) { + // // [2, 1] + // index_weight = 3.f; + // } else if ( (abs_x == 3) && (abs_y == 1) ) { + // // [3, 1] + // index_weight = 5.f; + // } else if ( (abs_x == 4) && (abs_y == 1) ) { + // // [4, 1] + // index_weight = 2.f; + // } else if ( (abs_x == 0) && (abs_y == 2) ) { + // // [0, 2] + // index_weight = 0.f; + // } else if ( (abs_x == 1) && (abs_y == 2) ) { + // // [1, 2] + // index_weight = 3.f; + // } else if ( (abs_x == 2) && (abs_y == 2) ) { + // // [2, 2] + // index_weight = 5.f; + // } else if ( (abs_x == 3) && (abs_y == 2) ) { + // // [3, 2] + // index_weight = 4.f; + // } else if ( (abs_x == 4) && (abs_y == 2) ) { + // // [4, 2] + // index_weight = 1.f; + // } else if ( (abs_x == 0) && (abs_y == 3) ) { + // // [0, 3] + // index_weight = 5.f; + // } else if ( (abs_x == 1) && (abs_y == 3) ) { + // // [1, 3] + // index_weight = 5.f; + // } else if ( (abs_x == 2) && (abs_y == 3) ) { + // // [2, 3] + // index_weight = 4.f; + // } else if ( (abs_x == 3) && (abs_y == 3) ) { + // // [3, 3] + // index_weight = 2.f; + // } else if ( (abs_x == 4) && (abs_y == 3) ) { + // // [4, 3] + // index_weight = 1.f; + // } else if ( (abs_x == 0) && (abs_y == 4) ) { + // // [0, 4] + // index_weight = 2.f; + // } else if ( (abs_x == 1) && (abs_y == 4) ) { + // // [1, 4] + // index_weight = 2.f; + // } else if ( (abs_x == 2) && (abs_y == 4) ) { + // // [2, 4] + // index_weight = 1.f; + // } else if ( (abs_x == 3) && (abs_y == 4) ) { + // // [3, 4] + // index_weight = 1.f; + // } else if ( (abs_x == 4) && (abs_y == 4) ) { + // // [4, 4] + // index_weight = 0.f; + // } + + // // // Calculate individual weights based on current x and y axis location of mask index, using distance from center point. + // // float mask_col_weight = (fabs(mask_middle_col - fabs(mask_middle_col - mask_col_index)) + 1) * mask_col_adj; + // // float mask_row_weight = (fabs(mask_middle_row - fabs(mask_middle_row - mask_row_index)) + 1) * mask_row_adj; + + // // // Calculate overall index weight, based on combination of individual dimension weights. + // // float index_weight = (mask_col_weight * mask_row_weight); + + // // printf(" [%d,%d] (%d) (%f,%f) ", mask_col_index, mask_row_index, mask_index, mask_col_weight, mask_row_weight); + // // printf(" [%d,%d] (%d) (%f) ", mask_col_index, mask_row_index, mask_index, index_weight); + // printf(" [%d,%d] (%f) ", mask_col_index, mask_row_index, index_weight); + printf(" (%f)", index_weight); // Finally, set mask index values. mask_arr[mask_index].r = index_weight; @@ -542,14 +672,14 @@ void Image::compute() { mask_weight_struct.r += index_weight; mask_weight_struct.g += index_weight; mask_weight_struct.b += index_weight; - // mask_arr[mask_index].r = 1.f; - // mask_arr[mask_index].g = 1.f; - // mask_arr[mask_index].b = 1.f; + // // mask_arr[mask_index].r = 1.f; + // // mask_arr[mask_index].g = 1.f; + // // mask_arr[mask_index].b = 1.f; } // printf("\n"); } // printf("Total Weights: r: %f g: %f b: %f\n", mask_weight_struct.r, mask_weight_struct.b, mask_weight_struct.g); - // printf("\n\n"); + printf("\n\n"); // Allocate memory on GPU. PixelStruct* gpu_pixel_arr; diff --git a/part_2/image.h b/part_2/image.h index a64cc8c0de6647e480888f277773d4fa312fcbfc..510149a1d327f2b9dab117b6f3795ffb7f989839 100644 --- a/part_2/image.h +++ b/part_2/image.h @@ -3,8 +3,12 @@ */ +#define _USE_MATH_DEFINES + + // System Import Headers. #include <cctype> +#include <cmath> #include <cstdio> #include <cstdlib> #include <filesystem>