Documente Academic
Documente Profesional
Documente Cultură
Procesarea Imaginii
2016
Cuprins
1.
2.
3.
4.
5.
Cerina proiectului .
Considerente teoretice
Proiectarea programului
Rularea programului .
Cod surs
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
3
5
10
12
6. Bibliografie
.
.
.
7. Mod de utilizare a aplicaiei .
8. Anex .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
17
18
19
1 Cerina proiectului
2
2 Considerente teoretice
Perimetrul
Perimetrul unei regiuni pentru o imagine binar este alctuit din mulimea pixelilor care aparin
obiectului i au cel puin un vecin care aparine fondului.
Aceti pixeli se contorizeaz, iar valoarea rezultat poate fi folosit ca perimetru. Exist dou
variante de calcul n funcie de tipul conectrii, tetra-conectare sau octo-conectare.
Lum exemplul perimetrului unei regiuni circulare negre pe fond alb cu diametrul de 17 pixeli
(fig 1).
n cazul tetra-conectrii,
alctuit numai din pixeli tetra(fig 2) se obine 64.
n cazul octo-conectrii, perimetrul unei regiuni este alctuit numai din pixeli octo-conectai.
Pentru exemplu (fig 3) se obine 54.
Problema care apare la msurarea perimetrului este aceea c pixelii considerai reprezint de fapt
o arie i nu o distan liniar.
n acest caz trebuie introdus observaia legat de modul n care un pixel este traversat de linia
perimetrului.
Cazul cel mai simplu este acela n care linia perimetrului traverseaz un pixel P dup o direcie
vertical sau orizontal. Aportul unui astfel de pixel la calcularea perimetrului este 1.
n alte situaii linia perimetrului traverseaz un pixel dup o direcie diagonal. De aceast dat
contribuia acestui pixel este dat de diagonala ptratului
2 .
n alte cazuri linia perimetrului traverseaz pixelul considerat dup o direcie orizontal/vertical
i o direcie diagonal. n acest caz contribuia acestui pixel este
1
2 +
2
2
Cu aceste observaii, pentru determinarea perimetrului unei regiuni se parcurg urmtorii pai:
4
1. Se identific i se separ pixelii care alctuiesc conturul regiunii pentru care urmeaz s
calculm perimetrul.
2. Se testeaz fiecare pixel al perimetrului pentru a determina ponderea cu care va participa
la calculul perimetrului.
3. n final se nsumeaz toate aceste contribuii individuale ale pixelilor i valoarea obinut
este o valoare aproximativ a perimetrului.
3 Proiectarea programului
Pentru implementarea programului s-au folosit urmatoarele funcii:
void citire_imagine() citete informaia din fiierul text n care se afl matricea imaginii
void afisare()
afieaz imaginea
int findSeed()
Pentru a determina coordonatele pixelului seed se execut urmtorii pai: parcurgem matricea
imaginii, cnd se determina primul pixel cu valoarea 1 cutarea se oprete i se reine poziia
pixelului. Funcia returneaz valoarea 0 dac nu mai exist regiuni noi.
int findSeed()
{
5
int x=0;
int p;
for( i=1;i<=n;i++)
{
for( j=1;j<=m;j++)
{
p = imag[i][j];
if(p == 1)
{
iSeed=i;
jSeed=j;
x++;
break;
}
}
if(p == 1)
break;
}
return x; // daca x=0 atunci nu mai exista regiuni noi
}
Pentru a marca regiunea pentru care vom calcula perimetrul, folosim funcia mark4 care va
marca cu valoarea val toi pixelii din regiunea pentru care urmeaz s calculm perimetrul,
ncepnd de la pixelul de coordonate [iseed][jseed].
void mark4(int c, int iseed, int jseed)
{
if(imag[iseed - 1][jseed] == 1)
{
imag[iseed - 1][jseed] = c;
mark4(c, iseed - 1, jseed);
}
if(imag[iseed][jseed + 1] == 1)
{
imag[iseed][jseed + 1] = c;
mark4(c, iseed, jseed + 1);
}
if(imag[iseed + 1][jseed] == 1)
{
imag[iseed + 1][jseed] = c;
mark4(c, iseed + 1, jseed);
6
}
if(imag[iseed][jseed - 1] == 1)
{
imag[iseed][jseed - 1] = c;
mark4(c, iseed, jseed - 1);
}
}
Pentru a marca pixelii regiunii care nu fac parte din linia perimetrului i care sunt tetra-conectai
vom folosi funcia nay4. Aceasta verific pixelii tetra-conectai cu pixelul de coordonate [i][j] i
va returna numrul vecinilor. Dac numrul este 4, adic sunt 4 pixeli tetra-conectai, nseamn
ca pixelul nu face parte din linia perimetrului i l marcheaz pentru tergere.
int nay4(int i,int j)
{
if(imag[i-1][j] != 0)
nr++;
if(imag[i][j+1] != 0)
nr++;
if(imag[i+1][j] != 0)
nr++;
if(imag[i][j-1] != 0)
nr++;
return nr;
}
Pentru a marca pixelii regiunii care nu fac parte din linia perimetrului i care sunt octo-conectai
vom folosi funcia nay4. Aceasta verific pixelii octo-conectai cu pixelul de coordonate [i][j] i
va returna numrul vecinilor. Dac numrul este 8, adic sunt 8 pixeli octo-conectai, nseamn
ca pixelul nu face parte din linia perimetrului i l marcheaz pentru tergere.
int nay8(int i,int j)
{
int nr=0;
if(imag[i-1][j] != 0)
nr++;
if(imag[i][j+1] != 0)
nr++;
if(imag[i+1][j] != 0)
nr++;
7
if(imag[i][j-1] != 0)
nr++;
if(imag[i-1][j-1] != 0)
nr++;
if(imag[i-1][j+1] != 0)
nr++;
if(imag[i+1][j+1] != 0)
nr++;
if(imag[i+1][j-1] != 0)
nr++;
return nr;
}
Pentru a calcula perimetrul regiunii folosim funcia perimeter(int reg). n cazul n care avem o
regiune tetra-conectat, folosind funcia nay4 vom marca pixelii care nu fac parte din linia
perimetrului i i vom terge. Se testeaz fiecare pixel al perimetrului pentru a determina
ponderea cu care va participa la calculul perimetrului, n funcie de tipul vecinilor pixelului. n
final se nsumeaz toate aceste contribuii individuale ale pixelilor i valoarea obinut este o
valoare aproximativ a perimetrului
float perimeter(int reg)
{
for( i=1;i<=n;i++)
for( j=1;j<=m;j++)
if(imag[i][j]==reg)
if(nay8(i,j)==8) //nu apartine conturului
imag[i][j]=1; // marcam cu val 1 pentru a vedea pixelii care nu fac parte din perimetru
printf("\n Linia perimetrului = 2, interiorul cercului =1");
afisare();
for( i=1;i<=n;i++)
for( j=1;j<=m;j++)
if(imag[i][j]== 1)
imag[i][j]=0; // se sterg pixelii care nu apartin liniei perimetrului
printf("\n Pixelii care nu apartineau liniei perimetrului au fost stersi");
afisare();
float suma;
suma = 0.0;
for( i=1;i<=n;i++)
for( j=1;j<=m;j++)
{
int vo=0; //vecini verticala-orizontala
8
4 Rularea programului
Pentru a arta cum funcioneaz procedura perimeter vom lua exemplul discului cu D=17 i
regiune octo-conectat. Citirea se va face din fiierul cerc.txt. Coninutul acestui fiier este:
9
19 19
0000000000000000000
0000000111110000000
0000011111111100000
0001111111111111000
0001111111111111000
0011111111111111100
0011111111111111100
0111111111111111110
0111111111111111110
0111111111111111110
0111111111111111110
0111111111111111110
0011111111111111100
0011111111111111100
0001111111111111000
0001111111111111000
0000011111111100000
0000000111110000000
0000000000000000000
Pentru aceast imagine se va calcula perimetrul, folosind procedurile prezentate mai sus.
n momentul n care selectm Run programul va afia regiunea pentru care calculm perimetrul
(fig. 4),regiunea marcat cu valoarea 2 (fig. 5) i linia perimetrului pentru care s-a calculat
perimetrul (fig. 6), n acest exemplu fiind o regiune tetra-conectat.
10
11
5 Codul surs
#include<process.h>
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
FILE *f; //fisierul in care pastram imaginea binara
int n,m; //dimensiunile imaginii
int imag[25][25]; //matricea imaginii
int iSeed,jSeed; // coordonatele pixelului Seed
int markval; // valoarea cu care se marcheaza pixelii regiunii
int reg; // regiunea pentru care trebuie sa calculam perimetrul
int i,j,opt,val;
void citire_imagine()
{
if((f = fopen("cerc.txt","r"))==NULL)
printf("\n Fisierul nu a fost deschis!");
fscanf(f,"%d",&n);
fscanf(f,"%d",&m);
for( i=1;i<=n;i++)
for( j=1;j<=m;j++)
fscanf(f,"%d",&imag[i][j]);
fclose(f);
}
void afisare()
{
printf("\n");
for( i=1;i<=n;i++)
{
for( j=1;j<=m;j++)
printf("%d ", imag[i][j]);
printf("\n");
}
}
// functia determina primul pixel al regiunii
int findSeed()
{
12
int x=0;
int p;
for( i=1;i<=n;i++)
{
for( j=1;j<=m;j++)
{
p = imag[i][j];
if(p == 1)
{
iSeed=i;
jSeed=j;
x++;
break;
}
}
if(p == 1)
break;
}
return x; // daca x=0 atunci nu mai exista regiuni noi
}
//marcheaza regiunea cu val c
void mark4(int c, int iseed, int jseed)
{
if(imag[iseed - 1][jseed] == 1)
{
imag[iseed - 1][jseed] = c;
mark4(c, iseed - 1, jseed);
}
if(imag[iseed][jseed + 1] == 1)
{
imag[iseed][jseed + 1] = c;
mark4(c, iseed, jseed + 1);
}
if(imag[iseed + 1][jseed] == 1)
{
imag[iseed + 1][jseed] = c;
mark4(c, iseed + 1, jseed);
}
if(imag[iseed][jseed - 1] == 1)
{
imag[iseed][jseed - 1] = c;
13
void main()
{clrscr();
citire_imagine();
printf("\n Matricea pentru care calculam perimetrul este:\n\n");
afisare();
int copie;
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
copie = imag[i][j];
if (copie == 1)
{
iSeed = i;
jSeed = j;
break;
}
}
if (copie == 1)
break;
}
printf("\n\n\n Regiunea a fost marcata cu valoarea 2");
mark4(2,iSeed,jSeed);
afisare();
float p;
p = perimeter(2);
printf("\n\nPerimetrul regiunii este: %2.f", p);
getch();
8 Anex
17
18