m2b-gd-tp8/demo2.cpp

245 lines
7.3 KiB
C++

/*
demo2.cpp - exemple d'utilisation de Astico2D
CC BY-SA Edouard.Thiel@univ-amu.fr - 22/08/2021
Usage :
$ make demo2
$ ./demo2 [-mag width height] [-thr seuil] image_in [image_out]
*/
/*
Pour le rendu de TP :
- renommez ce fichier tp<n°-de-la-planche>-<vos-noms>.cpp
- écrivez ci-dessous vos NOMS Prénoms et la date de la version :
<NOM1 Prénom1> [et <NOM2 Prénom2>] - version du <date>
*/
#include "astico2d.hpp"
//----------------------- T R A N S F O R M A T I O N S -----------------------
// Placez ici vos fonctions de transformations à la place de ces exemples
enum NatureDessin { D_BLANC, D_NOIR, D_BLEU, D_INV, D_LAST };
char const *nom_dessins[4] = {"blanc", "noir", "bleu", "inverse"};
void dessiner_damier_couleur (cv::Mat &img_coul, int taille,
int coulR, int coulG, int coulB)
{
CHECK_MAT_TYPE(img_coul, CV_8UC3);
for (int y = 0; y < img_coul.rows; y++)
for (int x = 0; x < img_coul.cols; x++)
{
int numero_case_x = x / taille;
int numero_case_y = y / taille;
if ((numero_case_x + numero_case_y) % 2) {
// Attention img_coul est en B, G, R
img_coul.at<cv::Vec3b>(y,x)[0] = coulB;
img_coul.at<cv::Vec3b>(y,x)[1] = coulG;
img_coul.at<cv::Vec3b>(y,x)[2] = coulR;
}
}
}
void dessiner_damier_inverse (cv::Mat &img_coul, int taille)
{
CHECK_MAT_TYPE(img_coul, CV_8UC3);
for (int y = 0; y < img_coul.rows; y++)
for (int x = 0; x < img_coul.cols; x++)
{
int numero_case_x = x / taille;
int numero_case_y = y / taille;
if ((numero_case_x + numero_case_y) % 2) {
img_coul.at<cv::Vec3b>(y,x)[0] = 255 - img_coul.at<cv::Vec3b>(y,x)[0];
img_coul.at<cv::Vec3b>(y,x)[1] = 255 - img_coul.at<cv::Vec3b>(y,x)[1];
img_coul.at<cv::Vec3b>(y,x)[2] = 255 - img_coul.at<cv::Vec3b>(y,x)[2];
}
}
}
void dessiner_damier (cv::Mat &img_coul, int taille, NatureDessin nat)
{
switch (nat) {
case D_BLANC :
dessiner_damier_couleur (img_coul, taille, 255, 255, 255);
break;
case D_NOIR :
dessiner_damier_couleur (img_coul, taille, 0, 0, 0);
break;
case D_BLEU :
dessiner_damier_couleur (img_coul, taille, 0, 0, 255);
break;
case D_INV :
dessiner_damier_inverse (img_coul, taille);
break;
default :
std::cout << "Erreur, nature de dessin non prevu" << std::endl;
}
}
void calculer_differences_en_x (cv::Mat &img_niv)
{
CHECK_MAT_TYPE(img_niv, CV_32SC1);
// Remarque : l'image img_niv étant seuillée (valeurs 0 ou 255), le
// résultat sera dans { -255, 0, 255 }.
for (int y = img_niv.rows-1; y > 0; y--)
for (int x = img_niv.cols-1; x > 0; x--)
{
img_niv.at<int>(y,x) = img_niv.at<int>(y,x) - img_niv.at<int>(y,x-1);
}
}
void representer_en_rouge_ou_vert (cv::Mat &img_niv, cv::Mat &img_coul)
{
CHECK_MAT_TYPE(img_niv, CV_32SC1);
CHECK_MAT_TYPE(img_coul, CV_8UC3);
// Palette rouge dans les valeurs négatives, vert dans les valeurs positives
for (int y = 0; y < img_niv.rows; y++)
for (int x = 0; x < img_niv.cols; x++)
{
int g = img_niv.at<int>(y,x);
// Attention img_coul est en B, G, R
if (g >= 0) {
img_coul.at<cv::Vec3b>(y,x)[0] = 0;
img_coul.at<cv::Vec3b>(y,x)[1] = g % 256; // Vert
img_coul.at<cv::Vec3b>(y,x)[2] = 0;
} else {
img_coul.at<cv::Vec3b>(y,x)[0] = 0;
img_coul.at<cv::Vec3b>(y,x)[1] = 0;
img_coul.at<cv::Vec3b>(y,x)[2] = (-g) % 256 ; // Rouge
}
}
}
//----------------------------- I N T E R F A C E -----------------------------
class MonApp : public Astico2D {
public:
// Déclarez ici d'autres membres éventuels
int taille = 20, taille_max = 100;
NatureDessin nature_dessin = D_BLANC;
MonApp (int argc, char **argv) :
Astico2D (argc, argv)
// initialisez ici vos classes membre éventuelles
{
if (!init_ok) return; // erreur dans l'initialisation
// On crée ici un slider "Taille" qui manipulera le membre taille de 0
// à taille_max.
creer_slider ("Taille", &taille, taille_max);
// On affiche les arguments supplémentaires de la ligne de commande
std::cout << "Arguments restant : argc = " << argc;
if (argc > 0) {
std::cout << " argv =";
for (int i = 0; i < argc; i++) std::cout << " " << argv[i];
}
std::cout << std::endl;
}
void afficher_touches_clavier () override
{
// Ceci affiche l'aide de base
Astico2D::afficher_touches_clavier ();
// Indiquez ici les touches du clavier et vos transformations
std::cout <<
" 1 dessine un damier sur l'image seuillee\n"
" tT deplace le slider Taille\n"
" n change la nature du dessin\n"
<< std::endl;
}
bool traiter_touche_clavier (char key) override
{
switch (key) {
// Gérez ici les touches de flags.
case 't' : diminuer_slider ("Taille", 0); break;
case 'T' : augmenter_slider ("Taille", taille_max); break;
case 'n' : {
int suiv = static_cast<int>(nature_dessin)+1;
nature_dessin = static_cast<NatureDessin>(suiv);
if (nature_dessin == D_LAST) nature_dessin = D_BLANC;
std::cout << "Nature dessin : "
<< nom_dessins[static_cast<int>(nature_dessin)] << std::endl;
break;
}
// Rajoutez ici les touches pour effectuer_transformations.
case '1' :
// On mémorise la touche pressée
touche_transfo = key;
// On précise le mode : M_NIVEAUX ou M_COULEURS
mode_transfo = M_COULEURS;
break;
case '2' :
touche_transfo = key;
mode_transfo = M_NIVEAUX;
break;
default : return false; // touche non traitée
}
return true; // touche traitée
}
void effectuer_transformations () override
{
// Appelez ici vos transformations selon touche_transfo et mode_transfo :
// - si mode_transfo est M_NIVEAUX, l'image d'entrée est l'image seuillée
// img_niv, de type CV_32SC1 ; à la fin, pour l'affichage, il faut la
// convertir en couleur dans img_coul, de type CV_8UC3, par exemple avec
// representer_en_couleurs_vga.
// - si mode_transfo est M_COULEURS, travaillez directement sur img_coul,
// de type CV_8UC3, elle sera affichée telle quelle.
switch (touche_transfo) {
case '1' : // M_COULEURS
dessiner_damier (img_coul, taille, nature_dessin);
break;
case '2' : // M_NIVEAUX
calculer_differences_en_x (img_niv);
representer_en_rouge_ou_vert (img_niv, img_coul);
break;
}
}
};
//---------------------------------- M A I N ----------------------------------
int main (int argc, char **argv)
{
MonApp app (argc, argv);
return app.run ();
}