/* Astico2D: Another Simple Tool for Image Computing with OpenCV in 2D https://pageperso.lis-lab.fr/edouard.thiel/Astico2D/ demo2.cpp - example 2 of Astico2D use: - Transformations triggered by the keyboard: '1' and '2' - Add a slider, also keyboard responsive ('t' and 'T') - Manage a flag to change the nature of a drawing ('n') and display the flag in the title bar of the View window - Display result in RGB (for transformation '1') - Creation of a Red/Green palette (for transformation '2') - place to handle the command line arguments Usage : $ make demo2 $ ./demo2 [-mag w h] [-thr threshold] [-o image_res] image_src CC BY-SA Edouard.Thiel@univ-amu.fr - 30/07/2023 - v1.1 */ #include "astico2d.hpp" //----------------------- T R A N S F O R M A T I O N S ----------------------- // Place here your image transformations in place of these examples. enum DrawingNature { D_WHITE, D_BLACK, D_BLUE, D_REV, D_LAST }; std::string drawing_names[4] = {"white", "black", "blue", "reverse"}; void draw_colored_checkerboard (cv::Mat &img_col, int size, int colR, int colG, int colB) { CHECK_MAT_TYPE(img_col, CV_8UC3); for (int y = 0; y < img_col.rows; y++) for (int x = 0; x < img_col.cols; x++) { int cell_num_x = x / size; int cell_num_y = y / size; if ((cell_num_x + cell_num_y) % 2) { // Attention img_col is in B, G, R order img_col.at(y,x)[0] = colB; img_col.at(y,x)[1] = colG; img_col.at(y,x)[2] = colR; } } } void draw_reversed_checkerboard (cv::Mat &img_col, int size) { CHECK_MAT_TYPE(img_col, CV_8UC3); for (int y = 0; y < img_col.rows; y++) for (int x = 0; x < img_col.cols; x++) { int cell_num_x = x / size; int cell_num_y = y / size; if ((cell_num_x + cell_num_y) % 2) { img_col.at(y,x)[0] = 255 - img_col.at(y,x)[0]; img_col.at(y,x)[1] = 255 - img_col.at(y,x)[1]; img_col.at(y,x)[2] = 255 - img_col.at(y,x)[2]; } } } void draw_checkerboard (cv::Mat &img_col, int size, DrawingNature nat) { switch (nat) { case D_WHITE : draw_colored_checkerboard (img_col, size, 255, 255, 255); break; case D_BLACK : draw_colored_checkerboard (img_col, size, 0, 0, 0); break; case D_BLUE : draw_colored_checkerboard (img_col, size, 0, 0, 255); break; case D_REV : draw_reversed_checkerboard (img_col, size); break; default : std::cout << "Error, unexpected drawing nature" << std::endl; } } void compute_differences_in_x (cv::Mat &img_int) { CHECK_MAT_TYPE(img_int, CV_32SC1); // Remark: since the image img_int is thresholded (values 0 or 255), the // result will be in { -255, 0, 255 }. for (int y = img_int.rows-1; y > 0; y--) for (int x = img_int.cols-1; x > 0; x--) { img_int.at(y,x) = img_int.at(y,x) - img_int.at(y,x-1); } } void translate_in_red_or_green (cv::Mat &img_int, cv::Mat &img_col) { CHECK_MAT_TYPE(img_int, CV_32SC1); CHECK_MAT_TYPE(img_col, CV_8UC3); // Red palette for negative values, green palette for positive values for (int y = 0; y < img_int.rows; y++) for (int x = 0; x < img_int.cols; x++) { int g = img_int.at(y,x); // Attention img_col is in B, G, R order if (g >= 0) { img_col.at(y,x)[0] = 0; img_col.at(y,x)[1] = g % 256; // Green img_col.at(y,x)[2] = 0; } else { img_col.at(y,x)[0] = 0; img_col.at(y,x)[1] = 0; img_col.at(y,x)[2] = (-g) % 256; // Red } } } //--------------------------- A P P L I C A T I O N --------------------------- class MyApp : public Astico2D { public: // Declare here other members int size = 20, size_max = 100; DrawingNature drawing_nature = D_WHITE; MyApp (int argc, char **argv) : Astico2D (argc, argv) // initialize here your member classes { if (!init_ok) return; // error during initialization // We create a slider "Size" that will manipulate the member size // in the interval 0 to size_max. create_slider ("Size", &size, size_max); // Manage remaining command-line arguments while (argc > 0) { if (!strcmp(argv[0], "-t")) { if (argc < 2) break; // 2 arguments expected modify_slider ("Size", atoi(argv[1])); argc -= 2; argv += 2; // shift of 2 arguments } else break; } if (argc > 0) { std::cout << "Arguments unexpected or incomplete: "; for (int i = 0; i < argc; i++) std::cout << " " << argv[i]; std::cout << std::endl; print_usage(); // Print here the syntax for additional arguments std::cout << "Other options: " << "[-t size]" << std::endl; exit (1); } } void print_keyboard_keys () override { // This prints the default usage Astico2D::print_keyboard_keys (); // Indicate keyboard keys and corresponding transformations std::cout << " 1 draw a checkerboard onto the thresholded image in RGB\n" " sS change the slider Size\n" " n change the drawing nature\n" " 2 show the differences in x, using a red/green palette\n" << std::endl; } bool handle_keyboard (char key) override { switch (key) { // Handle here the flags case 's' : decrease_slider ("Size", 0); break; case 'S' : increase_slider ("Size", size_max); break; case 'n' : { int nd = static_cast(drawing_nature)+1; if (nd == static_cast(D_LAST)) nd = 0; drawing_nature = static_cast(nd); rename_view_window ("View - "+drawing_names[nd]); std::cout << "Drawing nature: " << drawing_names[nd] << std::endl; break; } // Add keys for process_transformations case '1' : // Memorize the pressed key key_transform = key; // Specify mode M_LEVELS or M_COLORS mode_transform = M_COLORS; break; case '2' : key_transform = key; mode_transform = M_LEVELS; break; default : return false; // key not handled } return true; // key handled } void process_transformations () override { // Call here your transforms depending on key_transform and mode_transform: // - if mode_transform is M_COLORS, you can work directly in img_col, // which has the type CV_8UC3; it will be displayed as is. // - if mode_transform is M_LEVELS, the starting image is the thresholded // image img_int, of type CV_32SC1; at the end, to be displayed, you // need to convert the image in colors in img_col, of type CV_8UC3, // for instance with the help of translate_to_vga_colors. switch (key_transform) { case '1' : // M_COLORS draw_checkerboard (img_col, size, drawing_nature); break; case '2' : // M_LEVELS compute_differences_in_x (img_int); translate_in_red_or_green (img_int, img_col); break; } } }; //class MyApp //---------------------------------- M A I N ---------------------------------- int main (int argc, char **argv) { MyApp app (argc, argv); return app.run (); }