Actualizări:
Scopul temei:
Procesarea de imagini se refera la aplicarea unor algoritmi specifici pe continutul unei imagini pentru a obtine anumite efecte (blur, sharpening, etc.) sau rezultate (face detection/recognition, etc.). In aceasta tema vom lucra cu unul dintre cele mai simple formate de imagini si anume formatul BMP.
O imagine BMP are următoarea structură:
Header-ele pe care le puteți folosi în implementare se află în scheletul de cod asociat temei.
Veti avea de rezolvat 5 task-uri obligatorii si un task bonus.
input
din checker.
Se va implementa un parser al liniei de comandă pentru a putea lucra interactiv cu transformările descrise în cerințele de mai jos și pentru a putea vedea la fiecare pas output-ul rezultat. Programul scris va citi în continuu de la standard input și va putea primi următoarele comenzi.
Pentru acest task vom implementa primele doua operatii de baza necesare unui editor de imagini:
Input: edit poza1.bmp
Input: save ./output/poza_editata.bmp
Va crea fisierul poza_editata.bmp in folderul output(existent).
output
├── poza_editata.bmp
Veti deschide fisierele bmp cu ajutorul functiei fopen utilizand modul de access “rb”. Pentru fisierul de output veti utiliza modul de access “wb”.
fwrite si fread au antetul functiei similare.
size_t fread(void *restrict ptr, size_t size, size_t nmemb, FILE *restrict stream);
size_t fwrite(const void *restrict ptr, size_t size, size_t nmemb, FILE *restrict stream);
Ambele functii intorc numarul de elemente citite, respectiv scrise.
Pentru acest task vom implementa următoarele doua operații:
Ele reprezinta coordonatele punctului stanga-jos, in matricea imaginii din edit mode, de la care se va introduce noua imagine.
dim 1024 × 768
In cazul y si x - coordonata y reprezinta pozitia de pe linia si x linia din matrice.
Pentru acest task vom implementa următoarele cinci operații:
x are valori impare intre 1 si 255, valoarea default este 1
Exemplu:
Pentru line_width = 3, pixelul principal este cel de culoare verde. La desenare, atat pixelul principal, cat si pixelii ce formeaza patratul(si interiorul lui) vor primi culoarea setata.
(y - yA) / (yB - yA) = (x - xA) / (xB - xA).
Se stabileste pe ce axa se afla intervalul maxim (x max - x min) sau (y max - y min).
Se va parcurge de la minim la maxim intervalul de lungime maxima [x min, x max] sau [y min, y max] si pe baza formulei calculate PE INTREGI se afla a doua coordonata a punctului desenat.
Pentru punctele (1, 1) si (2, 5), intervalul mai mare este cel de pe axa Oy.
Deci formula prin care vom afla x-ul corespunzator fiecarui y din intervalul [1, 5] este x = (y + 3) / 4.
y = 1 → x = 1
y = 2 → x = 1
y = 3 → x = 1
y = 4 → x = 1
y = 5 → x = 2
Pentru a evita erorile de rotunjire, punctele initiale primite ca parametru se vor desena indiferent de rezultatul functiei.
Daca intervalele sunt egale, atunci dreapta rezultata este de forma f(x) = x + C sau f(x) = -x + C, unde nu conteaza modul in care va fi desenata linia.
Pentru acest task vom implementa operația finală:
În urma operației, pixelul de la pozitia (y, x) va fi suprascris cu pixeli setati prin comanda set draw_color R G B. Operația va fi repetată recursiv pentru toți vecinii acestuia (stânga, dreapta, sus, jos) care aveau aceeași culoare cu pixelul original din (y, x).
Dacă pixelul original avea tot culoarea (r, g, b), operația nu produce nici un efect.
Exemplu
Imaginea Originală:
(0, 0, 255) (10, 10, 10) (255, 0, 0) (10, 10, 10) (10, 10, 10) (0, 255, 0) (10, 10, 10) (10, 10, 10) (10, 10, 10) (10, 10, 10) (10, 10, 10) (10, 15, 10)
Instrucțiunea:
set draw_color 42 42 42 fill_color 1 2
În urma aplicării operației, toți vecinii accesibili din poziția (1, 2), având culoarea (10, 10, 10), au fost suprascriși cu un pixel de valoarea (42, 42, 42). Pixelul de pe poziția (0, 1) a rămas neschimbat.
Imaginea Obținută:
(0, 0, 255) (10, 10, 10) (255, 0, 0) (42, 42, 42) (42, 42, 42) (0, 255, 0) (42, 42, 42) (42, 42, 42) (42, 42, 42) (42, 42, 42) (42, 42, 42) (10, 15, 10)
Intrucat unul din scopurile principale ale acestei teme este alocarea dinamica a memoriei, pentru a rezolva acest task trebuie sa nu aveti nicio eroare sau leak de memorie la rularea utilitarului valgrind pe aceasta.
Utilitarul se va rula folosind urmatoarea comanda:
valgrind --tool=memcheck --leak-check=full --error-exitcode=1 ./bmp < input_file
make build
trebuie sa fie neaparat bmp!
Resursele pentru tema se pot descarca:
Tema va fi trimisa folosind vmchecker, cursul Programarea Calculatoarelor, tema image_processing.
Punctajul:
Lista nu este exhaustivă. Se pot aplica chiar depunctări mai mari în cazuri excepționale.