Sistem Informatic de Recunoastere a Imaginilor In Baza Indicilor de Momente Geometrice

TEZA DE LICENȚĂ

Sistem informatic de recunoaștere a imaginilor în baza indicilor de momente geometrice

CUPRINS

SARCINA

ADNOTARE

АДНОТАЦИЯ

ADNOTATION

LISTA ABREVIERILOR

INTRODUCERE

1. ANALIZA METODELOR INVARIANTE DE RECUNOAȘTERE A IMAGINILOR

1.1. Eficiența metodelor invariante bazată pe clasificare de textură Gabor wavelets

1.2. Recunoașterea și evaluarea momentelor invariante

1.2.1. Momente invariante folosind integralele de linie

1.2.2. Parametru optimizat filtre Gabor

1.3. Recunoasterea formelor invariant folosind ridgelets, wavelet ciclu-spinning

1.3.1. Transformarea ridgelet

1.3.2. Normalizarea de traducere și scară

1.3.3. Wavelet ciclu-filare

1.4. Recunoașterea obiectelor invariante folosind clustere EDGE

1.4.1. Transformarea DT CWT și funcții ICP

1.4.2. Construirea unui model în baza indicilor de momente geometrice

1.5. Concluzii la capitolul 1

2. ELABORAREA SISTEMULUI INFORMAȚIONAL DE RECUNOAȘTERE A IMAGINILOR ÎN BAZA INDICILOR DE MOMENTE GEOMETRICE

2.1. Tehnologiile utilizate pentru a dezvoltat de sistem informatic de recunoaștere a imaginilor în baza indicilor de moment geometrice

2.2. Particularitățile program în C++ Builder

2.3. Restricții de securitate pentru program

2.4. Ciclul de viață al unui program C++ Builder

2.5. Obiect Orientat C++ Builder

2.6. Proiectarea sistemului de recunoaștere a indicilor de moment geometrici

2.7. Forma generală a instrucțiunilor condiționale if, else, else if

2.8. Crearea cîmpurilor și ariilor de text

2.9. Crearea Componentei ComboBox și ScrollPane

2.10. Crearea firelor de execuție

2.11. Utilizarea componentei Label

2.12. Citirea și scriere unui obiect într-un fișier

2.13. Concluzii la capitolul 2

3.DESCRIEREA SISTEMULUI

3.1. Ghidulutilizatorului

3.2. Ghidul programatorului

3.2.1. Interfața de lucru a platformei C++ Builder

3.2.2.Crearea unui proiect cu ajutorul tehnologiilor C

3.2.3. Modul de grupare a claselor C++ sub formă de pachete

3.2.4.Adăugarea unei clase noi în program

3.3. Concluzii la capitolul 3

CONCLUZII GENERALE ȘI RECOMANDĂRI

BIBLIOGRAFIE

ANEXA 1. Codul sursă a programului.

DECLARAȚIA PRIVIND ASUMAREA RĂSPUNDERII

CURRICULUM VITAE

DATE PRIVIND CONTROLUL TEHNIC AL TEZEI

LISTA ABREVIERILOR

INTRODUCERE

Momentele au un spectru larg de aplicații în analiza imaginilor, inclusiv recunoașterea formelor, clasificarea obiectelor, estimarea pozițiilor. În general, un set de momente calculat pentru o imagine digitală reprezintă caracteristicile globale ale unei imagini și oferă o multitudine de informații cu privire la diferite tipuri de caracteristici geometrice ale acestei imagini. Capacitatea de momente de imagine pentru a reprezenta caracteristici vizuale a fost folosit pe larg în computer vision și robotică. Ca o consecință a acestui progres în procesare a imaginii, au fost introduse numeroase noi tipuri de momente, fiecare dintre acestea având propriile avantaje. Considerând o imagine ca o distribuție de distribuție bi-dimensional, momente de imagine, într-un mod similar, pot asigura informații despre zona de imagine, orientare imagine și despre coordonatele centroid. Aceste caracteristici pot fi utilizate după la construirea unui vector de caracteristici vizuale care sunt invariante la deplasările cauzate de traduceri, rotații și scalarea.

Actualitatea și importanța: În ultima perioadă este un mare pas de a extinde sectorul de robotică și anume de recunoaștere a imaginelor de la calculator.

Cu toate acestea realizatorii au creat un produs cu un nivel foarte ridicat, reducînd considerabil utilizatorii, permițînd utilizarea doar de care persoanele care au cunostințe în domeniu ci nu de către orice persoană care nu a fost intruit în folosirea soft-ului.

Scopul și obiectivele tezei: În această teză noi vom elabora un program in mediu C++, care ne va permite recunoașterea figurilor geometrice din imagine. Acest program are scopul de a fi cît mai simplu pentru a permite să fie utilizat nu numai de către persoanele din domeniu, ci și de către persoanele simple, adica oamenii din diverse domenii de activitate nespecializate în această sferă.

Această lucrare prezintă o aplicație ce constă într-o recunoaștere de figuri geometrice, construit utilizînd tehnologia C++. Acest program permite:

Să utilizăm careva setări la recunoaștere.

Arie unde să introducem imaginea.

Butoane pentru a genera, salva, deschide, șterge și a ieși.

Spațiu pentru a vizualiza produsul generat.

Noutatea științifico – practică a rezultatelor obținute: Prin crearea a unui astfel de sistem, noi vom analiza și trece prin toate fazele elaborării unui sistem, ceea ce ne va permite în viitor să recunoaștem obiecte cu ajutorul calculatorului. Folosirea tehnologiei C++ ne oferă mari benificii în atingerea scopurilor propuse. În teza dată noi facem analiza tehnologie C++ pentru elaborarea unui sistem, proiectăm și elaborăm un sistem ce va recunoaște figuri geometrice din imagini, simplu de utilizat.

Sumarul compartimentelor tezei:

În această teză sunt incluse 3 capitole:

Primul capitol cuprinde teorie și toate informațiile elementare privind recunoașterea imaginilor invariante, argumente și formule de bază care contribuie la crearea noastră bazându puțin și pe treptele altor cercetători. Se plătește o mare atenție la toate teoremele de dezvoltare, în scopul de a înțelege pas cu pas fenomenul de creare a propriei noastre moale folosind teoremele anterioare. În plus față de aceasta, se face o comparație detaliată cu alte sisteme de punerea în evidență totul despre recunoasterea invariant.

Al doilea capitol prezintă partea practică despre modul în care a fost elaborat sistemul de recunoaștere a imaginilor invariante geometrice. Acest capitol explică întrebarea principală de cercetare a tezei. Aici este descris în detaliu modul în care a fost elaborat în C++ și este clarificată de ce tocmai această tehnologie a fost aleasă.

Capitolul trei conține documentația totale si caracteristicile propriei noastre moale. Acest capitol, de asemenea, vine cu capturi de ecran care demonstrează fiecare din funcțiile sale și codul sursă care ajută la realizarea operațiunilor necesare.

Fiecare capitol se încheie cu concluzii referitoare la capitolul dat.

Importanța teoretică și valoarea aplicativă a lucrării: Datorită sistemului vom obține o recunoaștere a figurilor geometrice din imagini.

ANALIZA METODELOR INVARIANTE DE RECUNOAȘTERE A IMAGINILOR

1.1. Eficiența metodelor invariante bazată pe clasificare de textură Gabor wavelets

Gabor wavelets, ale cărei boabe de sunt similare cu răspunsul bidimensionale profilurile teren receptive ale expoziției mamifere simplu de celule corticale caracteristicile dorite de capturare proprietăți vizuale importante, cum ar fi localizarea spațială, selectivitate orientare și frecvență spațială. În domeniul spațial, un Gabor wavelets este o exponențială complex modulat printr-o funcție Gauss, care este definit după cum urmează:

, (1.1)

unde denotă poziția pixel domeniul spațial, ω este frecvența centrală radială, este orientarea al Gabor wavelets, și este deviația standard a funcției gaussiană a lungul și , unde se presupune. Valoarea poate fi derivat după cum urmează:

, (1.2)

unde și este de lățime de bandă în octave. Prin selectarea diferitelor frecvențe centrale și orientări, putem obține o familie de miezuri Gabor din (1.1), care pot fi utilizate pentru a reprezenta o imagine [1]. Gabor filtre cu diferite frecvențe centru și orientări sunt prezentate în Fig. 1.1.

Fig. 1.1. Filtre Gabor: (a) părțile reale ale Gabor filtre la cinci frecvențe diferite centre și opt orientări. Frecvențele sunt , , , și din partea de sus a rândul de jos, respectiv. Orientările sunt de 0 la în pași de , de la stânga la coloana din dreapta, respectiv. (b) mărimi ale Gabor filtre la cinci frecvențele centrale diferite corespunzătoare.

Având în vedere o imagine de nivel de gri , convoluția de și se acordă astfel:

(1.3)

unde asterisc denotă operatorul de convoluție. Concatenarea ieșirile convoluție, putem obține o reprezentare Gabor unidimensional din imaginea de intrare,

, (1.4)

unde T reprezintă operația transpune, și sunt lățimea și înălțimea imaginii, respectiv. În această lucrare, considerăm doar magnitudinea reprezentările Gabor, care poate oferi o măsură a proprietăților locale ale unei imagini (pentru comoditate, am, de asemenea, o nota ca [2]. Apoi acestea Gabor are, cu diferite și , sunt concatenate pentru a forma un vector-dimensională ridicată caracteristică, dupa cum urmeaza:

, (1.5)

unde m și n sunt numărul de frecvențe centru și orientări utilizate, respectiv.

1.2. Recunoașterea și evaluarea momentelor invariante

1.2.1. Momente invariante folosind integralele de linie

Un vector este o cantitate care include atât mărime și direcție, cum ar fi forța, viteza, deplasare si accelerare. In vectorul algebră, doi vectori A si B sunt egale, dacă doi vectori au aceeași direcție și magnitudine indiferent de poziția punctelor lor inițiale (A = B). Integralelor obișnuite de vectori pot fi definite prin

, (1.6)

unde sunt intervale specificate și u este un singur variabile scalare. Ecuația. (1.7) reprezintă o parte integrantă nedeterminată

. (1.8)

Pentru unde este vectorul de poziție al și definește o curbă care unește punctele C și , unde , și respectiv [8]. Să presupunem că C este echilibrat de un număr finit de curbe. Pentru fiecare dintre poziția curbei sale, vector are un derivat continuu. Lasă o funcție vector definit pentru poziția. Este continuă de-a lungul C. Linia integrantă F de-a lungul C de la pentru este definit ca

, (1.9)

În plan 2D, o forță poate fi definită printr-un vector a cărui magnitudine este puterea de forța și direcția este calea prin care forța este împinsă. Fig. 1.2. arată că forța este de la stânga la dreapta, un obiect se deplasează sub controlul de forță și propunerea este reprezentat de vectorul (S). Cu toate acestea, forța nu este una constantă, la diferite puncte forța poate vârf în direcții diferite, cu putere. În conformitate cu aceste studii de bază, o proiecție a unei funcții 2D este un set de integrale de linie, de la care datele pot fi produse prin radiind din surse unice și multiple [9]. Aceste două surse sunt utilizate pentru a estima unghiul de rotație a obiectelor.

Fig. 1.2. Reprezentarea forță și mișcare în integralele de linie.

O rotație 2D este aplicat unui obiect prin repoziționarea-a lungul unui traseu circular. Un unghi de rotație și punctul de pivotare despre care obiectul ce trebuie rotit sunt specificate pentru generarea rotație. In ceasornic, valorile unghiurilor pozitive sunt folosite pentru a se roti în jurul punctului pivot și în contrast orar rotație necesită valori unghi negativ.Transformarea rotație este de asemenea descrisă ca o rotație în jurul unei axe care este perpendiculară xy avion și trece prin punctul pivot. Ecuațiile de transformare rotație sunt determinate de poziția la poziția printr-un unghi (B) în raport cu originea de coordonate.Deplasarea inițială a punctului de axa x este (A) [9]. Acest lucru este ilustrat în Fig.1.3.

Fig. 1.3. Rotație de LP în sens antiorar cu unghiuri duble (A, B).

Rotația poate fi obținut ca

, .

, .

și , (1.10)

, (1.11)

, (1.12)

Cu elementele de bază ale transformare rotație și de linie integrale, putem introduce coordonatele nou eșantionare raze x’ și y’ și Jacobian (J) este descris ca

. (1.13)

Proiecția fasciculului ventilator cu integrală Radon este definit ca

, (1.14)

unde este densitatea la punctul cu coordonate polare în regiune, în timp ce este distanța perpendiculară dintre raza și acest punct [10].

1.2.2. Parametru optimizat filtre Gabor

În literatura de specialitate actuală filtre Gabor și selecții de funcții respective ste puterea de forța și direcția este calea prin care forța este împinsă. Fig. 1.2. arată că forța este de la stânga la dreapta, un obiect se deplasează sub controlul de forță și propunerea este reprezentat de vectorul (S). Cu toate acestea, forța nu este una constantă, la diferite puncte forța poate vârf în direcții diferite, cu putere. În conformitate cu aceste studii de bază, o proiecție a unei funcții 2D este un set de integrale de linie, de la care datele pot fi produse prin radiind din surse unice și multiple [9]. Aceste două surse sunt utilizate pentru a estima unghiul de rotație a obiectelor.

Fig. 1.2. Reprezentarea forță și mișcare în integralele de linie.

O rotație 2D este aplicat unui obiect prin repoziționarea-a lungul unui traseu circular. Un unghi de rotație și punctul de pivotare despre care obiectul ce trebuie rotit sunt specificate pentru generarea rotație. In ceasornic, valorile unghiurilor pozitive sunt folosite pentru a se roti în jurul punctului pivot și în contrast orar rotație necesită valori unghi negativ.Transformarea rotație este de asemenea descrisă ca o rotație în jurul unei axe care este perpendiculară xy avion și trece prin punctul pivot. Ecuațiile de transformare rotație sunt determinate de poziția la poziția printr-un unghi (B) în raport cu originea de coordonate.Deplasarea inițială a punctului de axa x este (A) [9]. Acest lucru este ilustrat în Fig.1.3.

Fig. 1.3. Rotație de LP în sens antiorar cu unghiuri duble (A, B).

Rotația poate fi obținut ca

, .

, .

și , (1.10)

, (1.11)

, (1.12)

Cu elementele de bază ale transformare rotație și de linie integrale, putem introduce coordonatele nou eșantionare raze x’ și y’ și Jacobian (J) este descris ca

. (1.13)

Proiecția fasciculului ventilator cu integrală Radon este definit ca

, (1.14)

unde este densitatea la punctul cu coordonate polare în regiune, în timp ce este distanța perpendiculară dintre raza și acest punct [10].

1.2.2. Parametru optimizat filtre Gabor

În literatura de specialitate actuală filtre Gabor și selecții de funcții respective au fost realizate în mod incercare si eroare. Aceste tehnici sunt fie potrivite pentru o problemă simplă orientate sau ales de parametri de filtrare într-un mod independent de date. Filtrele Gabor au fost calculate pentru selecția caracteristică în două metode diferite unul este numit filtru bancar și altul este abordare de design filtru. În fostele metodele [14] [15], parametrii sunt alese într-un mod improvizat, dar nu a oferit o soluție optimă pentru o anumită sarcină. O altă problemă cu aceste filtre este redundanța convolutions, care cere mai multe operațiuni în extracția caracteristica. Un set câteva filtre sunt concepute pentru a clasifica modelele prezentate eficient folosind abordare de design filtru care oferă un set optim de filtre Gabor și reduce complexitatea de calcul decât cea fostul. În [16], evolutiv Gabor metode de optimizare de filtrare a fost propus pentru procesul de detectare vehiculului pe șosea. În acest algoritm genetic cromozomi bazate au fost utilizate împreună cu abordări clustering incrementale pentru a găsi parametrii optimi de filtre Gabor. Problema recunoașterii olografe au fost efectuate cu ajutorul filtrelor Gabor optimizate [17].

Aceste metode au folosit un răspuns optim de metode de suprafață și o baltă de filtre predefinite cu rate minime de eroare operate pentru procesul de selecție caracteristică. Am folosit o combinație de mașini Boltzmann cu K-mijloace de clustering pentru alegerea celor mai bune valori legate de frecvență, de orientare și la scară parametrii de filtre Gabor. Inițial, masina Boltzmann cu procesul de recoacere produce set optim de parametri Gabor. Apoi, K-mijloace de abordare clustering este folosit pentru a grupa răspunsul redundant de filtre generate în optimizarea. În cele din urmă, în funcție de rezultatul de proiectare clasificator, filtre optime sunt colectate pentru un anumit domeniu de aplicare.

Abordarea optimizare globală este efectuat pentru a optimiza parametrii de filtre Gabor. Selecția filtru este un alt proces esențial pentru a colecta fel similar de parametri de filtrare împreună, în scopul de a colecta ca un singur grup. Acest lucru se realizează prin luarea valorii medii a parametrilor, care oferă același tip de răspunsuri. Astfel, algoritmul propus simțurile sa scoateti filtrele redundante, reduce operațiunile de convoluție inutile și de a crește eficiența extracției facilitate cu o mulțime compactă de filtre. 1-D Gabor transformare a fost inițiat de Gabor și a fost extins la 2D de Daugman [18]. O funcție 2D Gabor este o discordant sinusoidal orientată modulat de funcția Gauss 2D [19]. Aceasta este descris ca

, (1.15)

, (1.16)

unde este Gaussian cu parametrii parametru de scară (), acești parametri determină mărimea efectivă a funcționării vecinătate a unui pixel în care convoluția greutății se efectuează, f este frecvența centrală care este un grilaj sinusoidală limitată deschideri. θ specifică orientarea normală la benzile paralele ale unei funcții Gabor. Valoarea sa este specificată în grade de la 0 ^ ∘ la 〖360〗 ^ ∘. Cu toate acestea, θ este considerat în între 0 grade și 180 de grade, deoarece simetrie face cealaltă orientare redundant. În orientarea aplicație specific poate fi calculat as unde radian = 180 grade, 1 radian = și n reprezintă numărul de orientări menținute în sistem. Filtrul Gabor face funcția de prim rang complex și este compus în părți reale și imaginare ca:

, (1.17)

, (1.18)

1.3. Recunoasterea formelor invariant folosind ridgelets, wavelet ciclu-spinning

1.3.1. Transformarea ridgelet

După cum știm, ridgelets au fost dezvoltate recent pentru aplicații de procesare a imaginii [1–8]. Pentru fiecare , fiecare și fiecare , ridgelet bivariate: : este definit ca

. (1.19)

Un ridgelet este constantă de-a lungul liniilor . Transversing la aceste culmi este o wavelet. Având o imagine bivariate integrabilă , putem defini coeficienții de ridgelet ca

, (1.20)

unde Este funcția wavelet. Fig. 1.3 arată funcția ridgelet original și cele care sunt scalate, schimbat, și rotit, respecti Vely [21].

Ridgelet transformare poate fi reprezentată în termeni de Radon transformare.Radon transforma dintr-o imagine este definit ca

, (1.21)

unde este distribuția Dirac. Așa ridgelet transforme e exact aplicarea unei 1D wavelet transforme pentru felii de Radon transformă unde unghiulare variable este constantă și t variază. Ridgelets sunt diferite de wavelets în sensul că ridgelets prezintă sensibilitate direcțională foarte mare și sunt foarte anizotrope.

Fig. 1.4. Ridgelets-urile utilizate de Candes.

Un ridgelet transformare rapidă poate fi realizată în domeniul Fourier. În primul rând 2D FFT este calculat. Apoi este interpolate de-a lungul unui număr de linii drepte egal cu numărul selectat de proiecții. Fiecare linie trece prin centrul spațiului frecvență 2D, cu o pantă egală unghiul de proiecție, precum și un număr de puncte de interpolare egal cu numărul de raze per proiecție. După FFT inversă 1D de-a lungul fiecare ray interpolate ajungem ridgelet coeficienți de transformare [22].

1.3.2. Normalizarea de traducere și scară

În această secțiune, vom analiza unele dintre tehnicile de normalizare mai frecvent utilizate pentru a elimina traducere și varianța scară. Pentru a realiza invarianta traducere, putem folosi momente regulate ale unei imagini. Reamintim că momentele regulate sunt definite ca

. (1.22)

Invarianta traducere poate fi realizată prin transformarea imaginii, astfel încât primele sale momente de ordinul, m01 și m10, sunt ambele egale cu zero. Lasă și fi locația centrului de greutate al imaginii originale, atunci ., , prin urmare, putem transforma imaginea pentru .

Există trei metode utilizate în mod obișnuit pentru a atinge scara invarianta. În primul rând, se poate realiza prin scalarea imaginii astfel încât momentul de ordine zero m00 este egală cu o valoare predeterminată [23]. De calcul, putem alege factorul de scalare .

Astfel, invarianță scară se realizează prin transformarea funcția originală a imaginii într-o nouă funcție , cu . În al doilea rând, putem realiza invarianță scară prin stabilirea , mai lungă distanță de la până la un punct pe modelul. Această metodă, ho Wever, este rar utilizat în mediu zgomotos, deoarece este foarte sensibil la zgomot.A treia metodă este de a normaliza imaginea astfel încât raza medie de imagine pixelii sunt un sfert a dimensiunii grilei de intrare; adică, avem

, . (1.23)

Pe scurt, o funcție imagine pot fi normalizate pentru a fi la scară și invariant de traducere prin transformarea acesteia în , cu fiind centrul de greutate al și un factor de scalare adecvat a. Când nu corespunde într-o locație de rețea, putem interpola de valorile celor patru apropiate locații de rețea din jurul ei.

1.3.3. Wavelet ciclu-filare

Tabelul ciclu-filare, de asemenea, numit-traducere invariant (TI) de masă, este de scalar discret wavelet transforma și multiwavelet transforma [24]. Tabelul ciclul filare a unui semnal este un matrix Swith . Fiecare i rând de matricea este partiționat în blocuri. Aceste blocuri conțin toți coeficienții wavelet la scara i pentru diferite schimburi. Aceasta matrice este umplut dinamic în timpul fiecare scală rezoluție.Completarea în a tabelului ciclului de filare sunt îndeplinite de o serie de operațiuni de decimare și de filtrare. Lăsa g și h suport pentru obișnuite down-eșantionare pasa mare și operațiunile trece jos a teoriei wavelet. De asemenea suport pentru schimbare circular de h. Set , semnalul 1D, și inițializa

, , (1.24)

, .

apoi, ecuațiile recursive urma

, , (1.25)

, ,

for j = 1, …, J – 1 and k = 0, 1, …, 2j – 1 – 1.

Fig. 1.5. ilustrează modul în care putem potrivi caracteristicile modelului necunoscut masa caracteristica ciclu-filare în baza de date caracteristica [25]. După cum știm, masa ciclu filare wavelet conțin coeficienții wavelet de un semnal pentru toate schimbările. Deci, este spectrul Fourier al wavelet coeficienților sub-bandă. Pentru un semnal de schimbare dat, putem efectua 1D wavelet transforma și a obține spectrul Fourier . Deoarece spectrul Fourier este simetrică, păstrăm doar jumătate din coeficienților [26]. Acest lucru se poate face timp de procesare mai rapidă. Pentru a calcula distanța dintre caracteristicile spectrale ale modelului necunoscută și masa ciclu-filare a bazei de date model, vom lua distanța dintre normă și fiecare pentru în rândul lea i al tabelului ciclu spinning. Dacă ne reprezintă fiecare sub-banda wavelet ca un nod, atunci putem indica masa ciclu filare wavelet ca un copac. Fiecare nod din arborele are doi copii, cu excepția frunzele. Distanța întregului copac pot fi evaluate de jos în sus. Pentru fiecare nod, luăm distanța minimă de doi copii și adăugați-l la distanta de nodul părinte. În cele din urmă la rădăcină, ne distanța dintre modelul necunoscut și masa ciclu-spinning wavelet [27].

Fig. 1.5. Wavelet masă Ciclul-filare și arborele în calcul distanța dintre modelul necunoscută și date modelul.

1.4. Recunoașterea obiectelor invariante folosind clustere EDGE

1.4.1. Transformarea DT CWT și funcții ICP

În această secțiune, vom rezuma ILP și ICP funcțiile, care transformă ambele imagini țintă și de căutare în domeniul în care vom efectua potrivire. Vom începe cu o imagine de ansamblu asupra CWT DT pe care se bazează funcțiile ILP și ICP.

Wavelet Complex Dual-copac Transformarea (DT CWT) transformă o imagine N * M într-o piramidă de niveluri L, în cazul în care fiecare nivel l = 1L conține coeficienții interlevel complexe.Magnitudinea unui coeficient reprezintă puterea activității în vecinătatea locației sale spațiale (x, y), scară l, și orientare d, unde d = 1. . . 6 reprezintă sub-benzi direcționale aproximativ egale între 15 și 165. Faza coeficienților CWT DT schimba liniar cu offset de o caracteristică de locația coeficient.

Rețineți că comportamentul coeficienților CWT DT sunt similare cu coeficienți piramidale orientabile [28]; cu toate acestea, DT CWT pot fi implementate cu liniar separabile băncile filtru wavelet, oferind viteze îmbunătățite de calcul. Cu toate acestea, această accelerare vine în detrimentul de a pierde "manevrabilitatea"; sunt fixate numărul și direcțiile sub-benzile.

Fig. 1.6. Relația dintre faza complexă a unui coeficient ILP în 15° sub-bandă și natura unei ~15° caracteristică în vecinătatea.

Comparativ cu Discrete Wavelet Transform, DT CWT are două proprietăți dorite potrivite pentru recunoașterea obiectelor: invarianta schimbare moderată și selectivitate mai bună direcție. Cu toate acestea, în timp ce mărimile coeficienților wavelet complexe furniza informatii valoroase pentru recunoașterea obiectelor, fazele în stare brută sunt mai puțin utile. Dacă imaginea este deplasată ușor, comparativ cu referința decimare, modificări de fază vor fi introduse care fac potrivite dificilă. Ar fi util, în schimb, în cazul în care faze ale coeficienților au fost mai direct dependente numai conținutul imaginii. În secțiunea următoare, vom vedea cum funcționează ICP și ILP crea aceste dependențe [29].

Uitandu-se la diferența de fază între un coeficient DT CWT W(x, y, l, d) și o versiune a dublat fază a mamă scalate-grosier W(x, y, l +1, d), se poate vedea că relațiile compensa faze liniare anuleze pentru a produce o diferență de fază, care este relativ constant, indiferent de funcția spațială offset. Ca urmare, această diferență de fază este legată numai de natura multiscale caracteristica prezent la locul dat; această relație este prezentată în Fig.1.6. Un coeficient de ILP, χ(x, y, l, d), creează această diferență de fază prin înmulțirea coeficientului copil cu conjugatul mamă; mai multe detalii ale acestui proces pot fi găsite în [1]. În mod specific, faza ILP reprezinta tipul de fază congruență între componente, chiar și impare Fourier o octavă în afară. Ca un exemplu, un real pozitiv 2D ILP (L χ = 0)1 corespunde congruența de sinus pozitive coeficienții (nui adevărat) Fourier, care formează o muchie pozitiv pas în această pereche de scară; În mod similar, un imaginar ILP negativ (L χ = 270) indica congruență de cosinus negativ (chiar) coeficienții Fourier. În [30][31], Kovesi descrie relația dintre componente Fourier și coeficienții wavelet complexe în detaliu (folosind complex wavelet log-Gabor).

1.4.2. Construirea unui model în baza indicilor de momente geometrice

Începem prin transformarea T de imagine țintă cu funcțiile ILP și ICP pentru a produce piramida χ(T) și ψ(T) respectiv coeficienții, și izolarea regiunilor în care credem că fazele coeficientul va fi stabilă.

Observații empirice ale coeficienților ILP indică faptul că margine și crestelor obiecte de interes apar în cazul în care coeficienții ILP, în cadrul aceleiași sub-bandă, posedă următoarele calități:

1. Magnitudine mare, indicând că activitatea este prezent;

2. Adiacenta spațială a unui număr de coeficienți cu aproximativ aceeași fază complex (coeficienții "coerente" ILP), ceea ce înseamnă că aceeași caracteristică, dominant influenteaza toate coeficienți. În aceste condiții relația dintre faza ILP și conținut imagine este stabil; că este, este invariant la relativ mici transformări afine de conținut, cum ar fi pot apărea cu rotatie sau de traducere. Pentru a pune în aplicare din urmă criteriile și muchiile, prin urmare, în mod eficient separate de texturi, vom crea mai întâi un nou set de coeficienți R(x, y, l, d) la fiecare sub-bandă și nivel care cere fază similitudine între coeficienți vecine, cum dictată de cerința 2 de mai sus:

(1.26)

unde ) și β este un prag care controlează strictețea cu care se poate impune coerență de fază; vom folosi o valoare de β = 0.8. Coeficienții R care rezultă sunt fie o medie de patru coeficienților ILP învecinate, cazul în care acestea posedă de fază similară. Regiunile în care R este zero (de exemplu, cu coeficienți ILP inconsistente) corespund pentru a netezi sau regiuni imagini texturate.

Avem acum clustere corespunzătoare vizual importante și consistente caracteristicile margine / crestelor într-o imagine țintă. Mai precis, vom defini o "Edge-Profile Cluster" c să fie un grup de coeficienți coerente ILP care reprezintă în mod eficient o muchie sau o creasta cu cinci parametri: centrul său (µc), dimensiune / formă (Σc), orientare (), greutate (αc), și profilul de margine ().

1.5. Concluzii capitolul 1

Acest capitol cuprinde o analiză profundă a întregului set de surse de informare pe tema "Sistem informatic de recunoaștere a imaginilor în baza indicilor de momente geometrice". O atenție mare a fost acordată teoremele de evoluție și de descrierea fiecărui pas care are menirea de a ne ajuta pentru a crea un nou moale. În special, o prezentare a modului de imagini invariante recunoaștere a fost definit și a fost proprietățile momente invariante cu avantaje principale și dezavantaje au fost prezentate.

Pot concluziona că recunoașterea imaginilor invariante poate fi mai eficient și mai exact decât în cazul în care sunt combinate, de exemplu – rotație cu scalare, translație cu rotație sau translație cu scalare.

2. ELABORAREA SISTEMULUI INFORMAȚIONAL DE RECUNOAȘTERE A IMAGINILOR ÎN BAZA INDICILOR DE MOMENTE GEOMETRICE

2.1. Tehnologiile utilizate pentru a dezvoltat de sistem informatic de recunoaștere a imaginilor invariante

C++ Builder este un mediu (o unealtă) care ajută la dezvoltarea de aplicații proprii în limbajul C++ putându-se crea astfel ușor aplicații cu interfață pentru sistemul de operare WINDOWS. Pentru a putea crea o aplicație windows trebuie creat prima dată un proiect. Proiectele sunt colecții de fișiere sursă (cpp) care sunt compilate pe rând și din care este realizat un singur fișier executabil. De aceea în cadrul unui proiect trebuie să existe o singură funcție main (sau WinMain pentru windows). Pentru crearea unei aplicații pentru windows cu interfață în C++ Builder se intră în meniul ”File-> New->Application”. Se va crea automat o aplicație care conține o fereastră (în c++ Builder se numește FORM) goală perfect funcțională. Pentru a putea fi rulată această aplicație trebuie în prealabil să fie salvată. Pentru salvarea întregului proiect se folosește comanda „File->Save Project As”. Pentru un proiect nou se recomandă prima dată salvarea întregului proiect. La execuția acestei comenzi se cere prima dată calea și un nume pentru un fișier cu extensia cpp (Unit1.cpp). Acest fișier conține codul scris deja pentru forma noastră. Se va specifica un nume pentru acest fișier și se va selecta exact calea unde se dorește salvat proiectul (Pentru această temă recomand numele „Prima.cpp”). În folderul specificat vor fi salvate 2 fișiere cu numele specificat, unul cu extensia .cpp și unul cu extensia .h. După salvarea formei se va cere specificarea numelui proiectului. Pentru salvarea proiectului în folderul specificat vor fi create alte două fișiere unul cu extensia .cpp.

Limbajul de programare C++ a fost inițial derivat din C. Totuși, nu absolut orice program scris în C este valid C++. Deoarece C și C++ au evoluat independent, au apărut, din nefericire, o serie de incompatibilități între cele două limbaje de programare. Cea mai amplă revizie a limbajui C, C99, a creat un număr suplimentar de conflicte. Diferențele fac să fie greu de scris programe și biblioteci care să fie compilate și să ruleze corect în calitate de cod C sau C++, și produce confuzii celor care programează în ambele limbaje. Diferențele fac ca fiecare din cele două limbaje de programare să împrumute din caracteristicile celuilalt limbaj de programare.

Builder IDE este mediul în care se execută programele C++. În prezent, există mai mulți furnizori de IDE, printre care Borland, CodeGear. În 2006, Borland a anunțat că face disponibilă varianta sa de IDE către CodeGear.

Pentru a insera un buton se folosește toolbar-ul de componente în tabul „Standard”. Se face clic pe componenta dorită din toolbar și apoi se face clic pe fereastră în locul unde se dorește inserat butonul. Acesta poate fi modificat și repoziționat prin drag-and-drop. Pentru atașarea unui eveniment de clic pe buton se merge în „Object inspector” și se selectează tabul „Events” (atenție să fie selectat butonul pentru că altfel selectați evenimentele pentru formă). Acolo va apărea o listă cu toate evenimentele care pot fi activate pentru componenta curent selectată. Pe noi ne interesează evenimentul „OnClick”.

Se va face dublu-click în dreptul acestui eveniment în locația goală. Automat C++ Builder va insera o metodă pe care o va atașa de acest eveniment. Deci de câte ori noi vom facem click pe acel buton se va apela automat codul acestei metode (funcții). Urmează ca în această metodă să scriem funcția standard din c++ care ne închide o aplicație. O altă modalitatea de a crea (sau ajunge) la funcția creată pentru evenimentul onClick pe un buton este să facem dublu-click pe butonul respectiv. Rulați aplicația să vedeți dacă și funcționează.

2.2. Particularitățile program în C++ Builder

Programul C++ este o mica aplicație care este scrisă în C++ și livrate la utilizator sub formă de bytecode. Utilizatorul lansează exe dintr-un calculator dupa care se execută în cadrul unui nucleu, care este instalată pe calculatorul utilizatorului. În linii generale cpp sunt subclase ale clasei h, care la rîndul lor sunt incluse într-un fisier de tip exe, dupa care vor fi lansate în execuție imediat la încărcarea totală a programului.

C++ este prezentat uneori ca "asamblor portabil", făcându-se astfel diferențele principale față de limbajele de asamblare: codul unui program C++ poate fi compilat și rulat pe aproape orice tip de mașină (calculator), asemănător altor limbaje de programare, în timp ce limbajele de asamblare sunt specifice unui anumit model de mașină. Limbajul C++ aparține clasei limbajelor de nivel scăzut sau de nivel mediu, aceasta indicând strânsa legătură între interoperabilitate și echipamentul hardware.

Pentru a accesa în cod o anumită proprietate a unei componente trebuie să amintim că aceste componente nu sunt altceva decât obiecte de tipuri mai complexe, deci se accesează ca și un membru dintr-o clasă (structură).

Deși lista minusurilor limbajului C++ este destul de lungă, aceasta nu reprezintă un dezavantaj suficient de mare pentru inhiba utilizarea limbajului C++ în practică, deoarece permite ca noi compilatoare să poată fi scrise pe noi tipuri de platforme și pentru că permite programatorului să țină bine sub control programul pe care îl scrie. Acesta este unul din motivele care face ca un cod scris în C++ să fie mult mai eficient decât dacă ar fi scris în alte limbaje de programare. Numai un cod scris cu foarte mare grijă într-un limbaj de asamblare poate fi mai performant, deoarece are control integral asupra mașinii, dar performanța avansată a compilatoarelor, combinată cu complexitatea noilor tipuri de procesoare, a făcut ca limbajul C++ să fie preferat și să fie acceptat din ce în ce mai mult de programatori.

2.3. Restricții de securitate pentru program

Restricții de securitate applet constă în siguranța ce este menținută atunci când rulează applet-urile pe computerul utilizatorului. C++ utilizează așa -numitul "model de securitate sendbox" pentru executarea applet-urilor pentru a preveni programe distructivede deteriorarea a sistemului pe care browser-ul este pornit. Programele nu au voie să folosească "sandbox" resurse din afară și se limitează la următoarele activități:

Programele nu li se permite să citească, sau scrie în sistemul de fișiere al computerului. În caz contrar, acestea ar putea deteriora fișierele și răspândi viruși.

Programele nu sunt permise pentru a rula programe pe calculator a browser-ului. Altfel, eles-ar putea numi programe locale distructive și deteriora sistemul local de pe utilizator calculator.

Programele nu sunt permise pentru a stabili conexiuni între computerul utilizatorului și oricealt calculator, cu excepția pentru serverul pe care sunt stocate în web servicii, această restricție previne applet-ul de conectare calculatorul utilizatorului la un alt calculator fără cunoștințelor utilizatorului [16].

2.4. Ciclul de viață al unui program C++ Builder

Execuția unui program începe în momentul în care este accesat exe-ul în care este inclus codul sursa al nostru și care trece prin mai multe etape. Fiecare etapă este strîns legată de un eveniment generat de către sistem și determină apelarea unei metode specifice din clasa ce implementează C++. Sistemul controlează și execută programul folosind metodele C++ a ciclului de viață.

Programele sunt de fapt executate din recipientul codului sursa, care este un plug-in într-un sistem. A plug-in este o componentă software care poate fi adăugată într-un software de mare pentru a furniza informații suplimentare și funcții. Clasa programului conține init (), start (), stop (), și distruge () metode, cunoscut sub numele de metodele ciclului de viață. Aceste metode sunt numite de către containerul program de a controla executarea unui sistem. Acestea sunt puse în aplicare cu un corp gol din clasa, astfel încît acestea să nu facă nimic în mod implicit. Le-ai putea trece într-o subclasă pentru a efectua operațiile dorite.

Fig. 2.1 Schema execuției unui applet [elaborat de autor].

Metoda de inițializare init()

Metoda de inițializare este invocată după ce este creat applet-ul. În cazul în care o subclasă a applet-ul are o inițializare pentru a efectua, acesta trebuie să anuleze această metodă. Funcțiile de obicei implementate în această metodă se numără, obținerea valorilor parametrilor șir de tag-ul<class> în pagina HTML [25].

Metoda de pornire start()

Metoda de pornire este invocată după metoda de inițializare. Se mai numește atunci cînd utilizatorul se întoarce la pagina Web care conține applet-ul, după navigarea alte pagini. O subclasă de Applet suprascrie această metodă dacă are orice operație care trebuie efectuată ori de câte ori pagina Web care conține applet-ul este vizitată. Un applet cu animație, de exemplu, s-ar putea porni cronometrul pentru a relua animația.

Metoda de oprire stop()

Metoda de oprire este opusul metodei de pornire (start()). Metoda de start se numește atunci cîndutilizatorul se mută înapoi la pagina care conține applet-ul. Metoda de oprire este invocată atunci cînd utilizatorul părăsește pagina. O subclasă de Applet suprascrie această metodă dacă are orice operație de efectuat în timp cîndpagina Web care conține applet-ul nu mai este vizibilă. Un applet cu animațiede exemplu, s-ar putea opri cronometrul pentru a întrerupe animația.

Metoda de distrugere distroy()

Metoda distruge este invocată atunci cînd browser-ul iese în mod normal pentru a informa applet care nu mai este necesar și ar trebui să elibereze toate resursele care le-a alocat. Metoda de oprire este întotdeauna numită înainte de metoda distruge. O subclasă de Applet suprascrie această metodă dacă are nevoie ca orice operație să se efectueze înainte acesta sa fie distrusă. De obicei, nu veți avea nevoie pentru a trece peste această metodă dacă nu vrei să-i elibereze resursele specifice care applet-ul creat le-a ocupat [15].

2.5. Obiect Orientat C++ Builder

Programarea orientată obiect este fraza de captură de programare în anii 1990. Deși programarea orientată obiect a fost în jur într-o formă sau alta, deoarece limba Simula a fost inventat in anii 1960, este într-adevăr a început să apuce în medii GUI moderne cum ar fi Windows, Motif și Mac. În programele orientate-obiect de date este reprezentat de obiecte. Obiectele au două secțiuni, domenii (variabile exemplu) și a metodelor. Domenii vă spun ce un obiect este. Metode pe care le spun ce face un obiect. Aceste câmpuri și metode sunt strâns legate de caracteristicile reale ale obiectului și comportamentul. Când un program este rulat mesajele sunt transmise înainte și înapoi între obiecte. Când un obiect primește un mesaj răspunde corespunzător astfel cum este definit prin metodele sale.

Fig. 2.2. Una din clasele utilizate în GUI este fereastra.

Programarea orientată obiect se presupune a avea o serie de avantaje, printre care:

• simplu, mai ușor de citit de programe

• reutilizarea mai eficientă a codului

• timp rapid de pe piață

• cod de eroare Mai mult robust

În practică programe orientate obiect au fost la fel de lent, costisitor și buggy ca programele tradiționale orientate non-obiect. În mare parte aceasta se datorează faptului că cel mai popular limbaj orientat-obiect este C++. C++ este un limbaj complex, dificil, care împărtășește toate confuzia mintală C în timp ce schimbul niciuna dintre eficienței C lui. Este posibil, în practică, pentru a scrie ușor de citit cod curat, C++.

2.6. Proiectarea sistemului de recunoaștere a indicilor de moment geometrici

O imagine este o suprafata de obicei dreptunghiulara caracterizata, la nivelul oricarui punct al ei, de o anumita culoare. La modul ideal, culoarea variaza in mod continuu in oricare directie. Din pacate, in sistemele numerice, nu se pot utiliza marimi care variaza continuu ci doar forma discretizata a acestora. Discretizarea este operatia prin care se reprezinta o marime cu variatie continua sub forma unui ansamblu finit de esantioane. De exemplu, temperatura mediului ambiant variaza in mod continuu pe durata unei zile, totusi se poate reprezenta evolutia acestiea prin intermediul valorilor masurate la un interval de un minut. Se poate observa ca pentru a se obtine o captare cit mai fidela a evolutiei temperaturii aceasta trebuie masurata la un interval cit mai scurt posibil. In caz contrar (spre exemplu daca s-ar masura o data pe ora) se pot pierde anumite variatii care au aparut intre doua masuratori si care astfel nu mai pot fi observate.

În concluzie, o imagine trebuie sa fie discretizata inainte de a se pune problema reprezentarii numerice. Discretizarea consta in impartirea imaginii intr-un caroiaj asemanator unei table de sah. Fiecare sectiune de imagine delimitata de acest caroiaj va fi considerata ca avind o culoare uniforma – o medie a culorii existente pe aceasta sectiune. Aceste sectiuni mai sint denumite si pixeli sau puncte, numarul acestora definind rezolutia imaginii. Astfel se poate afirma, de exemplu, ca o imagine oarecare are o rezolutie de 640×480 pixeli ceea ce inseamna ca pe suprafata acesteia s-a definit un caroiaj care o imparte pe orizontala in 640 de sectiuni iar pe verticala in 480. Pasul urmator il constituie gasirea unei reprezentari pentru culoare. Orice culoare poate fi descompusa in trei culori primare (de exemplu rosu-R, verde-G si albastru-B), cu alte cuvinte orice imagine poate fi obtinuta prin suprapunerea aditiva a trei radiatii luminoase avind aceste trei culori si intensitati diferite. Deci, pentru a reprezenta numeric o culoare este suficient sa reprezentam intensitatile luminoase ale celor trei culori primare. Daca alocam cite 8 biti pentru fiecare componenta se pot codifica 256 nivele de intensitate, astfel, absenta culorii (intensitate zero) se codifica prin valoarea 00000000 binar (00h) iar intensitatea maxima prin cea mai mare valoare reprezentabila pe 8 biti si anume 11111111 binar (FFh).

În program incarcam o imagine in format *.BMP pe care o binarizăm și recunoastem figurile geometrice de pe ea. Programul se bazeaza pe o baza de cunoștințe, dupacare și are loc recunoașterea figurilor geometrice. Aplicația este realizată în mediul de programare C++ Builder v.6 ceea cei ofera o eleganță aplicației, o interfață frumoasă și comoda în utilizare.

Programul dispune de o viteză de prelucrare a datelor destul de mare și este capabil să recunoască figurile geometrice din baza de cunoștințe, atît de pe un fon de o singură culoare, cît și de pe fonuri bogat colorate. O condiție importanta pentru funcționarea corectă a programului este faptul figurile geometrice de pe imagine care trebuie să fie recunoscute nu trebuie să fie de culoare neagră sau alba, faptul dat împiedică binarizarea corectă a imaginii, ceea ce duce la nereușirea determinării soluțiilor.

Fig. 2.3. Diagrama de activitate din UML.

2.7. Forma generală a instrucțiunilor condiționale if ,else, else if

Instrucțiunea if cere sistemului să evalueze o expresie (condiție) la o valoare deadevăr. Dacă expresia este adevărată, atunci sunt executate una sau mai multe instrucțiuniaflate în blocul if. Dacă expresia nu este adevărată, instrucțiunile respective sunt omise. Expresia evaluată dintr‐o instrucțiune if se numește expresie condițională. Forma generală:

if (<conditie>)

[<instructiune_adevarat>];

Else această clauză aparține instrucțiunii if și conține una sau mai multe instrucțiuni care suntexecutate atunci când expresia condițională din instrucțiunea if este falsă. Forma generală:

if (<conditie>)

[<instructiune_adevarat>];

[else

[<instructiune_fals>];]

Analizind if și else acum le putem combina obținînd o instrucțiune mult mai complexă și aceasta este forma generală de reprezentare:

if (<conditie_1>)

<instructiune_adevarat_1>;

else if (<conditie_2>)

<instructiune_adevarat_2>;

else

<instructiune_fals>.

2.8. Crearea cîmpurilor și ariilor de text

Un punct destul de imprtant este și citirea textelor în awt ce se realizează prin intermediul cîmpurilor text și al ariilor text. Un cîmp conține o singură linie pe cind o arie text conține mai multe linii. Cîmpurile text sunt definite de clasa TextField., iar ariile text de cătreTextArea. Cele două sunt derivate din clasa TextComponent. Casetă de text este o componentă simplă și folosită în mod frecvent pentru a intra un volum mic (scris într-o singură linie) de date de tip text. Pentru a crea un cîmp de text cel mai frecvent se utilizează următorii constructori:

TextField (int coloane ) – creează o casetă de text gol suficient de larg pentru a se adapta coloanele de caractere. Utilizatorul poate introduce în caseta de text șirul de orice lungime: pur și simplu se va derula.

TextField (text String ) – creează un cîmp de text cu textul textului inițial.

TextField (text String, int coloane ) – se poate seta atît lățimea și textul inițial.

Înserarea textului în metoda poate fi utilizată cu setText (Text String ). Gettext ( ) returnează conținutul casetei de text în întregime, și getText (int offset, int lungime) – lungimea de o bucată de lungime conținut, începînd cu caracter de offset.

O parte din cîmpul de text pot fi alocate (ca în software-ul și interacțiunea cu utilizatorul). Metoda getSelectedText () vă permite să obțineți o porțiune selectată de text. Înlocuirea textului selectat, se poate utiliza o altă metodă de replaceSelection (conținut String). Metode getSelectionStart() și getSelectionEnd() returnează limitele zonei selectate, și metode setSelectionStart (start int) și setSelectionEnd (final int) pentru a le schimba.

Metoda getCaretPosition() returnează poziția cursorului (caret) în caseta de text, și setCaretPosition metoda (poziția int) vă permite să setați programatic. Metoda setCaretColor (culoare de culoare), poate schimba culoarea cursorului [10].

În mod implicit, textul în cîmpul este apăsat la stînga. Acest lucru poate fi schimbat prin setHorizontalAlignment (int align), parametrul este una dintre alinierea constante definite în aceeași clasă TextField: LEFT, CENTER, RIGHT.

TextArea este, de asemenea un descendent al TextField și moștenește toate metodele sale. Spre deosebire de zona de cîmp de text sau de introducere a textului vă permite să introduceți mai mult de o linie. Prin urmare, TextArea oferă mai multe funcții adiționale. În primul rînd, este capacitatea de o folie de cuvînt pe linia următoare de a alege în întregime de către setWrapStyleWord metoda (wrapStyle boolean ). Dacă apelați această metodă cu un parametru true, cuvintele nu se vor rupe în punctul în care " un pas greșit ", la granița de componentei, și va fi transferat în întregime la noua linie. În al doilea rînd, este abilitatea de a încadra textul (de exemplu, linii lungi vor fi instalate în cîteva rînduri în loc de unul, care iese din limitele componentei. Această metodă controlează capacitatea setLineWrap ( lineWrap boolean). Metode isWrapStyleWord ( ) și isLineWrap ( ) le reven starea actuală a capacităților de date ( adevărat – activat și fals – dezactivat) [20, 265p.].

Cînd creați un TextArea folosit cel mai frecvent TextArea constructor (int rînduri, int coloane), stabilește înălțimea (numărul de rânduri) și lățimea (numărul de caractere) a componentei.

Pentru a lucra cu conținutul său TextArea oferă în plus două metode convenabile. Metoda de adaugare (text String ) adaugă un șir de text la sfârșitul unui text existent , și inserția metoda (text String, poziția int) se introduce în poziție.

2.9. Crearea Componentei ComboBox și ScrollPane

ComboBox – o componentă a Builder, care este o lista drop-down. Există două forme ComboBox verticală: editabile și non-editabile. Lista drop-down primul tip vă permite să introduceți valoarea dorită în caseta de text sau selectați din lista interesati, dacă există. Atunci când se lucrează cu un utilizator al doilea tip ComboBox poate selecta doar dintr-o listă drop-down. ComboBox ia forma de mai puțin spațiu în comparație cu alte componente, permite de a alege din mai multe variante. De exemplu, grupul de radio sau lista List cu 10 elemente ia mult mai mult spațiu decât ComboBox. Să vedem cum se poate de a crea o listă ComboBox verticală, umple-l cu datele necesare pentru a adăuga la formular, iar apoi utilizatorul selectează un element din listă.

În primul rând, creăm un simplu ComboBox și îl umplem cu date. Acest lucru poate fi realizat după cum urmează:

În primul rînd, se creează un tablou cu elemente pe care dorim să le vedem în viitor lista drop-down, și apoi trece o trimitere la matrice în constructorul ComboBox deja creat[17, 187p.].

După cum sa menționat mai sus, există două tipuri de ComboBox – editabile și non-editabile. În mod implicit, casetă combo non-editabile. În scopul de a face editabil, trebuie să apelați cu ajutorul la setEditable(true) ca un parametru.

Lista verticală ComboBox a fost creată. Acum, trebuie să fie capabil de a efectua anumite acțiuni atunci când utilizatorul selectează un element din listă. Acest lucru se poate realiza folosind actionlistener. În primul rînd vom crea ascultatorul – sau clasa anonim, sau un alt exemplu de realizare a ActionListener interfață. Apoi se adaugă un ascultător folosind metoda addActionListener [27, 160p.].

Mai jos este pregătit special un exemplu decrearea evenimentelor la acțiunea mouse-ului în interiorul ariei Combobox:

ActionListener actionListener = new ActionListener() { // declararea acțiunii

public void actionPerformed(ActionEvent e) { //metoda de tratare a acțiunii

public void actionPerformed(ActionEvent e) { //metoda de tratare a acțiunii

/*

* Acțiunea de care avem nevoie

*/}};

comboBox.addActionListener(actionListener); //introducerea ariei de acțiune

Pentru componentele de grup împreună le-a pus pe un Panel – Container, unde puteți seta aspectul, fundal, și granițele. Puteți folosi, de asemenea, un Panel pentru grafică, dar atunci îl puteți utiliza, de asemenea, ca un container component. Există și alte recipiente specializate, care acționează mai mult ca componente, de exemplu, ScrollPane. După ce ați adăugat componente de la un panou, a stabilit panou de conținut al containerului de nivel superior la acest panou cu myApplet.setContentPane (conținut). La toate aceste ComboBox vedem că au și cîte un ScrollPane ce ne permite să vedem și mai jos în lista noastră de opțiuni. Componenta ScrollPane poate fi utilizată asupra unei surse de date care poate fi, o imagine, un document text, o tabela. Aceste șiruri de date reprezintă componenta din a carei suprafața se va vizualiza doar o anumită regiune la un moment dat, cu posibilitatea de derulare.

Pentru aceasta operație ScrooPane pune la dispozitie două bare de derularet SscrolBar respectiv un container Viewport care reprezintă zona prim care se vizualizează componenta conținut, care poartă denumirea de privește (eng. view) p care poate fi obtinută printr-un apel get(Viewport). Pentru a obține o referință sau pentru a seta această componentă din care doar o porțiune este vizualizată la un moment dat, putem folosi metodele getView) respectiv setview.

2.10. Crearea firelor de execuție

Builder este în mod inerent multi-threaded. Un singur program de C++ poate avea mai multe fire de diferite de executare în mod independent și continuu. Trei C++ program de pe aceeași pagină poate rula împreună cu fiecare dată egala obtinerea de CPU cu foarte puțin efort suplimentar din partea programatorului.

Acest lucru face ca C++ foarte receptivi la introduse de utilizator. De asemenea, ajută să contribuie la soliditatea Java și oferă un mecanism prin mediu C++ poate asigura că un applet rău intenționat nu fura toate ciclurile procesorului gazdei.

Din păcate, multithreading este atât de strâns integrat cu C++, care o face C destul de greu de portul de arhitecturi precum Windows 3.1 sau PowerMac care nu suportă nativ preventiv multi-threading.

Există un cost asociat cu multi-threading. Multi-threading este C ++ ce pointer aritmetic este C, care este, o sursă de diabolic greu de găsit bug-uri. Cu toate acestea, în programe simple este posibil sa plece multi-threading singur și în mod normal să fie OK.

Avantajul de a folosi doar un singur fir să se ocupe de mai multe canale este că aveți nevoie mai puține fire să se ocupe canalele. De fapt, aveți posibilitatea să utilizați doar un fir să se ocupe de toate canalele. Comutarea între fire este scump pentru un sistem de operare, și fiecare fir are niște resurse (memorie) în sistemul de operare prea. Prin urmare, mai puțin firele pe care le utilizați, cu atât mai bine.

C++ definește o clasă fir și o interfață Runnable care poate fi folosit pentru a defini un obiect fir. Uitați-vă la exemplul de bază subiect care derivă din clasa Subiect. Se creează două fire care afișează mesaje asincron.

Acest lucru se întâmplă de obicei, atunci când rulează pe un calculator rapid sau folosind Just-In-Time (JIT). Motivul pentru aceasta este faptul că unul dintre firele de probă poate chiar finisare imprimarea tuturor mesajelor înainte de a fi programată pentru preemptiune. Incearca sa faci firele dura mai mult pentru a termina prin creșterea MAX_INDEX la 100 (sau mai mult) și a vedea ce se întâmplă.

Țineți minte însă, că sistemele de operare moderne și de CPU deveni mai bun și mai bine la multitasking, astfel încât cheltuielile de multithreading devine mai mică în timp. De fapt, dacă un procesor are mai multe nuclee, ați putea fi pierde puterea procesorului de nu multitasking. Oricum, faptul că discuția de design aparține într-un text diferit. Este suficient să spunem aici, pe care le pot ocupa mai multe canale, cu un singur fir, folosind un selector.

In fig. 3.4 este o ilustrare a unui fir folosind un selector să se ocupe de 3 Channel.

Fig. 3.4. Un fir utilizează un selector pentru a gestiona 3 Channel in C ++.

C++ nu are o fază legătură explicită. Codul sursă C++ este împărțit în fișiere .cpp, aproximativ unul pentru fiecare clasă în programul tău. Compilatorul compilează acestea în fișiere .class conțin byte code. Fiecare fișier .cpp produce, în general, cu exact un fișier .class. Există câteva excepții, vom discuta mai târziu în semestrul, clasele non-publice și clase interioare.

Compilatorul cauta directorul curent și directoarele specificate în variabila de mediu CLASSPATH pentru a găsi alte clase referire în mod explicit de nume în fiecare fișier de cod sursă. Dacă fișierul pe care îl compilați depinde alte fișiere, care nu compilate compilatorul va încerca să le găsească și să le compilați, de asemenea. Compilatorul este destul de inteligent, și se poate ocupa dependențele circulare, precum și metode care sunt folosite înainte de a fi declarate. De asemenea, se poate determina dacă un fișier de cod sursă sa schimbat de la ultima dată când a fost compilat.

Mai important, clase care au fost necunoscute un program de când a fost compilat pot fi încărcate în ea în timpul rulării. De exemplu, un browser web poate încărca applet de diferite clase care niciodată nu a văzut înainte, fără recompilare.

În plus, fișierele C ++ .class tind să fie destul de mici, câteva kilobytes cel mult. Nu este necesar pentru a lega în biblioteci mari de rulare pentru a produce un executabil (non-native). În schimb clasele necesare sunt încărcate din CLASSPATH utilizatorului.

2.11. Utilizarea componentei Label

Label este, probabil, componenta cea mai simplă care o are un program. Folosind Label poate fi afișatun text într-o pictogramă. Dacă orice componentă a avut nevoie pentru a afișa un mesaj sau de a face o pictogramă de introducere a textului eticheta de cîmp sau un eveniment – folosi Label. Textul care îl arată Label nu poate fi selectat, el poate fi doar privit[22, 153p.].

Pentru cerare obiectului Label, care peurmă va fi pus într-o fereastră, poate fi folosit cu constructorul public Lable(String text). Parametru este text, care va fi afișat în Lable. Label vă permite să personalizați fontul care va fi folosit pentru a afișa text. Setarea de font se face de către Label metoda setfont. Această metodă ca un parametru transferat Font. Ceea ce ne dorim, atunci când vom specifica sau crea fontul? Primul – marca, Verdana sau Courier New, sau ambele. Cea de a doua – a treia și dimensiunea fontului – fontul este bold sau normal, sau poate fi cursiv. Prin urmare, constructorul adecvat pentru Font este unul care conține toate cele trei parametri la o dată – Font publice (String nume, stil int, int size). Primul parametru, așa cum este deja clar că numele fontului. Dacă nu este specificat, este folosit fontul implicit. Al doilea parametru stabilește stilul – bold, italic sau normal. Aici trebuie să treacă una dintre constantele obiect Font – Font.BOLD (bold), Font.PLAIN (normale sau plate) și Font.ITALIC (sublinierea). Și a treia opțiune – dimensiunea fontului. Obiect font poate fi creat ca în exemplu următor:Font font = new Font("Verdana", Font.PLAIN, 11);

După instalarea fontului și textul în Label uneori este necesar pentru a determina alinierea textului pe verticală și pe orizontală. Acest lucru se face cu ajutorul a două metode și setVerticalAlignment setHorizontalAlignment respectiv [9, 109p.].

Un obiect Label poate afișa fie text, o imagine, sau ambele. Puteți specifica zona de afișare a etichetei conținutul, etichetei sunt aliniate prin setarea alinierea pe verticală și orizontală. În mod implicit, etichetele sunt centrate vertical în zona lor de afișare. Doar text etichete sunt de vîrf aliniate, în mod implicit; doar-imagine etichetele sunt centrate pe orizontală, tot în mod implicit.

Ca parametri pentru setVerticalAlignment trebui să folosească ceva din urmatoarea lista : Label.TOP ( aliniate în partea de sus ), Label.CENTER ( centru ) și Label.BOTTOM (aliniază marginea de jos). Pentru mai multe parametrilor metodei setHorizontalAlignment – Label.LEFT (marginea din stânga), Label.CENTER (în mijloc), Label.RIGHT (dreapta – justificate), Label.LEADING și Label.TRAILING. Pentru limbile care scriu merge de la stânga la Label.LEADING textului de la dreapta – aceasta este marginea din stînga, și Label.TRAILING – dreapta. Pentru limbi al căror scris de la dreapta la stînga, Label.LEADING – aceasta este marginea din dreapta, și Label.TRAILING – stînga.

Label poate afișa o pictogramă, împreună cu textul. Pentru a instala pictogramele folosim metoda setIcon. Singurul parametru de metoda este Icon. Atunci cînd se administrează o pictogramă pentru Label, puteți specifica locația de text în raport cu icoana. În acest scop, metode și setVerticalTextPosition setHorizontalTextPosition. Parametrii utilizați sunt aceleași ca constantele alinierea textului [21, 164p.].

Acum, avem nevoie pentru a determina ce culoare textul este Label nostru. Acest lucru se face cu ajutorul setForeground metoda. Aici aveți nevoie pentru a trece la Color. Pentru a crea o culoare poate utiliza diferite designeri sau locul folosi constantele definite în Color obiect. Există o Color.BLACK negru, Color.GREEN verde, roșu Color.RED și altele. Dacă doriți să creați un fel de o anumită culoare, trebuie să utilizați proiectantul. Pentru mine, Culoare publică mai convenabil (int red , int verde, int albastru ). Trece culorile componente necesare aici și de a lua ceea ce au vrut. Ei bine, apoi setați culoarea în Label.Exemplu:

label.setForeground(Color.GREEN);

2.12. Citirea și scriere unui obiect într-un fișier

Într‐un program real, multe din elementele de date pe care vreți să le stocați într‐un fișier sunt date membre ale unei clase. Multe atribute ale unei clase sunt stocate în variabile de instanță. O variabilă de instanțăn reprezintă o locație de memorie folosită pentru stocarea datelor specifice unei instanțe a clasei [23, 221p.].

Să presupunem că în definiția clasei sunt definite două variabile de instanță și sunt create cinci obiecte ale clasei. C++ rezervă cinci seturi de variabile de instanță, independente unul față de celălalt. Totuși, fiecare dintre cele cinci obiecte folosește același set de metode – cele asociate clasei.

Atunci cînd se dorește păstrarea instanței unei clase, aceasta se salvează într‐un fișier. Când seface acest lucru, în fișier sunt salvate numai variabilele de instanță, nu și metodele clasei.

Etapele scrierii și citirii unui obiect în/din fișier.

Trebuie implementată interfața Serializable în clasa a cărei obiecte urmează să-l scrieți în fișier. Interfața Serializable permite ca instanțele clasei respective să fi transformate într‐un flux de octeți care poate fi scris pe disc sau trimis pe rețea. Această operație se numește serializare. La citirea obiectului, fluxul de octeți este deserializat șieste reconstituită instanța clasei.

Crearea unei instanțe a clasei și atribuirea valorii variabilelor de instanță. Apoi sedeschide fișierul apelând constructorul clasei FileOutputStream, căruia i se transmitenumele fișierului. Operatorul new returnează o referință a unui obiectFileOutputStream. Această referință este transmisă constructorului claseiObjectOutputStream, care definește metodele folosite pentru scrierea unui obiectîntr‐un fișier.

După crearea unei instanțe ObjectOutputStream se scrie un obiect în fișier. Pentruacest lucru se apelează metoda writeObject() și se transmite o referință a obiectuluidorit a fi scris în fișier. Variabilele statice ale obiectului nu sunt salvate. Ultimul pasconstă în apelarea metodei close(), pentru a închide fișierul [7, 203p.].

Citirea unui obiect dintr‐un fișier este la fel de simplă ca și scrierea unui obiect într‐un fișier. Totuși, în locul clasei ObjectOutputStream se folosește clasa ObjectInputStream, iar înlocul clasei FileOutputStream se folosește clasa FileInputStream. Se citește un obiect dinfișier apelând metoda readObject(), definită în clasa ObjectInputStream. MetodareadObject() returnează o referință de tip Object. Această referință trebuie convertită latipul specific al clasei obiectului citit. Obiectul returnat de metoda readObject() este apoiatribuit unei referințe a obiectului respectiv și este folosit ca orice alt obiect din program.

2.13. Concluzii la capitolul 2

În acest capitol am descris partea practică a cercetării mele și mai ales am integrat algoritmul de recunoaștere a imaginilor invariante explicat în al doilea capitol al acestei teze. Softul a fost elaborat folosind mediu C++ Builder și C++ ca un limbaj de programare . Cel mai mare avantaj al acestui limbaj de programare a este simplitatea de descrierea și citirea codului și care constituie un sistem dinamic. Acest soft ruleaza pe Windows.

De asemenea, acest capitol cuprinde toate detaliile elaborarea pas cu pas și este completat de capturi de ecran, teste, avantaje și dezavantaje.

3. DESCRIEREA SISTEMULUI

3.1. Ghidul utilizatorului

Ghidul utilizatorului, este cunoscut de asemenea ca un manual, un document tehnic de comunicare destinat să ofere asistență persoanelor care folosesc un anumit sistem. Acesta este, de obicei scrisă de un scriitor tehnic, deși ghiduri sunt scrise de programatori sau manageri de proiect.

Ghiduri de utilizare sunt cel mai frecvent asociate cu produse electronice, hardware și software. Cele mai multe ghiduri de utilizare conțin atât un ghid scris și imaginile asociate. În cazul aplicațiilor informatice, este de obicei pentru a include imagini ale interfeței om-mașină, și manuale de hardware de multe ori includ diagrame clare, simplificate. Limbajul folosit este potrivit pentru publicul vizat, cu jargon menținute la un nivel minim sau explicat în detaliu.

Fig. 3.1. Forma de bază a aplicației. [elaborat de autor]

Pentru a încărca o imagine este nevoie de a tasta pe butonul „Încarcă” și se va deschide fereastra de dialog unde selectăm prin explorer imaginea care dorim să o încărcăm în sistemul nostru.

Fig. 3.2. Încărcarea imaginei în sistem. [elaborat de autor]

După încărcarea imaginei, automat apare in fereastra de baza a sistemului nostru, si putem începe să facem careva teste asupra acestei imagini. Avem posibilitate de a seta careva date pentru o recunoastere mai eficientă, și anume arie minima, arie maximă, culoare.

Fig. 3.3. Setări pentru recunoașterea eficientă. [elaborat de autor]

Următorul pas care o să-l facem este să tastăm butonul „Binarizează”, asta înseamnă că se va trece din imagină în cod binar pentru a trece la următoarea parte și anume de recunoaștere.

Fig. 3.4. Trece imaginei din imagine în cod binar. [elaborat de autor]

Și în final pentru a recunoaște imaginea vom tasta butonul „Recunoaște” unde vom obține asupra fiecărei figuri geometrice numele figurii care o reprezintă.

Fig. 3.5. Recunoașterea imaginei din sistem. [elaborat de autor]

După ce am obținut rezultatele imaginei recunoscute, avem posibilitatea de a utilize setările din figura 3.3 și să vedem ce rezultate am obținut. Pentru a ieși din program vom tasta „Iesire Program”. Astfel vom utiliza acest program în recunoașterea imaginelor.

3.2. Ghidul programatorului

Borland C++ Builder este o platformă multi‐scop pentru dezvoltarea de software, scrisă, în mare parte, înlimbajul C++, astfel putând rula pe orice sistem de operare actual. Oferă un mediu integrat dedezvoltare (IDE – Integrated Development Environment) pentru diverse limbaje de programare (C sau C++). Platforma C++ Builder se încadrează în categoria programelor cu licență. Printre facilitățile platformei C++ Builder merită a fi menționate:

crearea și gestiunea de proiecte;

debuging;

completarea automată a codului (code completion);

automatizări pentru operații des utilizate (redenumire, creare de set‐ere și get‐ere, completarea automată a secțiunii de import).

Toate programele C++ prezentate în continuare sunt dezvoltate folosind nucleul sistemului de operare și rulează pe sistem de operare Windows. Versiunile platformei C++ Builder, începând cu versiunea 3.2, și ultima versiune este 6.0. Însă ulterior a fost preluat de către CodeGear și îl dezvoltă mai departe.

3.2.1. Interfața de lucru a platformei C++ Builder

La pornirea mediului C++ Builder este afișat un panel cu componentele necesare pentru realizarea unei aplicații. Aici se vor salva proiectele și vor fi stocate datele necesare rulării proiectelor.

Fig. 3.6. Selecția spațiului de lucru. [elaborat de autor]

Dacă se utilizează același spațiu de lucru pentru toate proiectele, se poate bifa căsuța devalidare Use this as the default and do not ask again, pentru a elimina această întrebare lafiecare pornire a platformei. Ferestrele vizibile din interfața C++ Builder sunt grupate logic în perspective. O perspectivă indică numărul de ferestre vizibile, poziția lor și opțiunile vizibile în acesteferestre, în funcție de limbajul utilizat în proiectul deschis. În capturile de ecran prezentate înacest îndrumar se va folosi perspectiva C++. Perspectiva curentă se poate schimba de la butoanele dedicate situate în partea dreaptă‐sus a workbench‐ului Builder C++.

3.2.2. Crearea unui proiect cu ajutorul tehnologiilor C++

Din meniul File → New se alege opțiunea Application.

Fig. 3.7. Crearea unui proiect C++ în C++ Builder. [elaborat de autor]

În fereastra care se deschide trebuie specificat numele proiectului. Este indicat să fie selectată opțiunea Create separate folders for sources and class files din secțiunea Project layout, pentru a nu amesteca fișierele ce conțin codul sursă cu cele ce conțin codul de octeți, executabil. Pentru un proiect complet nou este bine să se aleagă opțiunea Create new project in workspacea secțiunii Contents. Apăsarea butonului Next va determina accederea la mai multe opțiuni, cum ar fi importul unor librării suplimentare, modificarea directoarelor unde vor fi salva tesursele și codul de octeți al proiectului, etc. Crearea și deschiderea în workbench a noului proiect se realizează prin apăsarea butonului Finish [4, 56p.].

3.2.3. Modul de grupare a claselor C++ sub formă de pachete

De multe ori, atunci cînd avem o șansă de a lucra la un proiect mic, un lucru ne-am propus să facem este de a pune toate fișierele java într-un singur director. Este rapid, ușor și inofensiv. Cu toate acestea, dacă proiectul nostru mic devine mai mare, iar numărul de dosare este în creștere, punînd toate aceste fișiere în același director ar fi un coșmar pentru noi. În C++ putem evita acest gen de probleme prin utilizarea de pachete.

Clasele unui proiect C++ sunt grupate, de regulă, în pachete. Criteriile de grupare țin de funcțiile pe care le îndeplinesc acele clase în proiect (lucrul cu fișiere, accesul la baze de date, comunicația prin rețea, etc.). De asemenea, pachetele asigură și controlul numelor și alvizibilității. Fizic un pachet este un director al proiectului [1, 62p.].

Pachetele C++ ajută, de asemenea, pentru a evita numele clasei coliziune atunci cînd vom folosi același nume de clasă ca și cea a altora. De exemplu, dacă avem un nume de clasa numita "Vector", numele său s-ar asemăna cu clasa Vector din sistem. Cu toate acestea, nu se întîmplă acest lucru, deoarece sistemul folosește cpp ca un nume de pachet pentru clasa Vector. Deci, clasa noastră Vector poate fi numit ca "Vector", sau putem să-l punem într-un alt pachet. Beneficiile de a utiliza pachetul reflectă ușurința de întreținere, de organizare, și de a crește colaborarea în rîndul dezvoltatorilor. Înțelegerea conceptului de pachet va ajuta, de asemenea, de a gestiona și utiliza în moduri mai eficiente fișierele stocate în fișiere exe.

Pachetul C++ este un mecanism de organizare a claselor C++ într-un spațiu de nume de module similare în limbajul de programare modulație. Pachetele C++ pot fi păstrate într-o formă comprimată în fișiere exe. De obicei pachete de clase combinate din aceeași categorie sau cu funcții similare. Fiecare pachet oferă un spațiu de nume unic pentru conținutul său. Pachete imbricate valide [13, 84p.].

Accesul la clasele dintr‐un pachet se face prin utilizarea instrucțiunii import la începutul codului sursă. Instrucțiunea import trebuie să conțină numele pachetelor și ale claselor carevor fi folosite în codul sursă. Crearea unui pachet în C++ Builder se realizează prin clic dreapta pe numele proiectului, iar din meniul care apare se alege New → Package. În fereastra ce se deschide se specifică numele noului pachetului, după care se apasă butonul Finish.

Un pachet poate conține alte pachete, care, la rândul lor, pot conține alte pachete. În cazulacesta se efectuează clic pe numele pachetului în care se face adăugarea, după care se parcurge aceleași etape prezentate mai sus.

3.2.4. Adăugarea unei clase noi în program

Clasele aparțin pachetelor, prin urmare adăugarea se va face prin click dreapta pe numele pachetului, se selectează New→Class. În fereastra care se deschide se completează numele clasei și se selectează opțiunile pentru aceasta. O clasă nu este altceva decât un model sau un șablon pentru a crea diferite obiecte care definește proprietățile și comportamentele sale. Obiecte de clasa C++ expune proprietățile și comportamentele definite de clasa sa. O clasă poate conține cîmpuri și metode pentru a descrie comportamentul unui obiect [3, 63p.].

Metodele nu sunt altceva decît membri ai unei clase care oferă un serviciu pentru un obiect sau a efectua unele operații logice. Cîmpuri C++ și funcții membre nume sunt case sensitive. Stări actuale de obiect corespunzătoare unei clase sunt stocate în variabile de instanță ale obiectului. Metode definesc operațiunile care pot fi efectuate în programare C++. Să presupunem că avem un fișier numit HelloWorld.cpp, și ne-o dorim pentru a pune acest dosar într-o lume pachet. Primul lucru ce trebuie să facem este de a specifica pachetul de cuvinte cheie, cu numele pachetului ne-o dorim pentru a utiliza (lumea în cazul nostru), pe partea de sus a fișierului noastră sursă, înainte de codul care definește clasele reale în pachetul, așa cum se arată în clasa noastră HelloWorld de mai jos: package world.

Se recomandă respectarea următoarei convenții de notare: numele claselor încep întotdeauna cu literă mare. Dacă numele conține mai mulți atomi lexicali (cuvinte), fiecare dintre ei încep cu literă mare. După apăsarea butonului Finish, este deschis automat fișierul ce conține declarația noii clase, așa cum se vede .

Această instrucțiune trebuie plasată în interiorul metodei main() (care este echivalentul programului principal: execuția programului începe cu această metodă). Deoarece instrucțiunea este foarte uzitată, editorul platformei C++ Builder oferă o scurtătură pentru scrierea ei. Înainte de lansarea în execuție a unui program este recomandabil să salvați fișierele pe care le‐ați modificat. Oricum, mediul C++ Builder vă va cere permisiunea de a salva aceste fișiere înainte de lansarea în execuție.

3.3. Concluzii capitolul 3

Acest capitol sunt oferite doua ghiduri dedicate utilizatorilor și programatorilor pentru afacilita utilizarea de către diferite persoane cu diferite scopuri, fie ele de a elimina dacunele sau de implimenta o ideie nouă în acest sistem, fie de a recunoaște figurile geometrice din imagine.

În prima parte a acestui capitol am reprezentat ghidul destinat pentru utilizatori. Ce cuprinde informații despre fieacare componetă al acestui sistem, tradusă în limba romană. Tot în această parte al capitolului am oferit un exemplu de creare al unui clase pentru a fi mai bine înțeleasă modalitatea de utilizare al sistemului.

În partea doua al capitolului am prezentat ghidul destinat programatorilor în caz că apar noi idei, pentru a fi posibile de a fi implimentate. Au fost definite și prezentate exemple de crearea aunui proiect nou în C++, precum și introducerea pachetelor și claselor dacă apare necesitatea.

A fost oferit și un exemplu în care se observă ca putem deodată să vizualizăm rezultatul făra a ieși din sistem. Testarea sistemului este un proces important ce ne poate ilucida unele dacune grave în sistem pentru aceasta administratorul trebuie să fie informat și atent .

CONCLUZII GENERALE ȘI RECOMANDĂRI

Teza se bucură de originalitate, deoarece profesional are o aplicabilitate frumos[. Aceasta reprezintă o lucrare de sinteză care a fost executat în baza întregul spectru de cunoștințe acumulate pe parcursul întregii perioade de studii. Este o combinație complexă de cunoștințe teoretice și practice, care reprezintă în cele din urmă o descriere perfectă a modelului de funcționare și recunoaștere.

Mai mult, imaginea dressing și analiză este importantă și a început deja explorarea spectaculos de tehnologie electronică și informatică. Creșterea continuă a puterii de calcul disponibile la unitățile de amenajare de calculatoare se va transforma, probabil, foarte curând dressing si analiza imaginilor de la o țestoasă și anexă exotic într-o soluție fiabilă de mare uz industrial.

O atenție mare a fost acordată teoremele de evoluție și de descrierea fiecărui pas care are menirea de a ne ajuta pentru a crea un nou program. În special, o prezentare a modului de imagini invariante recunoaștere a fost definit și a fost proprietățile momente invariante cu avantaje principale și dezavantaje care au fost prezentate.

Pot concluziona că recunoașterea imaginilor invariante poate fi mai eficient și mai exact decât în ​​cazul în care sunt combinate, de exemplu – rotație cu scalare, translație cu rotație sau translație cu scalare.

Am elaborat algoritmul cu care voi realiza soft de recunoaștere a momentelor invariante. Am făcut o asociere puternică între metodele analizate și algoritmul elaborat de mine. În primul capitol am analizat recunoașterea imaginilor invariante fi mai eficientă dacă se utilizează metoda de rotație și scalarea sau traducerea și scalarea. Acum am venit cu un nou algoritm care vorbește despre recunoașterea rotite, scalarea și imagini traduse concomitent. Există o mulțime de avantaje în integral, utilizând a transformărilor invariante. Principalul avantaj este că transformarea și recunoașterea poate fi calculat foarte repede.

BIBLIOGRAFIE

Adamiu I., Brut V. C++ Builder de la 0 la expert. Iași: Polirom, 2007. 380p.

Arnold K., GoslingJ. The C++ Programming Language, Fourth Edition. Boston: Addison-Wesley, 2005. 320p.

Athanasiu A. Limbajul C++. O perspectivă pragmatică. Editura: Agora, 1998. 250p.

Beck K. Extreme Programming Explained: Embrace Change. Boston: Addison-Wesley, 1999. 2803p.

Bloch J. Effective C++ Programming Language Guide. Boston: Addison-Wesley, 2001. 420p.

Bloch J. C++ Builder Puzzlers: Traps, Pitfalls, andCorner Cases. Boston: Addison-Wesley, 2005. 220p.

Bloch J. Collections. In The C++ Tutorial: A Short Course onthe Basics, Fourth Edition. Boston: Addison-Wesley, 2006. 386p.

Bracha G. Generics in the C++ Programming Language. Boston: Addison-Wesley,2004. 658p.

Chun R. C++ Builder expert. USA: Adobe Press, 2010. 385p.

Cristea V. Sisteme inteligente de instruire pe Web. București: Editura Politehnica Press, 2005. 452p.

Darryl K. Borland: Behind the Name. Boston: Addison-Wesley, 2008. 233p.

Deitel H. C++: How to Program. New York: Prentice Hall, 2003. 425p.

Publicitate online. http://ro.wikipedia.org/wiki/Publicitate_online (vizitat 15.03.2015).

Ioniță A. Effective C++ Builder 1. București: Polirom 2002. 250p.

Ioniță A. Effective C++ for programing. București: Polirom 2005. 323p.

Goetz B. C++ Concurrency in Practice. Boston: Addison-Wesley, 2006. 535p.

Gong L., EllisonG. Inside C++ Platform Security, Second Edition. Boston: Addison-Wesley, 2003. 468p.

Gosling J. The C++ Language Specification, Third Edition. Boston: Addison-Wesley, 2005. 433p.

Horstmann C., Cornell G. Core C++: Vol. 1 – Fundamentals. New York: Prentice Hall, 2002. 360p.

Knudsen J. C++ Graphics. Boston: O’Reilly, 2001. 350p.

Langer A. Borland C++ Builder Generics FAQs — Frequently Asked Questions. London: Book, 2008. 139p.

Lea D. Concurrent Programming in C++: Design Principlesand Patterns, Second Edition. Boston: Addison-Wesley, 2000. 254p.

Naftalin M., WadlerP. C++ Generics and Collections. Sebastopol: O’Reilly Media, 2007. 330p.

Nica I., Brut V. C++ pentru experți. Iași: Polirom, 2004. 390p.

Reinhardt R. Online strategies. California: Press, 2009. 400p.

Rosca I. ș.a. C++ Builder, Revista Informatică Economică, nr. 2. București, 2002. 17p.

Morvan P. ș.a. Dicționar de Informatică. Traducere. București: Editura Niculescu, 2005. 340p.

Smith P. ș.a. Instructional Design. New York: John Wilez & Sons, 2005. 197p.

Șerbănați L. Limbaje de programare și compilatoare. Editura: Academiei, 1987. 283p.

Tipuri de programare în C++ practicate.

http://www.radutrifan.com/teza/tipuri_de_programare_cpp_practicate.php (vizitat 16 martie 2015).

Vlada M. C++ pentru începători. București: Editura Universității din Bucuresti, 2003. 489p.

ANEXA 1.

Codul sursă a programului:

//–––––––––––––––––––––––––

#include <vcl.h>

#pragma hdrstop

#include "Unit1.h"

#include <math.h>

//–––––––––––––––––––––––––

#pragma package(smart_init)

#pragma resource "*.dfm"

class forma

{

public:

char nume[50];

int perimetru;

int aria;

};

TForm1 *Form1;

forma forme[10];

int nr=0;

int latime=0,inaltime=0;

//–––––––––––––––––––––––––

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//–––––––––––––––––––––––––

void __fastcall TForm1::Button3Click(TObject *Sender)

{

Form1->Close();

}

//–––––––––––––––––––––––––

void __fastcall TForm1::Button1Click(TObject *Sender)

{

if (OpenPictureDialog1->Execute()==true)

{

Graphics::TBitmap *imagine = new Graphics::TBitmap();

imagine->LoadFromFile(OpenPictureDialog1->FileName );

Label6->Caption=OpenPictureDialog1->FileName;

Image1->Picture->Assign(imagine);

latime=imagine->Width ;

inaltime=imagine->Height ;

delete imagine;

}

}

//–––––––––––––––––––––––––-

void __fastcall TForm1::Button2Click(TObject *Sender)

{

TCanvas * Canvas = Image1->Canvas;

int i,j;

for (i = 1; i <= latime ; i++)

for (j=1;j<=inaltime ;j++)

if (Canvas->Pixels[i][j]==clBlack)

Canvas->Pixels[i][j]=clWhite;

else

if (Canvas->Pixels[i][j] >= ScrollBar1->Position-ScrollBar2->Position && Canvas->Pixels[i][j]<=ScrollBar1->Position+ScrollBar2->Position)

Canvas->Pixels[i][j]=clBlack;

else

Canvas->Pixels[i][j]=clWhite;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::ScrollBar1Change(TObject *Sender)

{

AnsiString aux1(ScrollBar1->Position);

AnsiString aux2("VALOARE CULOARE PRAG = ");

Label1->Caption= aux2+aux1;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::ScrollBar2Change(TObject *Sender)

{

AnsiString aux1(ScrollBar2->Position);

AnsiString aux2("INTERVAL RECUNOASTERE = ");

Label2->Caption= aux2+aux1;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::ScrollBar3Change(TObject *Sender)

{

AnsiString aux1(ScrollBar3->Position);

AnsiString aux2("ARIA MINIMA = ");

Label3->Caption= aux2+aux1;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::ScrollBar4Change(TObject *Sender)

{

AnsiString aux1(ScrollBar4->Position);

AnsiString aux2("ARIE MAXIMA = ");

Label4->Caption= aux2+aux1;

}

//–––––––––––––––––––––––––

int pozitii[100000][3]={0};

long poz=0;

int aux=0;

long valoare=0;

int negru,galben;

void contur(int i,int j, TCanvas * Canvas)

{

if (i>0 && i<latime && j>0 && j<inaltime)

if (Canvas->Pixels[i][j]==clYellow)

{

negru=0;

galben=0;

if (Canvas->Pixels[i+1][j]==clYellow ) galben++;

else {if (Canvas->Pixels[i+1][j]!=clBlue ) negru++;}

if (Canvas->Pixels[i+1][j+1]==clYellow ) galben++;

else {if (Canvas->Pixels[i+1][j+1]!=clBlue ) negru++;}

if (Canvas->Pixels[i][j+1]==clYellow ) galben++;

else { if (Canvas->Pixels[i][j+1]!=clBlue ) negru++;}

if (Canvas->Pixels[i+1][j-1]==clYellow ) galben++;

else {if (Canvas->Pixels[i+1][j-1]!=clBlue ) negru++;}

if (Canvas->Pixels[i-1][j+1]==clYellow ) galben++;

else {if (Canvas->Pixels[i-1][j+1]!=clBlue ) negru++;}

if (Canvas->Pixels[i][j-1]==clYellow ) galben++;

else {if (Canvas->Pixels[i][j-1]!=clBlue ) negru++;}

if (Canvas->Pixels[i-1][j]==clYellow ) galben++;

else {if (Canvas->Pixels[i-1][j]!=clBlue ) negru++;}

if (Canvas->Pixels[i-1][j-1]==clYellow ) galben++;

else {if (Canvas->Pixels[i-1][j-1]!=clBlue ) negru++;}

if (galben>0 && negru>0)

{

valoare++;

Canvas->Pixels[i][j]=RGB(0,0,255);

contur(i+1,j,Canvas);

contur(i,j+1,Canvas);

contur(i+1,j+1,Canvas);

contur(i-1,j-1,Canvas);

contur(i-1,j,Canvas);

contur(i,j-1,Canvas);

contur(i+1,j-1,Canvas);

contur(i-1,j+1,Canvas);

}

else return;

}

}

long perimetru(int i,int j,TCanvas * Canvas)

{

int aux;

while (i>0 && i<latime && j>0 && j<inaltime)

if (Canvas->Pixels[i][j]==clYellow )

{

aux=0;

if (Canvas->Pixels[i+1][j]==clYellow ) aux++;

if (Canvas->Pixels[i+1][j+1]==clYellow) aux++;

if (Canvas->Pixels[i][j+1]==clYellow) aux++;

if (Canvas->Pixels[i+1][j-1]==clYellow) aux++;

if (Canvas->Pixels[i-1][j+1]==clYellow) aux++;

if (Canvas->Pixels[i][j-1]==clYellow) aux++;

if (Canvas->Pixels[i-1][j]==clYellow) aux++;

if (Canvas->Pixels[i-1][j-1]==clYellow) aux++;

if (aux>=3)

i++;

else break;

}

else {i–;break;}

valoare=0;

contur(i,j,Canvas);

return valoare;

}

void gaseste(int i,int j)

{

int k;

for (k=1;k<=poz;k++)

if (pozitii[k][0]==i && pozitii[k][1]==j)

{

pozitii[k][2]=0;

return;

}

}

void umple(int i,int j,TCanvas * Canvas)

{

if (i>0 && i<latime && j>0 && j<inaltime)

{

valoare++;

Canvas->Pixels[i][j]=RGB(0,0,0);

gaseste(i,j);

if (Canvas->Pixels[i+1][j]==clYellow || Canvas->Pixels[i+1][j]==clBlue)

umple(i+1,j,Canvas);

if (Canvas->Pixels[i][j+1]==clYellow || Canvas->Pixels[i][j+1]==clBlue)

umple(i,j+1,Canvas);

if (Canvas->Pixels[i+1][j+1]==clYellow || Canvas->Pixels[i+1][j+1]==clBlue)

umple(i+1,j+1,Canvas);

if (Canvas->Pixels[i-1][j-1]==clYellow || Canvas->Pixels[i-1][j-1]==clBlue)

umple(i-1,j-1,Canvas);

if (Canvas->Pixels[i-1][j]==clYellow || Canvas->Pixels[i-1][j]==clBlue)

umple(i-1,j,Canvas);

if (Canvas->Pixels[i][j-1]==clYellow || Canvas->Pixels[i][j-1]==clBlue)

umple(i,j-1,Canvas);

if (Canvas->Pixels[i+1][j-1]==clYellow || Canvas->Pixels[i+1][j-1]==clBlue)

umple(i+1,j-1,Canvas);

if (Canvas->Pixels[i-1][j+1]==clYellow || Canvas->Pixels[i-1][j+1]==clBlue)

umple(i-1,j+1,Canvas);

}

// else return;

}

long aria(int i,int j,TCanvas * Canvas)

{

valoare=0;

umple(i,j,Canvas);

return valoare;

}

#define EROARE_PATRAT 5

int patrat(long perimetru,long aria)

{

double latura=sqrt(aria);

if (fabs(4*latura-perimetru)<=EROARE_PATRAT) return 1;

return 0;

}

#define EROARE_CERC 5

int cerc(long perimetru,long aria)

{

double raza=sqrt(aria)/M_PI;

if (fabs(2*M_PI*raza-perimetru)<=EROARE_CERC) return 1;

return 0;

}

#define EROARE_TRIUNGHI 5

int triunghi(long perimetru,long aria)

{

double latura=perimetru/3;

if (fabs(latura*latura*sqrt(3)/4-aria)<=EROARE_TRIUNGHI) return 1;

return 0;

}

#define EROARE_CRUCE 5

int cruce(long perimetru,long aria)

{

double latura=perimetru/4;

if (fabs(5*latura*latura/9-aria)<=EROARE_CRUCE) return 1;

return 0;

}

#define EROARE_DREPTUNGHI 5

int dreptunghi(long perimetru,long aria)

{

double latime=perimetru/6;

double lungime=perimetru-latime;

if (fabs(latime*lungime-aria)<=EROARE_DREPTUNGHI) return 1;

return 0;

}

#define EROARE_TRAPEZ 5

int trapez(long perimetru,long aria)

{

double latura=sqrt(2*aria/3);

if (fabs((3*latura+latura*sqrt(5))-perimetru)<=EROARE_TRAPEZ) return 1;

return 0;

}

void __fastcall TForm1::Button4Click(TObject *Sender)

{

AnsiString aux1;

AnsiString aux2;

int aux,i,j,k;

double prop1,prop2;

poz=0;

for (i = 1; i <= latime; i++)

for (j=1;j<=inaltime;j++)

if (Canvas->Pixels[i][j]==clBlack)

{

k=0;

while (k<10000)

{

k++;

aux=0;

if (Canvas->Pixels[i][j-k]==clBlack) aux++;

if (Canvas->Pixels[i-k][j]==clBlack) aux++;

if (Canvas->Pixels[i+k][j]==clBlack) aux++;

if (Canvas->Pixels[i][j+k]==clBlack) aux++;

if (aux<=3) break;

}

if (k>=4)

{

pozitii[++poz][0]=i;

pozitii[poz][1]=j;

pozitii[poz][2]=k-1;

}

}

for (i=1;i<=poz;i++)

if (pozitii[i][2]>=ScrollBar5->Position)

Canvas->Pixels[pozitii[i][0]][pozitii[i][1]]=clYellow;

int mem_maxim=0;

int mem_x;

long mem_aria;

long mem_perimetru;

while(1)

{

mem_maxim=0;

for (i=1;i<poz;i++)

{

if (mem_maxim<pozitii[i][2])

{

mem_maxim=pozitii[i][2];

mem_x=i;

}

}

if (mem_maxim==0) break;

mem_perimetru=perimetru(pozitii[mem_x][0],pozitii[mem_x][1],Canvas);

mem_aria=aria(pozitii[mem_x][0],pozitii[mem_x][1],Canvas);

if (mem_perimetru==0) break;

if (mem_aria==0) break;

mem_maxim=0;

if (mem_aria>=ScrollBar3->Position && mem_aria<=ScrollBar4->Position)

{

int loc=0;

int minim=10000;

for (i=1;i<=nr;i++)

{

if (mem_aria<forme[i].aria)

prop1=(double)forme[i].aria/mem_aria;

else

prop1=(double)mem_aria/forme[i].aria;

if (mem_perimetru<forme[i].perimetru)

prop2=(double)forme[i].perimetru/mem_perimetru;

else

prop2=(double)mem_perimetru/forme[i].perimetru;

if (minim>=fabs(prop1-prop2))

{

minim=fabs(prop1-prop2);

loc=i;

}

}

if (loc!=0)

Canvas->TextOut(pozitii[mem_x][0],pozitii[mem_x][1],forme[loc].nume);

aux1="";

aux1.printf("%d",mem_perimetru);

aux2="";

aux2.printf("%d",mem_aria);

Canvas->TextOut(pozitii[mem_x][0],pozitii[mem_x][1]-20,aux1);

Canvas->TextOut(pozitii[mem_x][0],pozitii[mem_x][1]+20,aux2);

}

}

}

//–––––––––––––––––––––––––

void __fastcall TForm1::ScrollBar5Change(TObject *Sender)

{

AnsiString aux1(ScrollBar5->Position);

AnsiString aux2("PRAG PENTRU ARIE = ");

Label5->Caption= aux2+aux1;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::FormActivate(TObject *Sender)

{

nr=0;

strcpy(forme[++nr].nume,"PATRAT");

forme[nr].perimetru=200;

forme[nr].aria=2500;

strcpy(forme[++nr].nume,"CERC");

forme[nr].perimetru=157;

forme[nr].aria=1962;

strcpy(forme[++nr].nume,"TRIUNGHI");

forme[nr].perimetru=112;

forme[nr].aria=1250;

strcpy(forme[++nr].nume,"CRUCE");

forme[nr].perimetru=200;

forme[nr].aria=1389;

strcpy(forme[++nr].nume,"DREPTUNGHI");

forme[nr].perimetru=300;

forme[nr].aria=5000;

strcpy(forme[++nr].nume,"TRAPEZ");

forme[nr].perimetru=203;

forme[nr].aria=2400;

AnsiString aux;

aux="";

aux.printf("%ld",ScrollBar1->Position);

Label1->Caption ="VALOARE CULOARE PRAG = " + aux;

aux="";

aux.printf("%ld",ScrollBar2->Position);

Label2->Caption ="INTERVAL RECUNOASTERE = " + aux;

aux="";

aux.printf("%ld",ScrollBar3->Position);

Label3->Caption ="ARIE MINIMA = " + aux;

aux="";

aux.printf("%ld",ScrollBar4->Position);

Label4->Caption ="ARIE MAXIMA = " + aux;

aux="";

aux.printf("%ld",ScrollBar5->Position);

Label5->Caption ="PRAG PENTRU ARIE = " + aux;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::FormCreate(TObject *Sender)

{

GroupBox1->Visible=false;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::CheckBox1Click(TObject *Sender)

{

if(CheckBox1->Checked==true) {

GroupBox1->Visible=true;

CheckBox1->Caption="Scoate bifa p/u a ascunde setarile"; }

else {

GroupBox1->Visible=false;

CheckBox1->Caption="Bifeaza p/u a vedea panoul cu setari";

}

}

//–––––––––––––––––––––––––

BIBLIOGRAFIE

Adamiu I., Brut V. C++ Builder de la 0 la expert. Iași: Polirom, 2007. 380p.

Arnold K., GoslingJ. The C++ Programming Language, Fourth Edition. Boston: Addison-Wesley, 2005. 320p.

Athanasiu A. Limbajul C++. O perspectivă pragmatică. Editura: Agora, 1998. 250p.

Beck K. Extreme Programming Explained: Embrace Change. Boston: Addison-Wesley, 1999. 2803p.

Bloch J. Effective C++ Programming Language Guide. Boston: Addison-Wesley, 2001. 420p.

Bloch J. C++ Builder Puzzlers: Traps, Pitfalls, andCorner Cases. Boston: Addison-Wesley, 2005. 220p.

Bloch J. Collections. In The C++ Tutorial: A Short Course onthe Basics, Fourth Edition. Boston: Addison-Wesley, 2006. 386p.

Bracha G. Generics in the C++ Programming Language. Boston: Addison-Wesley,2004. 658p.

Chun R. C++ Builder expert. USA: Adobe Press, 2010. 385p.

Cristea V. Sisteme inteligente de instruire pe Web. București: Editura Politehnica Press, 2005. 452p.

Darryl K. Borland: Behind the Name. Boston: Addison-Wesley, 2008. 233p.

Deitel H. C++: How to Program. New York: Prentice Hall, 2003. 425p.

Publicitate online. http://ro.wikipedia.org/wiki/Publicitate_online (vizitat 15.03.2015).

Ioniță A. Effective C++ Builder 1. București: Polirom 2002. 250p.

Ioniță A. Effective C++ for programing. București: Polirom 2005. 323p.

Goetz B. C++ Concurrency in Practice. Boston: Addison-Wesley, 2006. 535p.

Gong L., EllisonG. Inside C++ Platform Security, Second Edition. Boston: Addison-Wesley, 2003. 468p.

Gosling J. The C++ Language Specification, Third Edition. Boston: Addison-Wesley, 2005. 433p.

Horstmann C., Cornell G. Core C++: Vol. 1 – Fundamentals. New York: Prentice Hall, 2002. 360p.

Knudsen J. C++ Graphics. Boston: O’Reilly, 2001. 350p.

Langer A. Borland C++ Builder Generics FAQs — Frequently Asked Questions. London: Book, 2008. 139p.

Lea D. Concurrent Programming in C++: Design Principlesand Patterns, Second Edition. Boston: Addison-Wesley, 2000. 254p.

Naftalin M., WadlerP. C++ Generics and Collections. Sebastopol: O’Reilly Media, 2007. 330p.

Nica I., Brut V. C++ pentru experți. Iași: Polirom, 2004. 390p.

Reinhardt R. Online strategies. California: Press, 2009. 400p.

Rosca I. ș.a. C++ Builder, Revista Informatică Economică, nr. 2. București, 2002. 17p.

Morvan P. ș.a. Dicționar de Informatică. Traducere. București: Editura Niculescu, 2005. 340p.

Smith P. ș.a. Instructional Design. New York: John Wilez & Sons, 2005. 197p.

Șerbănați L. Limbaje de programare și compilatoare. Editura: Academiei, 1987. 283p.

Tipuri de programare în C++ practicate.

http://www.radutrifan.com/teza/tipuri_de_programare_cpp_practicate.php (vizitat 16 martie 2015).

Vlada M. C++ pentru începători. București: Editura Universității din Bucuresti, 2003. 489p.

ANEXA 1.

Codul sursă a programului:

//–––––––––––––––––––––––––

#include <vcl.h>

#pragma hdrstop

#include "Unit1.h"

#include <math.h>

//–––––––––––––––––––––––––

#pragma package(smart_init)

#pragma resource "*.dfm"

class forma

{

public:

char nume[50];

int perimetru;

int aria;

};

TForm1 *Form1;

forma forme[10];

int nr=0;

int latime=0,inaltime=0;

//–––––––––––––––––––––––––

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//–––––––––––––––––––––––––

void __fastcall TForm1::Button3Click(TObject *Sender)

{

Form1->Close();

}

//–––––––––––––––––––––––––

void __fastcall TForm1::Button1Click(TObject *Sender)

{

if (OpenPictureDialog1->Execute()==true)

{

Graphics::TBitmap *imagine = new Graphics::TBitmap();

imagine->LoadFromFile(OpenPictureDialog1->FileName );

Label6->Caption=OpenPictureDialog1->FileName;

Image1->Picture->Assign(imagine);

latime=imagine->Width ;

inaltime=imagine->Height ;

delete imagine;

}

}

//–––––––––––––––––––––––––-

void __fastcall TForm1::Button2Click(TObject *Sender)

{

TCanvas * Canvas = Image1->Canvas;

int i,j;

for (i = 1; i <= latime ; i++)

for (j=1;j<=inaltime ;j++)

if (Canvas->Pixels[i][j]==clBlack)

Canvas->Pixels[i][j]=clWhite;

else

if (Canvas->Pixels[i][j] >= ScrollBar1->Position-ScrollBar2->Position && Canvas->Pixels[i][j]<=ScrollBar1->Position+ScrollBar2->Position)

Canvas->Pixels[i][j]=clBlack;

else

Canvas->Pixels[i][j]=clWhite;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::ScrollBar1Change(TObject *Sender)

{

AnsiString aux1(ScrollBar1->Position);

AnsiString aux2("VALOARE CULOARE PRAG = ");

Label1->Caption= aux2+aux1;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::ScrollBar2Change(TObject *Sender)

{

AnsiString aux1(ScrollBar2->Position);

AnsiString aux2("INTERVAL RECUNOASTERE = ");

Label2->Caption= aux2+aux1;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::ScrollBar3Change(TObject *Sender)

{

AnsiString aux1(ScrollBar3->Position);

AnsiString aux2("ARIA MINIMA = ");

Label3->Caption= aux2+aux1;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::ScrollBar4Change(TObject *Sender)

{

AnsiString aux1(ScrollBar4->Position);

AnsiString aux2("ARIE MAXIMA = ");

Label4->Caption= aux2+aux1;

}

//–––––––––––––––––––––––––

int pozitii[100000][3]={0};

long poz=0;

int aux=0;

long valoare=0;

int negru,galben;

void contur(int i,int j, TCanvas * Canvas)

{

if (i>0 && i<latime && j>0 && j<inaltime)

if (Canvas->Pixels[i][j]==clYellow)

{

negru=0;

galben=0;

if (Canvas->Pixels[i+1][j]==clYellow ) galben++;

else {if (Canvas->Pixels[i+1][j]!=clBlue ) negru++;}

if (Canvas->Pixels[i+1][j+1]==clYellow ) galben++;

else {if (Canvas->Pixels[i+1][j+1]!=clBlue ) negru++;}

if (Canvas->Pixels[i][j+1]==clYellow ) galben++;

else { if (Canvas->Pixels[i][j+1]!=clBlue ) negru++;}

if (Canvas->Pixels[i+1][j-1]==clYellow ) galben++;

else {if (Canvas->Pixels[i+1][j-1]!=clBlue ) negru++;}

if (Canvas->Pixels[i-1][j+1]==clYellow ) galben++;

else {if (Canvas->Pixels[i-1][j+1]!=clBlue ) negru++;}

if (Canvas->Pixels[i][j-1]==clYellow ) galben++;

else {if (Canvas->Pixels[i][j-1]!=clBlue ) negru++;}

if (Canvas->Pixels[i-1][j]==clYellow ) galben++;

else {if (Canvas->Pixels[i-1][j]!=clBlue ) negru++;}

if (Canvas->Pixels[i-1][j-1]==clYellow ) galben++;

else {if (Canvas->Pixels[i-1][j-1]!=clBlue ) negru++;}

if (galben>0 && negru>0)

{

valoare++;

Canvas->Pixels[i][j]=RGB(0,0,255);

contur(i+1,j,Canvas);

contur(i,j+1,Canvas);

contur(i+1,j+1,Canvas);

contur(i-1,j-1,Canvas);

contur(i-1,j,Canvas);

contur(i,j-1,Canvas);

contur(i+1,j-1,Canvas);

contur(i-1,j+1,Canvas);

}

else return;

}

}

long perimetru(int i,int j,TCanvas * Canvas)

{

int aux;

while (i>0 && i<latime && j>0 && j<inaltime)

if (Canvas->Pixels[i][j]==clYellow )

{

aux=0;

if (Canvas->Pixels[i+1][j]==clYellow ) aux++;

if (Canvas->Pixels[i+1][j+1]==clYellow) aux++;

if (Canvas->Pixels[i][j+1]==clYellow) aux++;

if (Canvas->Pixels[i+1][j-1]==clYellow) aux++;

if (Canvas->Pixels[i-1][j+1]==clYellow) aux++;

if (Canvas->Pixels[i][j-1]==clYellow) aux++;

if (Canvas->Pixels[i-1][j]==clYellow) aux++;

if (Canvas->Pixels[i-1][j-1]==clYellow) aux++;

if (aux>=3)

i++;

else break;

}

else {i–;break;}

valoare=0;

contur(i,j,Canvas);

return valoare;

}

void gaseste(int i,int j)

{

int k;

for (k=1;k<=poz;k++)

if (pozitii[k][0]==i && pozitii[k][1]==j)

{

pozitii[k][2]=0;

return;

}

}

void umple(int i,int j,TCanvas * Canvas)

{

if (i>0 && i<latime && j>0 && j<inaltime)

{

valoare++;

Canvas->Pixels[i][j]=RGB(0,0,0);

gaseste(i,j);

if (Canvas->Pixels[i+1][j]==clYellow || Canvas->Pixels[i+1][j]==clBlue)

umple(i+1,j,Canvas);

if (Canvas->Pixels[i][j+1]==clYellow || Canvas->Pixels[i][j+1]==clBlue)

umple(i,j+1,Canvas);

if (Canvas->Pixels[i+1][j+1]==clYellow || Canvas->Pixels[i+1][j+1]==clBlue)

umple(i+1,j+1,Canvas);

if (Canvas->Pixels[i-1][j-1]==clYellow || Canvas->Pixels[i-1][j-1]==clBlue)

umple(i-1,j-1,Canvas);

if (Canvas->Pixels[i-1][j]==clYellow || Canvas->Pixels[i-1][j]==clBlue)

umple(i-1,j,Canvas);

if (Canvas->Pixels[i][j-1]==clYellow || Canvas->Pixels[i][j-1]==clBlue)

umple(i,j-1,Canvas);

if (Canvas->Pixels[i+1][j-1]==clYellow || Canvas->Pixels[i+1][j-1]==clBlue)

umple(i+1,j-1,Canvas);

if (Canvas->Pixels[i-1][j+1]==clYellow || Canvas->Pixels[i-1][j+1]==clBlue)

umple(i-1,j+1,Canvas);

}

// else return;

}

long aria(int i,int j,TCanvas * Canvas)

{

valoare=0;

umple(i,j,Canvas);

return valoare;

}

#define EROARE_PATRAT 5

int patrat(long perimetru,long aria)

{

double latura=sqrt(aria);

if (fabs(4*latura-perimetru)<=EROARE_PATRAT) return 1;

return 0;

}

#define EROARE_CERC 5

int cerc(long perimetru,long aria)

{

double raza=sqrt(aria)/M_PI;

if (fabs(2*M_PI*raza-perimetru)<=EROARE_CERC) return 1;

return 0;

}

#define EROARE_TRIUNGHI 5

int triunghi(long perimetru,long aria)

{

double latura=perimetru/3;

if (fabs(latura*latura*sqrt(3)/4-aria)<=EROARE_TRIUNGHI) return 1;

return 0;

}

#define EROARE_CRUCE 5

int cruce(long perimetru,long aria)

{

double latura=perimetru/4;

if (fabs(5*latura*latura/9-aria)<=EROARE_CRUCE) return 1;

return 0;

}

#define EROARE_DREPTUNGHI 5

int dreptunghi(long perimetru,long aria)

{

double latime=perimetru/6;

double lungime=perimetru-latime;

if (fabs(latime*lungime-aria)<=EROARE_DREPTUNGHI) return 1;

return 0;

}

#define EROARE_TRAPEZ 5

int trapez(long perimetru,long aria)

{

double latura=sqrt(2*aria/3);

if (fabs((3*latura+latura*sqrt(5))-perimetru)<=EROARE_TRAPEZ) return 1;

return 0;

}

void __fastcall TForm1::Button4Click(TObject *Sender)

{

AnsiString aux1;

AnsiString aux2;

int aux,i,j,k;

double prop1,prop2;

poz=0;

for (i = 1; i <= latime; i++)

for (j=1;j<=inaltime;j++)

if (Canvas->Pixels[i][j]==clBlack)

{

k=0;

while (k<10000)

{

k++;

aux=0;

if (Canvas->Pixels[i][j-k]==clBlack) aux++;

if (Canvas->Pixels[i-k][j]==clBlack) aux++;

if (Canvas->Pixels[i+k][j]==clBlack) aux++;

if (Canvas->Pixels[i][j+k]==clBlack) aux++;

if (aux<=3) break;

}

if (k>=4)

{

pozitii[++poz][0]=i;

pozitii[poz][1]=j;

pozitii[poz][2]=k-1;

}

}

for (i=1;i<=poz;i++)

if (pozitii[i][2]>=ScrollBar5->Position)

Canvas->Pixels[pozitii[i][0]][pozitii[i][1]]=clYellow;

int mem_maxim=0;

int mem_x;

long mem_aria;

long mem_perimetru;

while(1)

{

mem_maxim=0;

for (i=1;i<poz;i++)

{

if (mem_maxim<pozitii[i][2])

{

mem_maxim=pozitii[i][2];

mem_x=i;

}

}

if (mem_maxim==0) break;

mem_perimetru=perimetru(pozitii[mem_x][0],pozitii[mem_x][1],Canvas);

mem_aria=aria(pozitii[mem_x][0],pozitii[mem_x][1],Canvas);

if (mem_perimetru==0) break;

if (mem_aria==0) break;

mem_maxim=0;

if (mem_aria>=ScrollBar3->Position && mem_aria<=ScrollBar4->Position)

{

int loc=0;

int minim=10000;

for (i=1;i<=nr;i++)

{

if (mem_aria<forme[i].aria)

prop1=(double)forme[i].aria/mem_aria;

else

prop1=(double)mem_aria/forme[i].aria;

if (mem_perimetru<forme[i].perimetru)

prop2=(double)forme[i].perimetru/mem_perimetru;

else

prop2=(double)mem_perimetru/forme[i].perimetru;

if (minim>=fabs(prop1-prop2))

{

minim=fabs(prop1-prop2);

loc=i;

}

}

if (loc!=0)

Canvas->TextOut(pozitii[mem_x][0],pozitii[mem_x][1],forme[loc].nume);

aux1="";

aux1.printf("%d",mem_perimetru);

aux2="";

aux2.printf("%d",mem_aria);

Canvas->TextOut(pozitii[mem_x][0],pozitii[mem_x][1]-20,aux1);

Canvas->TextOut(pozitii[mem_x][0],pozitii[mem_x][1]+20,aux2);

}

}

}

//–––––––––––––––––––––––––

void __fastcall TForm1::ScrollBar5Change(TObject *Sender)

{

AnsiString aux1(ScrollBar5->Position);

AnsiString aux2("PRAG PENTRU ARIE = ");

Label5->Caption= aux2+aux1;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::FormActivate(TObject *Sender)

{

nr=0;

strcpy(forme[++nr].nume,"PATRAT");

forme[nr].perimetru=200;

forme[nr].aria=2500;

strcpy(forme[++nr].nume,"CERC");

forme[nr].perimetru=157;

forme[nr].aria=1962;

strcpy(forme[++nr].nume,"TRIUNGHI");

forme[nr].perimetru=112;

forme[nr].aria=1250;

strcpy(forme[++nr].nume,"CRUCE");

forme[nr].perimetru=200;

forme[nr].aria=1389;

strcpy(forme[++nr].nume,"DREPTUNGHI");

forme[nr].perimetru=300;

forme[nr].aria=5000;

strcpy(forme[++nr].nume,"TRAPEZ");

forme[nr].perimetru=203;

forme[nr].aria=2400;

AnsiString aux;

aux="";

aux.printf("%ld",ScrollBar1->Position);

Label1->Caption ="VALOARE CULOARE PRAG = " + aux;

aux="";

aux.printf("%ld",ScrollBar2->Position);

Label2->Caption ="INTERVAL RECUNOASTERE = " + aux;

aux="";

aux.printf("%ld",ScrollBar3->Position);

Label3->Caption ="ARIE MINIMA = " + aux;

aux="";

aux.printf("%ld",ScrollBar4->Position);

Label4->Caption ="ARIE MAXIMA = " + aux;

aux="";

aux.printf("%ld",ScrollBar5->Position);

Label5->Caption ="PRAG PENTRU ARIE = " + aux;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::FormCreate(TObject *Sender)

{

GroupBox1->Visible=false;

}

//–––––––––––––––––––––––––

void __fastcall TForm1::CheckBox1Click(TObject *Sender)

{

if(CheckBox1->Checked==true) {

GroupBox1->Visible=true;

CheckBox1->Caption="Scoate bifa p/u a ascunde setarile"; }

else {

GroupBox1->Visible=false;

CheckBox1->Caption="Bifeaza p/u a vedea panoul cu setari";

}

}

//–––––––––––––––––––––––––

Similar Posts

  • Sistem Informatic Pentru Medicina Dentara

    CUPRINS Capitolul 1. Introducere Obiectivul proiectului În prezent, informatica este într-o continuă dezvoltare, și își găsește aplicații în toate domeniile vieții. La nivel mondial, rețeaua a revoluționat viața privată a fiecărui individ, legătura și comunicarea dintre companii, logistică, mass media etc. Computerele pot transmite, prelucra, proteja și administra o mare cantitate de date într-un timp…

  • Magazine Virtuale

    CUPRINS: INTRODUCERE NOȚIUNI GENERALE DESPRE INTERNET Apariția Internetului în lume………………………………………………………..7 Funcționarea Internetului…………………………………………………………….8 1.3. Apariția Internetului în România………………………………………………….9 1.4. Utilitatea Internetului pentru Întreprinderile Mici și Mijlocii…………..10 AFACERI ELECTRONICE PE INTERNET 2.1. Caracteristici generale…………………………………………………………………15 2.2. Tipuri de afaceri on-line……………………………………………………………..17 2.3. Etapele realizării unei afaceri on-line……………………………………………23 2.4. Mijloace de plată în afacerile electronice………………………………………28 2.5. Categorii de fraude pe…

  • Calcul Stiintific de Inalta Performanta pe Procesoare Grafice

    Cuprins Motivarea alegerii temei de licență Tema lucrării mele de licență se intitulează „Calcul științific de înaltă performanță pe procesoare grafice” și reprezintă o curiozitate intelectuală și o nouă provocare în materie de dezvoltarea programelor. Motivul alegerii acestei teme rezultă din curiozitatea de documentare cu privire la procesoarele grafice. Fiind o temă de actualitate, așadar…

  • Avantajele utilizării AutoCAD sunt:

    CAPITOLUL I INTRODUCERE Desenarea și proiectarea asistată de calculator, cunosc în prezent o dezvoltare deosebită, datorită acurateții și rapidității pe care calculatorul le pune la dispoziția proiectantului. Avantajele utilizării AutoCAD sunt: AutoCAD-ul are un caracter general putând fi utilizat într-o varietate de domenii; AutoCAD-ul este un produs de desenare eficient și flexibil, permițând realizarea desenelor…