390
Tutte le informazioni contenute in questo volume sono rigorosamente sotto © COPYRIGHT di AMC ITALY e non possono essere distribuite o utilizzate senza permesso scritto della stessa. QUALSIASI ABUSO SARA’ PERSEGUITO A TERMINI DI LEGGE Versione 0.1.1 Flavio Bernardotti – [email protected] PROJECT MANAGER PROGETTO BIOTRACCIABILITA’ © Copyright 2004 AMC Italy Via La Pira, 21

Bioidentià - Il Progetto Ottico

Embed Size (px)

DESCRIPTION

Bioidentià - Il Progetto Ottico

Citation preview

Page 1: Bioidentià - Il Progetto Ottico

Tutte le informazioni contenute in questo volume sono rigorosamente sotto © COPYRIGHT di AMC ITALY e non

possono essere distribuite o utilizzate senza permesso scritto della stessa.

QUALSIASI ABUSO SARA’ PERSEGUITO A TERMINI DI LEGGE

Versione 0.1.1

Flavio Bernardotti – [email protected] MANAGER PROGETTO BIOTRACCIABILITA’

© Copyright 2004 AMC ItalyVia La Pira, 21

10028 Trofarello (TO)ITALY

[email protected]

Page 2: Bioidentià - Il Progetto Ottico

IntroduzioneIl progetto biotracciabilità è costituito da diversi gruppi logici relativi ciascuno ad una problematica differente come ad esempio l'acquisizione dell'immagine della retina, la sua elaborazione grafica, la creazione del codice di preselezione all'interno di un database, la sua comparazione con un'immagine di retina acquisita precedentemente e così via sino a giungere al sistema informativo destinato alla gestione logica di tutto insieme.

Uno dei blocchi, tra l'altro uno di quelli più delicati da cui dipende la buona riuscita di tutto resto del progetto, è quello relativo alla creazione del sistema ottico capace di eseguire l'acquisizione dell'immagine della retina.

Normalmente quando si progetto un obiettivo si tiene conto dei parametri relativi allo stesso per cui le modifiche del percorso ottico vengano considerate esclusivamente ed intrinsecamente al obiettivo.

Purtroppo la retina non è come uno degli oggetti che ci circondano nel mondo esterno ma è un qualche cosa presente all'interno di una sfera dentro la quale si accede tramite un foro di dimensioni ridotte il quale possiede a sua volta una lente utilizzata dall'occhio stesso per la focalizzazione delle immagine del nostro mondo reale.

Questa lente costituisce un'alterazione del percorso ottica o di un ipotetico obiettivo studiato per acquisire l'immagine retinale.

In altre parole nella progettazione di questo obiettivo si deve considerare il potere diottrico del cristallino.

Nella progettazione degli obiettivi fotografici ci si deve tener conto delle focalizzazione relativamente al mondo esterno ma anche del modo per illuminarlo.

Essendo la retina contenuta all'interno dell'occhio e chiaro che l'unico metodo per illuminarla e quella di fare passare la luce attraverso la pupilla e quindi attraverso il cristallino.

Senza considerare dati altamente scientifici e facile immaginare come la luce potrebbe di fatto creare grossi problemi nell'ambito del sistema di ripresa a causa della superficie lucida costituita dalla cornea dell'occhio e di fatto anche dal potere al ferrante rispetto a percorso ottico che possiede il cristallino.

In effetti la riflessione causata dalla lucidità della cornea potrebbe costituire un problema all'interno dell'attività di ripresa.

Page 3: Bioidentià - Il Progetto Ottico

Allo stesso modo le dimensioni della pupilla potrebbero indurre a poter fornire la luce in pochi modi e quindi l'eliminazione di certi tipi di problemi potrebbe essere di fatto un'operazione critica.

Lo sviluppo di questa parte di progetto pretende alcuni tipi di conoscenze legate alla fisiologia dell'occhio e alle proprietà della fisica dell'ottica.

Le informazioni che sono state utilizzate per lo sviluppo di tale progetto verranno riportate all'interno di questo volume al fine di sveltire l'opera di culturizzazione di una persona introdotta di fresco all'interno dello staff di lavoro.

In tale documento verranno riportate soltanto le informazioni di tipo tecnico in quanto quelle di tipo statistico potranno essere inserite solo dopo un lungo periodo di prova.

Generalmente un progetto diviene ideato in una certa maniera e successivamente, a seguito di test, alcuni metodi utilizzati vengono modificati per adattarli alla forma ottimale.

Alcune tipologie di problema possono essere immaginate ma di fatto l’ entità di queste possono essere solo considerate dopo prove pratiche.

In effetti alcuni tipi di informazione potrebbero essere ricavate da documenti provenienti da studi fatti da università nel campo dell'ottica come ad esempio quelle relative ai coefficienti di riflessione della retina.

Questo tipo di dato dovrebbe essere utilizzato nell'ambito dell'individuazione del sistema di illuminazione ideale.

Il problema è che di fatto passare dal informazione teorica a quella pratica in effetti potrebbe non essere così semplice come sembra per cui una serie di test pratici sarà sicuramente alla base della scelta effettiva.

Altri tipi di informazioni invece possono essere individuati mediante l'osservazione degli oggetti esistenti in quel determinato settore come ad esempio per quale che riguarda il sistema di illuminazione.

Uno dei capitoli presenti in questo volume sarà infatti quello indirizzato ad eseguire una panoramica sugli oftalmoscopi esistenti sul mercato per uso umano.

Generalmente la prima fase di un qualsiasi progetto e quella in cui si va a ricercare tutte le informazioni esistenti relative alla cultura specifica del progetto stesso.

Page 4: Bioidentià - Il Progetto Ottico

In altre parole, una volta individuati i settori di intervento, si cerca di creare dei poli culturali specifici di ogni settore.

Nel nostro caso la ricerca su Internet a costituisce uno dei punti predominante nell'ambito della progettazione anche se di fatto, per quello che riguarda il riconoscimento retinale, non esiste così tanta documentazione in merito neppure nel settore umano.

Chiaramente tale tipo di riconoscimento è risultato penalizzato dal suo alto coefficiente di invasività rispetto ad altre metodologie biometriche.

Un sistema di identificazione biometrico come ad esempio l'impronta digitale permette di eseguire tale funzione semplicemente appoggiando il dito su un sensore di rilevamento.

Il riconoscimento dell'iride invece pretende la semplice acquisizione dell'immagine dell'occhio mediante una telecamera posizionata a qualche decina di centimetri dal volto.

La retina invece, proprio per le complicazioni indotte dalla presenza del cristallino e dalle dimensioni ridotte della pupilla, pretende che l'occhio venga appoggiato su un sistema di rilevamento.

Questa procedura crea dei problemi in alcune persone.

Questo motivo è stato quello per cui il riconoscimento retinale è stato poco utilizzato in campo umano anche se di fatto l'immagine della retina e quella che permette delle percentuali di riconoscimento maggiore a qualsiasi altro metodo biometrico.

Page 5: Bioidentià - Il Progetto Ottico

Il sistema ottico.

La ripresa di una retina all'interno dell'occhio di una mucca è di fatto un'operazione complessa che deve tenere conto di molti fattori.Nei normali sistemi di ripresa l'obiettivo tiene conto di una focalizzazione minima ma di fatto generalmente non deve aver a che fare con una oggetti che modificano il percorso ottico.

Nel caso dell'occhio della mucca abbiamo, all'interno della pupilla, una lente che possiede sui due lati delle focali differenti che permettano di creare le immagine virtuale, da una parte, sulla retina e, dall'altra parte, sull'ambiente esterno.

Se mediante una macchina da ripresa dovessimo acquisire le immagine delle parti esterne dell'occhio non avremmo nessun tipo di problema in quanto l'occhio stesso risulterebbe essere come un normalissimo oggetto del mondo esterno per cui gli unici problemi di cui dovremmo tenere conto sarebbero quelli della quantità di luce e quindi della regolazione di un

diaframma atto a aumentare o diminuire la quantità di questa che arriverebbe alla cella di ripresa e della focale ovvero del sistema di lenti necessario per mettere a fuoco l’oggetto ad una

certa distanza.

La massima difficoltà che potremmo incontrare potrebbe essere collegata al fatto che l’occhio essendo una superficie lucida potrebbe riflettere le cose posizionate davanti a lui oltre alla luce dell’illuminazione.

Essendo la retina oltre questa lente chiamata cristallino il sistema di acquisizione dell'immagine deve essere calcolato tenendo conto delle focali relative alla sua parte interna e a quella esterna.

Inoltre i problemi relativi all'acquisizione delle immagini retinali coinvolge anche il sistema di illuminazione.

Page 6: Bioidentià - Il Progetto Ottico

La luce, o meglio il sistema di illuminazione, deve essere calcolato in modo tale da considerare nel insieme anche le focali

del cristallino.

La pupilla subisce l’influsso della luce per cui qualsiasi condizione sfavorevole potrebbe indurre ad un restringimento di questa e quindi un ulteriore complicazione nell’ambito della ripresa.Generalmente nel caso di progetti nuovi la prima attività è rivolta alla ricerca di quanto esiste già fatto con il fine di

trovare almeno un indirizzamento.

Sfortunatamente in questo settore non esiste nulla se non gli oftalmoscopi i quali comunque sono molto differenti in quanto la ripresa dell’immagine retinale avviene a contatto con l’occhio.

I metodi legati all'acquisizione della retina nell'ambito umano differiscono a causa di molte particolarità anche se di fatto la cosa fondamentale rimane la non collaborazione che c'è da parte dell'animale al momento della ripresa stessa.Gli portavano scoppi esistenti per uso umano sono essenzialmente di due tipi e precisamente:

Tipo indiretto Tipo diretto

Il primo tipo utilizza una lente da circa 20 diottrie tenute in mano dal medico e da un illuminatore posizionato in un caschetto tenuto in testa sempre da questo.

Il tipo diretto invece è praticamente una macchina fotografica indirizzata alla ripresa del fondo retinale.

A questa tipologia di oftalmoscopi appartengono quelle definite con il termine di fundus camera le quali generalmente sono progettate per uso ambulatoriale ed in ogni modo per pazienti collaborativi.

Questa tipologia di sistemi dispone di una struttura dentro alla quale il paziente appoggia la testa la quale viene tenuta ad una

Page 7: Bioidentià - Il Progetto Ottico

distanza fissata dall’obbiettivo di acquisizione.

Questo tipo di oftalmoscopio possiede un costo elevato e per questo motivo, a parte quello di doverlo considerare come un apparato fisso, può essere visto esclusivamente come uno strumento diagnostico da utilizzare all'interno di uno studio ottico.

Il sistema utilizza un insieme di specchi e di prismi finalizzati a fondere il percorso ottico con quello dell'illuminatore.

L'osservazione delle tipologie di oftalmoscopi presenti in circolazione

ha reso in un certo senso difficile la scelta della metodologia utilizzabile per la messa a fuoco della retina unita al sistema di illuminazione.

Infatti, come abbiamo appena detto, il sistema di lenti utilizzato per la messa a fuoco potrebbe essere in contrasto con il sistema di illuminazione utilizzato a causa degli effetti collaterali legati alla riflessione della luce stessa contro il vetro della lente.

Alcuni tipi di oftalmoscopi sfruttano l'emisfero alto della lente e quello basso per le due funzionalità ovvero il percorso ottico utilizzato per la visualizzazione della retina passa attraverso la parte alta mentre quella bassa viene utilizzata per focalizzare la luce.

Questa metodologia permette di utilizzare le due parti in modo separato in modo tale che il riflesso indotto dalla luce non vada a disturbare l'immagine acquisita.

Purtroppo questa metodologia è sicuramente quella più complicata da mettere a punto.

Una soluzione alternativa e quella di mettere illuminatore dopo la lente di focalizzazione.

Anche in questo caso bisogna prestare molta attenzione in quanto l'illuminatore stesso non deve coprire parte della zona utilizzata per la visualizzazione della retina.

Come vedremo successivamente i metodi utilizzati negli oftalmoscopi per uso umano purtroppo non possono essere utilizzati nel caso dell'acquisizione dell'immagine della retina legata ad una mucca.

Page 8: Bioidentià - Il Progetto Ottico

L'occhio della mucca infatti risulta essere molto più grosso di quello di un uomo anche se di fatto possiede alcune agevolazioni non disponibili in ambito umano come ad esempio le dimensioni molto più grande della pupilla.

Page 9: Bioidentià - Il Progetto Ottico

La tabella delle lenti

Nell'ambito del nostro progetto abbiamo utilizzato delle lenti scelte dai cataloghi della Edmund e della Thor.

A parte essere le compagnie più conosciute per quanto riguarda la fornitura di componenti per l'ottica sono anche quelle i cui cataloghi sono presenti all'interno dei programmi di simulazione di banchi ottici come ad esempio Zemax.

Quest'ultimo è stato utilizzato in sostituzione del Banco ottico fisico per tutto quello che riguarda la simulazione relativa all'obiettivo ottico e al sistema di illuminazione.

Dato che il manuale si prefigge d'essere anche una guida di consultazione vengono riportate le tabelle delle lenti commercializzate dalle varie società.

Questo viene fatto per facilitare il lavoro in fase di progettazione senza necessariamente doversi collegare su Internet per reperire i dati legati alle focali e alle dimensioni delle varie lenti utilizzabili.

Tech Spec™ Near Infrared Achromats

• Designed to Give Increased Resolution and Smaller Spot Sizes for NIR Wavelengths (700-1100nm)• Decreased Spherical Aberration for Monochromatic Sources Out to 2µm• Broadband AR Coating has <1% Reflectivity Between 700–1550nm

Our new Tech Spec™ Near IR doublets are designed to provide the smallest spot size possible for polychromatic light between 700 and 1100nm. By utilizing our NIR doublets instead of standard doublets designed for the visible, RMS spot diameter can be reduced from 43µm to 22.5µm, for example, when using polychromatic light. Spot size will be smaller when focusing monochromatic sources. Near-IR doublets also reduce spherical aberration and have superior performance when used with a monochromatic source up to 2µm in wavelength. Typical applications for these doublets include: CCD imaging lenses for the near infrared, focusing and expanding of NIR lasers, and focusing/collimating lenses for fiber optics and NIR LEDs.

Specification Table

Page 10: Bioidentià - Il Progetto Ottico

Diameter Surface Quality Dia. Tolerance C.T. Tolerance Centering Tolerance

3.00 40-20 +0.0/-0.05 ±0.2 3 - 5 arc min.

6.00 - 25.00 40-20 +0.0/-0.10 ±0.2 3 - 5 arc min.

50.00 60-40 +0.0/-0.10 ±0.2 3 - 5 arc min.

Notes Bevel If the diameter >= 0.85 x (radius of curvature), then no bevel is required.

3.00mm dia.: Max Bevel = 0.1mm x 45°

6.00 - 25.00mm dia.: Max Bevel = 0.25mm x 45°

50.00mm dia.: Max Bevel = 0.3mm x 45°

Clear Aperture 3.00 - 10.00mm dia.: CA >= 90% of diameter

10.1 - 50.00mm dia.: CA = diameter - 1.00mm

Glass Type LaKN22-SFL6

Focal Length Defined at 880nm; focal length tolerance ±2%

Coating NIR II AR (See Curves)

E.T. Tolerance Reference

Description Dia. (mm)

E.F.L. (mm)

Back F.L.

(mm) C.T.1 (mm)

C.T.2 (mm)

E.T. (mm)

Radius R1

(mm)

Radius R2

(mm)

Radius R3

(mm) MTF

Curve Stock Number

• LENS ACH-NIR 12 X 18 NIR-II

12 18 12.3 8 2.5 8.41 12.05 -8.65 -37.28 MTF Curve NT45-791

• LENS ACH-NIR 12 X 20 NIR-II

12 20 14.18 8 2.5 8.65 13.13 -9.59 -45.11 MTF Curve NT45-792

• LENS ACH-NIR 12 X 25 NIR-II

12 25 21.05 4.5 2.5 5.58 15.56 -13.75 -84.13 MTF Curve NT45-793

• LENS ACH-NIR 12 X 30 NIR-II

12 30 25.83 4.5 2.5 5.82 17.77 -16.46 -136.8 MTF Curve NT45-794

• LENS ACH-NIR 12 X 35 NIR-II

12 35 30.73 4.5 2.5 6 20.23 -19.17 -193.84 MTF Curve NT45-795

• LENS ACH-NIR 12 X 40 NIR-II

12 40 35.67 4.5 2.5 6.12 22.81 -21.91 -250.49 MTF Curve NT45-796

• LENS ACH-NIR 12 X 50 NIR-II

12 50 46.7 3 2.5 4.8 28.51 -28.2 -322.09 MTF Curve NT45-797

• LENS ACH-NIR 12 X 60 NIR-II

12 60 56.67 3 2.5 4.92 33.92 -33.81 -419.99 MTF Curve NT45-798

• LENS ACH-NIR 12 X 75 NIR-II

12 75 71.65 3 2.5 4.03 42.11 -42.3 -565.11 MTF Curve NT45-799

• LENS ACH-NIR 15 X 25 NIR-II

15 25 19.49 5.65 3.7 6.76 14.94 -14.94 -120.18 MTF Curve NT45-826

• LENS ACH-NIR 15 X 30 NIR-II

15 30 25.62 5 2 5.15 17.36 -17.36 -187.86 MTF Curve NT45-827

• LENS ACH-NIR 25 X 100 NIR-II

25 100 93.89 6 4 8.49 57.01 -56.72 -656.51 MTF Curve NT45-806

• LENS ACH-NIR 25 X 200 NIR-II

25 200 193.9 6 4 9.25 112.88 -112.88 -1415.62

MTF Curve NT47-271

• LENS ACH-NIR 25 X 35 NIR-II

25 35 26.87 11 4 10.48 23.4 -20.11 -87.52 MTF Curve NT45-800

Page 11: Bioidentià - Il Progetto Ottico

• LENS ACH-NIR 25 X 40 NIR-II

25 40 31.74 11 4 11.09 26.27 -22.26 -105.93 MTF Curve NT45-801

• LENS ACH-NIR 25 X 45 NIR-II

25 45 37.8 9 4 9.59 29.01 -25.53 -132.92 MTF Curve NT45-802

• LENS ACH-NIR 25 X 50 NIR-II

25 50 43.29 8 4 8.94 31.69 -28.45 -161.05 MTF Curve NT45-803

• LENS ACH-NIR 25 X 60 NIR-II

25 60 52.96 8 4 9.46 36.27 -33.8 -248.86 MTF Curve NT45-804

• LENS ACH-NIR 25 X 75 NIR-II

25 75 69.06 6 4 7.98 43.96 -42.9 -392.21 MTF Curve NT45-805

• LENS ACH-NIR 3 X 10 NIR-II

3 10 8.09 1.8 1 2.58 5.2 -5.2 0 MTF Curve NT45-822

• LENS ACH-NIR 3 X 15 NIR-II

3 15 13.07 1.8 1 2.65 7.71 -7.71 0 MTF Curve NT45-823

• LENS ACH-NIR 50 X 100 NIR-II

50 100 87.86 14.5 5.5 13.89 59.74 -59.74 -494.7 MTF Curve NT47-317

• LENS ACH-NIR 50 X 150 NIR-II

50 150 139.87 11 5.5 12.47 86.84 -86.84 -894.7 MTF Curve NT47-318

• LENS ACH-NIR 6 X 12 NIR-II

6 12 9.3 3.2 1 3.15 6.84 -5.99 -69.82 MTF Curve NT45-784

• LENS ACH-NIR 6 X 15 NIR-II

6 15 12.42 3 1.2 3.61 8.8 -7.93 -71.17 MTF Curve NT45-785

• LENS ACH-NIR 6 X 20 NIR-II

6 20 17.27 3 1.3 3.86 11.29 -10.63 -134.8 MTF Curve NT45-786

• LENS ACH-NIR 6 X 25 NIR-II

6 25 22.24 3 1.3 3.95 13.95 -13.4 -193.19 MTF Curve NT45-787

• LENS ACH-NIR 6 X 30 NIR-II

6 30 27.22 3 1.3 4.01 16.66 -16.18 -246.07 MTF Curve NT45-788

• LENS ACH-NIR 6 X 35 NIR-II

6 35 32.22 3 1.3 4.05 19.39 -19 -297.39 MTF Curve NT45-789

• LENS ACH-NIR 6 X 40 NIR-II

6 40 37.17 3 1.3 4.08 21.81 -22.07 -454.78 MTF Curve NT45-790

• LENS ACH-NIR 6 X 9 NIR-II

6 9 6.66 4 1.3 4.26 7.34 -4.18 -11.58 MTF Curve NT45-783

• LENS ACH-NIR 9 X 15 NIR-II

9 15 11.59 4.2 2 4.84 9.68 -7.91 -39.89 MTF Curve NT45-824

• LENS ACH-NIR 9 X 20 NIR-II

9 20 16.46 3.5 2 4.49 11.01 -11.01 -222.6 MTF Curve NT45-825

 

Page 12: Bioidentià - Il Progetto Ottico

Le lenti THORLAB

Product Summary

 Wavelength Range: 170nm to 8.0µm, Un coated Focal Lengths from 20mm to 1000mm

 Plano-Convex optics are best used where one conjugate point (object distance, S or image distance S’) is more than five times the other.This lens shape is near best-form for either focusing collimated light or for collimating a point source.

Part Number DIA    efl    tc    Material   LA5315 12.7 20.0 4.3 CAF2LA5183 12.7 50.0 2.5 CAF2LA5458 12.7 80.0 2.1 CAF2LA5370 25.4 40.0 7.5 CAF2LA5763 25.4 50.0 6.1 CAF2LA5042 25.4 75.0 4.6 CAF2LA5817 25.4 100.0 3.9 CAF2LA5012 25.4 150.0 3.3 CAF2LA5714 25.4 200.0 2.9 CAF2LA5255 25.4 250.0 2.8 CAF2LA5464 25.4 500.0 2.4 CAF2LA5956 25.4 750.0 2.3 CAF2LA5835 25.4 1000.0 2.2 CAF2

Product Summary

 Best Possible Performance from a Spherical Singlet Ideal for High Powered Applications

Page 13: Bioidentià - Il Progetto Ottico

 These lenses are an ideal choice for application from 200nm to 6µm. Magnesium Fluoride is extremely durable in comparison to other materials that reach this far down into the UV or out into the IR. The C-axis is oriented to minimize birefringence.

Plano-Convex optics are best used where one conjugate point (object distance, S or image distance S’) is more than five times the other.This lens shape is near best-form for either focusing collimated light or for collimating a point source.

Order

Part Number DIA    efl    fb    tc    Material   LA6002 25.4 50.0 45.0 6.9 MgF2LA6003 25.4 60.0 55.5 6.0 MgF2LA6004 25.4 75.0 71.4 5.0 MgF2LA6005 25.4 100.0 97.1 4.3 MgF2LA6006 25.4 150.0 147.7 3.2 MgF2LA6007 25.4 200.0 197.7 3.2 MgF2LA6008 25.4 250.0 248.0 2.8 MgF2LA6009 25.4 500.0 498.1 2.6 MgF2LA6010 25.4 1000.0 998.3 2.4 MgF2

Product Summary

 Wavelength Range: 185nm to 2.1µm, Uncoated Focal Lengths from 10mm to 1000mm Diameters from 5mm to 75mm Standard AR UV Coating Available: 290-370nm

 Plano-Convex optics are best used where one conjugate point (object distance, S or image distance S’) is more than five times the other.This lens shape is near best-form for either focusing collimated light or for collimating a point source.

Page 14: Bioidentià - Il Progetto Ottico

Part Number DIA    efl    tc    Material    Price   LA4249 5.0 10.0 2.2 UVFS $73.20   LA4280 6.0 10.0 2.6 UVFS $69.80   LA4917 6.0 15.0 2.2 UVFS $69.50   LA4194 6.0 20.0 2.0 UVFS $68.00   LA4966 6.0 30.0 1.8 UVFS $68.00   LA4647 12.7 20.0 4.3 UVFS $71.80   LA4936 12.7 30.0 3.4 UVFS $67.00   LA4130 12.7 40.0 2.9 UVFS $60.00   LA4765 12.7 50.0 2.7 UVFS $54.00   LA4327 12.7 75.0 2.4 UVFS $54.00   LA4600 12.7 100.0 2.2 UVFS $48.00   LA4052 25.4 35.0 8.2 UVFS $113.00   LA4306 25.4 40.0 7.1 UVFS $88.00   LA4148 25.4 50.0 5.8 UVFS $83.50   LA4725 25.4 75.0 4.4 UVFS $75.90   LA4380 25.4 100.0 3.8 UVFS $74.20   LA4236 25.4 125.0 3.4 UVFS $72.00   LA4874 25.4 150.0 3.2 UVFS $69.90   LA4924 25.4 175.0 3.0 UVFS $68.50   LA4102 25.4 200.0 2.9 UVFS $67.90   LA4158 25.4 250.0 2.7 UVFS $66.80   LA4579 25.4 300.0 2.6 UVFS $66.50   LA4184 25.4 500.0 2.4 UVFS $65.80   LA4716 25.4 750.0 2.2 UVFS $65.30   LA4663 25.4 1000.0 2.2 UVFS $65.00   LA4464 50.8 60.0 19.8 UVFS $240.00   LA4078 50.8 75.0 14.2 UVFS $230.00   LA4545 50.8 100.0 10.7 UVFS $214.00   LA4904 50.8 150.0 7.8 UVFS $206.00   LA4984 50.8 200.0 6.6 UVFS $194.80   LA4538 50.8 250.0 5.8 UVFS $182.00   LA4855 50.8 300.0 5.4 UVFS $168.00   LA4782 50.8 500.0 4.4 UVFS $156.00   

Page 15: Bioidentià - Il Progetto Ottico

LA4745 50.8 750.0 3.9 UVFS $146.00   LA4337 50.8 1000.0 3.7 UVFS $146.00   LA4384 75.0 90.0 26.9 UVFS $398.00   LA4372 75.0 150.0 14.1 UVFS $350.00   LA4795 75.0 200.0 11.0 UVFS $326.00   LA4246 75.0 500.0 6.1 UVFS $278.00   

LA4249-UV 5.0 10.0 2.2 UVFS $87.20   LA4280-UV 6.0 10.0 2.6 UVFS $83.80   LA4917-UV 6.0 15.0 2.2 UVFS $83.50   LA4194-UV 6.0 20.0 2.0 UVFS $82.00   LA4966-UV 6.0 30.0 1.8 UVFS $82.00   LA4647-UV 12.7 20.0 4.3 UVFS $85.80   LA4936-UV 12.7 30.0 3.4 UVFS $81.00   LA4130-UV 12.7 40.0 2.9 UVFS $74.00   LA4765-UV 12.7 50.0 2.7 UVFS $68.00   LA4327-UV 12.7 75.0 2.4 UVFS $68.00   LA4600-UV 12.7 100.0 2.2 UVFS $62.00   LA4052-UV 25.4 35.0 8.2 UVFS $141.00   LA4306-UV 25.4 40.0 7.1 UVFS $116.00   LA4148-UV 25.4 50.0 5.8 UVFS $111.50   LA4725-UV 25.4 75.0 4.4 UVFS $103.90   LA4380-UV 25.4 100.0 3.8 UVFS $102.20   LA4236-UV 25.4 125.0 3.4 UVFS $100.00   LA4874-UV 25.4 150.0 3.2 UVFS $97.90   LA4924-UV 25.4 175.0 3.0 UVFS $96.50   LA4102-UV 25.4 200.0 2.9 UVFS $95.90   LA4158-UV 25.4 250.0 2.7 UVFS $94.80   LA4579-UV 25.4 300.0 2.6 UVFS $94.50   LA4184-UV 25.4 500.0 2.4 UVFS $93.80   LA4716-UV 25.4 750.0 2.2 UVFS $93.30   LA4663-UV 25.4 1000.0 2.2 UVFS $93.00   LA4464-UV 50.8 60.0 19.8 UVFS $292.00   LA4078-UV 50.8 75.0 14.2 UVFS $282.00   LA4545-UV 50.8 100.0 10.7 UVFS $266.00   LA4904-UV 50.8 150.0 7.8 UVFS $258.00   LA4984-UV 50.8 200.0 6.6 UVFS $246.80   LA4538-UV 50.8 250.0 5.8 UVFS $234.00   LA4855-UV 50.8 300.0 5.4 UVFS $220.00   LA4782-UV 50.8 500.0 4.4 UVFS $208.00   LA4745-UV 50.8 750.0 3.9 UVFS $198.00   LA4337-UV 50.8 1000.0 3.7 UVFS $198.00   LA4384-UV 75.0 90.0 26.9 UVFS $450.00   LA4372-UV 75.0 150.0 14.1 UVFS $402.00   LA4795-UV 75.0 200.0 11.0 UVFS $378.00   LA4246-UV 75.0 500.0 6.1 UVFS $330.00   

Page 16: Bioidentià - Il Progetto Ottico

Come funziona l’occhio

Prima di poter supporre qualsiasi obiettivo adatto alla ripresa del fondo retinale è necessario conoscere il funzionamento dell'occhio. L'occhio, ovvero l'organo della vista, è un meccanismo complesso costituito da un'iride, paragonabile ad un diaframma automatico, da una pupilla composta da una lente chiamata cristallino, indirizzato alla focalizzazione verso un mondo esterno e verso la retina, da una retina, ovvero il meccanismo che traduce la luce in impulsi nervosi indirizzati al cervello e da altri componenti.Anche quelli che sono considerati componenti secondari devono essere presi in considerazione in quanto possono interagire con la fisica della luce.

Per fare un esempio potremmo un'utilizzare l'umore vitreo ovvero il liquido esistenti all'interno dell'occhio. Questo liquido agisce nel sistema di diffusione della luce all'interno dell'occhio stesso.La luce emessa dall'oggetto al quale si sta guardando giunge all'occhio attraverso la cornea. I raggi di luce attraversano la pupilla (la quale regola l'ammontare di luce che

giunge all'occhio), poi attraversano la lente (il cristallino).Finalmente, i raggi di luce vengono concentrati sulla retina che è un strato sottile coperta con celle recettori di luce. Grazie a reazioni elettrochimiche, la luce è convertita in impulsi elettrici emessi al cervello dal nervo ottico. Circa al centro della retina c’e’ una piccola depressione che è nota come macula.Al centro della macula ci sono celle contenute molto densamente (fovea) le quali forniscono le informazioni legate al colore. Ma, nonostante l'importanza del fovea, le altre parti della retina sono anche molto utili per scoprire il moto, vedere in luce fioca... Da un punto di vista ottico, l'occhio può essere comparato ad una macchina fotografica. Sulla mano del una, la combinazione di lente della macchina fotografica forma un'immagine sul film sensibile e d'altra parte l'occhio forma un'immagine sulla retina. Si dice che un occhio è normale, o emmetropico se l'immagine di un di oggetto distante focalizza sulla retina:

Page 17: Bioidentià - Il Progetto Ottico

altrimenti si dice che l'occhio sia ametropico.L'occhio normale è anche capace vedere oggetti vicini grazie ad un meccanismo di messa a fuoco eccellente, noto con il termine di sistemazione. Attraverso cambi nella sua forma, la lente (cristallino) dà una lunghezza focale variabile all'occhio.

Con questo meccanismo di sistemazione, il giovane occhio di creatura umana normale è capace vedere vicino ad oggetti, circa 25 cm di fronte a lui. Con l’ età, la sistemazione comincia a fallire e l'immagine di oggetti vicini può non concentrarsi sulla retina.Questo fenomeno è noto come presbiopia e comincia a colpire persone all'età di 40 anni.

Ametropia

Noi considereremo due generi di ametropia: miopia e hyperopia. Nota che noi immaginiamo l'occhio per non essere in condizione rilassata che è dire la sistemazione in uso.

Miopia

Miopia è la condizione in cui l'immagine di oggetti distanti cade di fronte alla retina.

Questo accade quando la lunghezza assiale della lente è troppo grande per il potere del sistema della lente.

Presbiopia

Hyperopia è la condizione in che l'immagine di oggetti distanti cade dietro alla retina.

Questo accade quando la lunghezza assiale della lente è troppo corta per il potere del sistema della lente.

Page 18: Bioidentià - Il Progetto Ottico

Una parte che a prima vista sembrerebbe centrare poco con gli studi relativi al sistema di acquisizione dell'immagine della retina, potrebbe essere quella legata al uso delle lenti finalizzata alla correzione dei difetti del cristallino.Di fatto questo permette di capire come un sistema di lenti esterne può interagire con il cristallino spesso al fine di creare una giusta focalizzazione sulla retina dell'occhio

Correzione della miopia

Un modo di correggere miopia è mettere una lente negativa (o lente divergente) di fronte all'occhio.

Correzione di hyperopia

Un modo di trattare hyperopia è mettere una lente positiva (o lente cobvergente) di fronte all'occhio. Un modo comune di caratterizzare le necessità della lente è quello di dargli il suo potere di vertice. Diamo un'occhiata alla definizione di potere di vertice di una lente:

Page 19: Bioidentià - Il Progetto Ottico

Come è possibile vedere, per un oggetto all'infinito, l'immagine è formata in f': punto di fuoco di immagine.

Per definizione, il potere di vertice di una lente è, l'inverso della distanza tra il vertice della superficie di retro e f.' Questa quantità è data in metro-1 o diottrie (D). Nel caso di miopia si può avere bisogno di un D di -3 con lente divergente per esempio, o un D del +3 con lente convergente nel caso di hyperopia.

Ora immaginiamo una persona di emmetropica.

A questo punto, lui può vedere chiaramente oggetti a distanze diverse, ma solamente oggetti che sono solo di fronte a lui.

Se l'oggetto che lui sta guardando si muove nel campo di visione, che cosa accade?

Come si può vedere, l'immagine dell'oggetto che è visto, non precipita sulla fovea e la visione non è perfetta (senza una buon acutezza). Questo problema può avere soluzioni diverse.

La prima, si può trasportare l'oggetto (come un orefice che guarda ad un diamante) o lo volta per metterlo solo di fronte al suo occhio.

Page 20: Bioidentià - Il Progetto Ottico

Questo non può essere sempre chiaramente in particolarmente se si sta guardando le stelle nel cielo.

Un altro modo più semplice e comune è trasportare la testa o girare gli occhi.

Nel seguente testo considereremo solamente il moto degli occhi, per una posizione determinata della testa:

Infatti il bulbo oculare sta muovendosi continuamente, così che luce emise da oggetto di interesse primario precipita sul fovea. Per esempio, quando Lei sta leggendo un giornale, è impossibile per leggere una linea intera senza trasportare la testa o gli occhi perché questo compito richiede una buon acutezza.

Una rappresentazione schematica dell'occhio è come segue.

Il bulbo oculare ruota intorno ad un punto fisso noto come il Centro di Rotazione dell’ Occhio (ECR) per concentrare l’ immagine sul fovea.

Questo è ottenuto quando i raggi di luce passano attraverso il centro della pupilla ed attraverso il centro dell'occhio di rotazione, definendo così una posizione di sguardo fisso.

Cosa si intende comunque, per l'indossatore di lenti oftalmiche?

Veda attraverso lenti oftalmiche Quando un myope o hypermetrope guarda attraverso una lente, pensa è un poco diverso. A causa delle leggi di Snell-Descartes, i raggi di luce non attraversano prima, la lente in una linea diritta.

Page 21: Bioidentià - Il Progetto Ottico

Occhio miope e lente che diverge

Hyperopic guarda e convergendo lente

Come Si può vedere, per la stessa posizione di sguardo fisso, emmetropico, miope e hypermetropico non vedranno lo stesso oggetto, o in altre parole, l'occhio di un myope ruoterà meno, che l'occhio di un hypermetrope per vedere lo stesso oggetto nel campo di visione. Questa è la ragione perché i miopi possono portare piccole montature e sono fortunati perché le lenti che divergono delle quali loro generalmente hanno bisogno si riducono in grossezza. Questi fenomeni sono noti come distorsione.

Ma c'è a questo punto un ultimo problema: lenti oftalmiche offrono solamente una buona visione mentre uno guarda attraverso i loro centri. Questo non è il caso come la posizione di sguardo fisso è non nullo, e la visione può essere colpita. Un modo di quantificare la qualità di visione sarebbe analizzare l'immagine formata sulla retina. Ma, sulla mano del una, è difficile fare raggio che traccia nell'occhio a causa di lui è struttura complessa e, d'altra parte non è facile interpretare come il cervello "vede" questa immagine. Come evitare questo?

Noi analizzeremo l'immagine formata dalla lente perché, infatti, questa è l'immagine alla quale l'occhio sta guardando: uno parla su immagine virtuale. Ma una cosa è sicura: il meglio l'immagine prodotta dalla lente, il meglio la qualità di visione per l'indossatore.

Per una posizione nulla di sguardo fisso, noi sappiamo, che l'immagine formò dalla lente prescritta deve essere ad una distanza 1/D metro dal vertice della superficie di schiena. Da dilazione per le altre posizioni di sguardo fisso, ed a causa della simmetria rotazionale circa l'ECR, l'immagine dovrebbe essere formata su una sfera concentrata su ECR, e noto come lontano sfera di punto.

Page 22: Bioidentià - Il Progetto Ottico

Come Si può immaginare, l'immagine formata dalla lente non è focalizzata sempre perfettamente sul lontano sfera di punto. Un modo di sapere se l'immagine è posizionata precisamente, è misurare la distanza tra l'intersecazione del raggio con la sfera di vertice (quale una sfera concentrò sull'ECR e tangente alla superficie di schiena) ed il fuoco aguzza. Questa quantità è definita per ogni posizione di sguardo fisso e dovrebbe essere 1/D metro sempre.

Aberrazioni presentate dalle lenti oftalmiche

Chiaramente, questa non è la meta della lente per presentare aberrazioni che saranno percepite direttamente dall'indossatore e decresceranno l'acutezza, ma cose sono cose... Comunque, nonostante le aberrazioni di tesi, è fiducioso che lenti oftalmiche sono valutate bene dagli indossatori.

Due generi delle aberrazioni possono deteriorare l'immagine:

aberrazioni cromatiche, a causa del fatto che il materiale della lente ha un indice che dipende dal colore o la frequenza della luce

le aberrazioni monocromatiche a causa della geometria della lente

Noi considereremo due delle aberrazioni monocromatiche e principali presi in considerazione nel contesto dell'ottica oftalmica: motorizzi errore ed astigmatismo.

Motorizzi errore:

Come spiegato prima, per una posizione determinata di sguardo fisso, il punto di fuoco può essere davanti, su, o dietro al

Page 23: Bioidentià - Il Progetto Ottico

lontano sfera di punto. Errore di potere è solo la differenza tra il potere prodotto dalla lente ed il potere prescritto. Errore di potere è positivo se il potere producesse dalla lente è più di D (il potere prescritto), e negativo (o nullo) altrimenti.

Astigmatismo:

Astigmatismo è asimmetricamente molto semplicemente, dovuto al fatto il cono di incidente di scioperi di raggi la lente. Quando il cono di raggi spedì dall'oggetto osservato giace una distanza apprezzabile dal centro della lente, loro non focalizzano in un solo punto ma immaginano come due linee corte, noto come foci astigmatico. Il rosso è il foci tangenziale ed il blu il sagittal foci.

Questa è una vista schematica con l'occhio, la lente ed il foci astigmatico:

Ora definiamo quantità diverse:

il potere tangenziale, T = 1 / Jt i sagittal motorizzano, S = 1 / Js

e Cattivo potere = (T + S) / 2

Page 24: Bioidentià - Il Progetto Ottico

Astigmatismo = | T - S | Motorizzi errore = il Cattivo potere - Prescrisse il potere

Astigmatismo è nullo al centro della lente sempre e generalmente aumenti con posizione di sguardo fisso. Errore di potere è supposto nullo al centro della lente, o nelle altre parole, noi consideriamo, la lente ha il potere prescritto al suo centro sempre.

Queste quantità sono definite per ogni posizione di sguardo fisso e possono essere rappresentate su tale grafico:

Come leggere questo grafico? Il rosso, curve blu e nere rappresentano rispettivamente il potere tangenziale, i sagittal motorizzano ed il cattivo potere di un D del +9 lente oftalmica. In questo caso, e per una posizione del 25° di sguardo fisso, T> 9 D, S <9 D e (T+S)/2> 9 D. Power errore che è la differenza tra il cattivo potere ed il potere prescritto (9 D) è più grande che 0, ed inscatola ape rosso sull'asse orizzontale, scalò tra -1 D e +1 Astigmatismo di D. può essere valutato come la distanza orizzontale tra il T e le curve di S. Motorizzi errore ed astigmatismo sono stampati anche in verde per la posizione attuale di sguardo fisso.

La conoscenza dell’occhio potrebbe indurre alla creazione di un illuminatore che permetta di non fare restringere la pupilla della mucca.

Quando si cercano i sistemi usati in campo umano per osservare la retina senza far dilatare la pupilla troviamo:

TRUCCHI PER OSSERVARE LA RETINA SENZA UTILIZZARE COLLIRI MIDRIATICI

Far rilassare il paziente

Page 25: Bioidentià - Il Progetto Ottico

Eseguire l’esame in ambiente non luminoso (meglio se quasi buio)

Chiedere al paziente di fissare un punto lontano Utilizzare un oftalmoscopio che dia una fioca illuminazione Evitare di dirigere il fascio di luce sulla macula del

paziente. Questo scatena la miosi. Cominciare l’osservazione dalla papilla e dai vasi della metà nasale.

Non fare stancare il paziente. Lasciandolo riposare per qualche secondo guadagneremo minuti preziosi grazie ad una migliore collaborazione

Se la parte di illuminazione non colpisce la fiovea la riduzione pupillare sarà minore.

Le seguenti immagini mostrano le varie componenti dell’occhio della mucca.

Il taglio della cornea La sua estrazione

L’estrazione del cristallino Lo spessore

Page 26: Bioidentià - Il Progetto Ottico

L’iride Il cristallino

Il fondo retinale La retina

Le ghiandole Il nervo ottico

Page 27: Bioidentià - Il Progetto Ottico

Gli oftalmoscopi

Come dicevamo prima all'inizio di una ricerca è sempre necessario crearsi una visione di tutto quello patrimonio informativo che è disponibile a riguardo di quanto già fatto in questo determinato settore.

Chiaramente le riprese dei fondi retina alle in campo veterinario non sono un settore così diffuso per cui l'unica documentazione reperibile è relativa a tutto quello che riguarda la ripresa delle retina in campo umano.

In questo settore bisogna però mettere un filtro alle ricerche in quanto la caratteristica fondamentale del nostro progetto rimane quella, come in tanti altri progetti, relativa al prezzo al quale si dovrà vendere il prodotto.

In campo oftalmico i prodotti sono spesso costosissimi per cui molti progetti sono relativi ad apparecchiature composte da strumenti tecnologicamente avanzatissime e quindi anche molto costose.

Il tipo di apparecchiature d'anno è ricercato doveva essere relativo a prodotti composte da un sistema di lenti, da un illuminatore e da una cella di ripresa.

Tutte quelle apparecchiature utilizzate dagli ottici nei loro studi, quelle in cui il capo del paziente viene posizionato su un apposito appoggia il mento, non sono state prese in considerazione se non per motivi culturali generale.

Le tecnologie degli stanno scoppi fondamentalmente si attengono a due metodi differenti e precisamente quelli legati al normale telecamere di ripresa le quali mediante opportune lenti focalizzano la retina, e quelle che utilizzano la tecnologia a scanner per acquisire la stessa.

Come abbiamo già detto nei capitoli precedenti tutti gli oftalmoscopi sono stati concepiti per uso umano a parte alcuni a contatto di usati in campo veterinario.

Page 28: Bioidentià - Il Progetto Ottico

Inizialmente il tentativo d'anno è fatto to quello di cercare di acquisire la retina da una distanza di circa 50 cm.

Tale distanza si dimostrò subito essere qualche cosa di irreale in quanto, come possibile vedere dagli schemi e gli oftalmoscopi reperiti, la visualizzazione della retina può avvenire, in dimensioni utili per poter eseguire un riconoscimento, solo nell'istante in cui la focalizzazione della lente viene eseguita sulla sclera.

Utilizzando questo tipo di focalizzazione diventa una questione di calcolo matematico capire quale potrebbe essere la superficie della retina acquisita.

Si consideriamo una lente che focalizza a 5 cm e si consideriamo che la retina si trova a 2 cm dietro la sclera di fatto mediante un calcolo sui triangoli creati riusciamo ad avere la superficie la quale sarà appunto di circa 2 cm.

Page 29: Bioidentià - Il Progetto Ottico
Page 30: Bioidentià - Il Progetto Ottico

United States Patent Application 20030098952 Kind Code A1 Goldfain, Ervin ;   et al. May 29, 2003

Eye viewing device for large field viewing

Abstract

The invention is a low cost, low input power eye viewing device well suited for viewing wide field retinal images through an undilated pupil. Included in the device are a converging light illumination system and an aperture stop. The converging light illumination system provides ease of entry of light rays into an eye, wide field retinal illumination, reduced glare and reduced power consumption. The aperture stop blocks unwanted received glare light not forming part of the retinal image. The device is made especially well suited for retinal viewing through an undilated pupil if the aperture is sized in accordance with the diameter of an undilated pupil.

Inventors: Goldfain, Ervin; (Syracuse, NY) ; Lagerway, William; (Auburn, NY) ; Roberts, Chris R.; (Skaneateles, NY) ; Slawson, Steven R.; (Camillus, NY) ; Krauter, Allan I.; (Skaneateles, NY)

Correspondence Name and Address:

GARY RITTS P.O. BOX 7651 NORTHRIDGE CA 913277651

Page 31: Bioidentià - Il Progetto Ottico

Assignee Name and Adress:

Welch Allyn, Inc.

Serial No.: 337588Series Code: 10 Filed: January 7, 2003U.S. Current Class: 351/200U.S. Class at Publication: 351/200Intern'l Class: A61B 003/00

United States Patent Application 20030063386 Kind Code A1 Slawson, Steven R. ;   et al. April 3, 2003

Eye viewing device comprising eye cup

Abstract

The invention is a hand-held eye viewing device adapted to be readily positioned in an operative radial displacement, angular orientation and axial standoff position relative to an eye. The eye viewing device includes an eye cup extending from a patient end of the device having a patient end

Page 32: Bioidentià - Il Progetto Ottico

adapted to be received at a patient's eye orbit. An outer diameter of a patient end of the eye cup is sized to correspond to a patient eye orbit such that a viewing axis is substantially centered on patient's pupil when the eye cup is received at an eye orbit. The eye cup is preferably made deformable so that patient comfort is improved and further so that contact of the eye cup with an eye orbit alerts a physician that the device is approaching an operative axial standoff position. The eye cup may also be made so that the device pivots about a pivot point toward a patient end of the eye cup such that the angular orientation of the device can be adjusted without disrupting the device's operative radial displacement and axial standoff positioning. The eye cup further blocks ambient light from impinging on an eye, thereby substantially eliminating a source of external glare. By allowing the device to be stabilized against an eye orbit the eye cup eases the task of maintaining an operative position once an operative position has been achieved.

Inventors: Slawson, Steven R.; (Camillus, NY) ; Roberts, Chris R.; (Skaneateles, NY) ; Krauter, Allan I.; (Skaneateles, NY) ; Goldfain, Ervin; (Syracuse, NY)

Correspondence Name and Address:

George S. Blasiak WALL MARJAMA & BILINSKI 101 South Salina Street, Suite 400 Syracuse NY 13202 US

Assignee Name and Adress:

Welch Allyn, Inc.

Serial No.: 783224Series Code: 09 Filed: February 14, 2001U.S. Current Class: 359/600U.S. Class at Publication: 359/600Intern'l Class: G02B 021/00; G02B 023/16

Page 33: Bioidentià - Il Progetto Ottico

United States Patent Application 20030157464 Kind Code A1 Tanassi, Cesare ;   et al. August 21, 2003

Instrument for eye examination and method

Abstract

The present invention relates to a novel instrument for the examination of an eye, namely the retina. The instrument features a LCD display for projection of various types of patterns and stimuli via an optical system onto the retina. The retina can be visualized by live IR image sequences as well as by visible light still frame images. It combines five examination types within one instrument, namely a perimetry examination, a microperimetry examination, a fixation stability examination, a scotoma boundary detection and psychophysical examinations as well as comparison experiments for comparing the results of two examinations of the above types which have been carried out at different times or with different patients.

Inventors: Tanassi, Cesare; (Pont della Priula (TV), IT) ; Piermarocchi, Dott. Stefano; (Padova, IT) ; Buscemi, Philip M.; (Greensboro, NC)

Correspondence Name and Address:

Walter L. Beavers 326 South Eugene Street Greensboro NC 27401 US

Serial No.: 364869Series Code: 10 Filed: February 11, 2003U.S. Current Class: 434/81U.S. Class at Publication: 434/81Intern'l Class: G09B 011/00

Page 34: Bioidentià - Il Progetto Ottico

United States Patent Application 20030206272 Kind Code A1 Cornsweet, Tom N. ;   et al. November 6, 2003

Ocular fundus auto imager

Abstract

An ocular fundus imager (8) automatically aligns fundus illuminating rays to enter the pupil (P) and to prevent corneal reflections from obscuring the fundus image produced. Focusing the produced fundus image is automatically performed and is based upon the fundus image iself. A head restraint for the patient undergoing examination is in the form of a pair of spectacles which is not only easy to use accurately but significantly reduce the gross alignment between the optical system (8) and the patient's pupil (P). pupil (P).

Inventors: Cornsweet, Tom N.; (Prescott, AZ) ; Buck, Gary F.; (Prescott, AZ)

Page 35: Bioidentià - Il Progetto Ottico

Correspondence Name and Address:

C Robert von Hellens Cahill Von Hellens & Glazer Suite 155 2141 E Highland Avenue Phoenix AZ 85016 US

Serial No.: 311492Series Code: 10 Filed: December 16, 2002PCT Filed: July 6, 2001PCT NO: PCT/US01/21410U.S. Current Class: 351/206U.S. Class at Publication: 351/206Intern'l Class: A61B 003/14

Page 36: Bioidentià - Il Progetto Ottico

Le ipotesi inizialiData la natura dell’occhio ed in particolare del fondo retinale riflettente i problemi legati alla creazione di un illuminatore possono derivare da tre problemi fondamentali.

La poca potenza La troppa potenza La posizione sbagliata La lunghezza d’onda errata

Nelle varie prove fatte è subito apparso il problema.

Nella prima prova ipotizzammo che la luce dovesse essere all’infrarosso e sufficientemente forte per non fare ridurre la pupilla dell’animale e che questa dovesse essere anulare per distribuire meglio la luce.

La pupilla dell’occhio funziona da diaframma per cui

maggiore è la quantità di luce più questa si fa piccola.

Nel caso dei sistemi di ripresa per uso umano vengono spesso utilizzate sostanze atte a dilatare le pupille cosa non fattibile nel caso di mucche o animali in generale.

L’occhio della mucca possiede una pupilla ovale orientata in senso orizzontale, come si può vedere nel disegno precedente.

La prima soluzione a cui pensammo che era legata alla telecamera e al tipo di illuminatore da utilizzare con questa.

Le ipotesi che vennero fatte furono legate alle proprietà dell'occhio che potevano essere viste mediante un'osservazione dall'esterno.

Riuscire a trovare i dati relativi alla fisiologia dell'occhio della mucca era alquanto complicato in quanto l'unico mezzo a disposizione era quello di cercare su Internet sui siti legati alla veterinaria.

Le informazioni a cui mi riferisco sono di fatto, ad esempio, le diottrie del cristallino, le dimensioni della retina, la distanza di questa dietro al cristallino e così Via.

Successivamente alcune informazioni vennero ipotizzate basandosi

Page 37: Bioidentià - Il Progetto Ottico

sui dati relativi alla focalizzazione sulla parte interna e su quella esterna dell'occhio.

Tornando quello che dicevamo prima precedentemente alla prima prova ipotizzammo un'idea su come doveva essere fatta una telecamera adatta alla ripresa del fondo oculare.

Pensando che dovevamo passare attraverso la pupilla il fattore d’ingrandimento doveva essere tale da visualizzare l’occhio grosso come tutta l’immagine.

Per quanto riguarda il sistema di illuminazione ipotesi fatta per quella per cui questo dovrebbe mettere una luce non visibile all'occhio e sufficientemente forte da poter penetrare all'interno di questo.

Ignorando che il fondo retinale riflette il risultato avuto fu il seguente.

La retina al fine di ottimizzare la luce riflette indietro sui ricettori la luce in eccesso.

In altre parole la luce che arriva dalla pupilla batte contro i fotorecettori mentre altri vanno sul fondo il quale li riflette indietro contro a questi ultimi.

Questo motivo è quello che causa gli occhi del gatto che

riflettono la luce che li colpisce.

Anche nel nostro caso l’occhio diventò luminoso impedendo di vedere il fondo.

La luce doveva quindi essere equilibrata in quanto quella in eccesso veniva riflessa.

Un altro dei problemi che vennero subito alla luce era causato dalla natura riflettente del cristallino.

La sorgente di luce veniva riflessa per cui questa creava problemi nell’immagine dell’occhio.

Page 38: Bioidentià - Il Progetto Ottico

A seguito delle prime prove ci informammo maggiormente sulla natura dell’occhio degli animali.

La lente, di cui parleremo dopo, aveva avuto anche si dei problemi in quanto la focalizzazione la faceva sull’esterno dell’occhio e non dietro al cristallino dove di fatto è posizionata la retina.

Di fatto il primo esperimento ci fece capire che non potevamo trattare l’occhio come se fosse un oggetto da fotografare come se fosse un paesaggio.

La pupilla che costituisce l’unico punto di passaggio, le

L’ illuminatore

Page 39: Bioidentià - Il Progetto Ottico

Sin dall'inizio il sistema di illuminazione è sembrato essere critico in quanto la luce, quella destinata ad illuminare la retina, doveva tener conto di quello che era cristallino e quindi della deviazione che questo induceva sul percorso ottico.

Il sistema adatto a descrivere otticamente tale insieme è quello definito con il termine di sistema telecentrico.

L’ossInoltre un altro parametro critico legato alla scelta del tipo di illuminazione era la lunghezza d'onda e la potenza della luce stessa.

In fatti si pensava che la luce visibile potesse di fatto far restringere la pupilla complicando in questo modo il metodo di acquisizione.

L'idea di poter utilizzare una luce all'infrarosso, teoricamente, ci fece pensare che questa di fatto non avrebbe interagito con pupilla.

D'altra parte una luce all'infrarosso di fatto non avrebbe potuto avere una potenza pari ad una lampadina con luce visibile in quanto avrebbe potuto recare danni all'occhio della mucca.

Alcune oftalmoscopiche avevamo in prova presso la nostra società utilizzavano la luce visibile ed inoltre possedevano alcuni filtri colorati che permettevano di cambiare il contrasto relativo all'immagine della retina.

Page 40: Bioidentià - Il Progetto Ottico

Tre oftalmoscopi presi in esame possedevano metodi di illuminazione simile ma non uguali.

Il primo era un oftalmoscopio indiretto costituito da una lente tenute in mano nelle vicinanze dell'occhio e da un illuminatore situato all'interno di un caschetto tenute in testa dall'operatore.

La luce destinata ad illuminare la retina di veniva focalizzato su questa mediante la stessa lente utilizzata per la visione.

L'utilizzo di questo tipo di apparecchio è abbastanza critica in quanto la visione della retina avviene in un punto ed in un punto solo.

Come vedremo successivamente l'idea che ci permise di creare un prototipo utile per l'osservazione della retina provenne da questa apparecchiatura.

Il secondo era costituito da un oftalmoscopio a contatto costituito da un obiettivo di circa 1 cm e mezzo di diametro della cui illuminazione era fornita in modalità simile assiale da un prisma posizionato sulla parte bassa della lente.

Page 41: Bioidentià - Il Progetto Ottico
Page 42: Bioidentià - Il Progetto Ottico
Page 43: Bioidentià - Il Progetto Ottico
Page 44: Bioidentià - Il Progetto Ottico

Il sistema anulare non funziona in quanto considerando che la lente focalizza a 5 CM attraverso un foro di 1 cm circa , considerando queste misure avremmo, senza considerare lo spostamento del fascio ottico del cristallino, un illuminazione che non coprirebbe la parte centrale della retina.

La simulazione dello spostamento del fascio di luce indotto da una lente con fuoco 2 cm dalla parte interna e a 20 cm quella esterna si avrebbe.

Page 45: Bioidentià - Il Progetto Ottico
Page 46: Bioidentià - Il Progetto Ottico
Page 47: Bioidentià - Il Progetto Ottico
Page 48: Bioidentià - Il Progetto Ottico
Page 49: Bioidentià - Il Progetto Ottico
Page 50: Bioidentià - Il Progetto Ottico
Page 51: Bioidentià - Il Progetto Ottico

The Keeler Professional total control at your fingertips

 

Page 52: Bioidentià - Il Progetto Ottico

The New Professional Ophthalmoscope has been designed to ensure ultimate control.Lenses, graticules and filters can all be introduced at the touch of a fingertip. No need to pull away from the patient, the Professional Ophthalmoscope makes routine examination far easier.

Xenon IlluminationWe recognize that illumination is of fundamental importance to good diagnosis. Thats why we have selected Xenon illumination for the new Professional ophthalmoscope.The brighter and whiter longer lasting light will meet any diagnostic challenge. With Xenon you have the power to diagnose even through cloudy media. Because it is longer lasting, that means fewer bulb changes giving greater peace of mind.

Positive Action MaywheelThe positive action easy access maywheel not only allows you to dial up the required lenses quickly it also allows you to know where you are without the need to pull away from the patient.

 

 

 

Swing Over FilterThe red free filter for enhanced vessel examintion can be used in conjunction with any of the 6 diagnostic beams.

Comprehensive Lens RangeThe extensive range of +29D to -25D in a single dioptre steps ensures easy examination of of all ocular structures and covers a wide range of patient/user prescriptions. A quick step swing of +/-20D helps speed up diagnosis.Brow RestThe integral soft brow allows for easy positioning and protects your lenses if you are a spectacle wearer

 

Welch Allyn® PanOptic Ophthalmoscope

IntroductionProduct Overview and DescriptionProduct Use and ProcedureFeatures and BenefitsFrequently Asked QuestionsCustomer TestimonialsTechnical SpecificationsWarrantyOther InformationProduct Ordering Information

Page 53: Bioidentià - Il Progetto Ottico

IntroductionThe Welch Allyn PanOptic™ Ophthalmoscope is a revolutionary new concept for visualizing the fundus.

Developed by Welch Allyn® the originator of the world's first hand-held direct illuminating ophthalmoscope, the PanOptic™ incorporates an innovative and patented new optical design called Axial PointSource™ Optics. This enabling technology makes it easier to enter small pupils and provides a dramatically wider, more panoramic view of the fundus that's 5X larger than ever before achieved with a standard ophthalmoscope in an undilated eye.

Product Overview and DescriptionBy converging the illumination to a point on the cornea, Axial PointSource Optics allows easy entry into even the smallest pupils. It then enables the illumination pathway to diverge to the retina, creating a very wide illuminated area of the fundus. Simultaneously, the unique viewing system allows the practitioner to see the illuminated area on virtually the same axis, creating the widest field of view attainable in undialated ophthalmoscopy. This means the practitioner is actually viewing the fundus through the mirror that directs the the eye, maximizing the alignment of the viewing axis with the illuminated area.

In addition to achieving superior views of the fundus, the PanOptic provides enhanced magnification-26% more than standard scopes-making it easier to see retinal details.

Product Use and ProcedureTo see diagrams, descriptions or a video clip of the PanOptic's use,

Features and BenefitsIllumination system converges the light to a point at the cornea, allowing easy entry into small, undilated pupils. Patented new Axial PointSource™ Optics.The illumination pathway then diverges to the retina, illuminating a very wide area of the fundus.Viewing system enables the operator to view the illuminated area on virtually the same axis, creating the widest field-of-view attainable.Provides a 5-times larger view of the fundus than ever before achieved with a standard ophthalmoscope in an undilated eye.Enables a 25-degree field-of-view vs. the standard 5-degree field-of-view.Increases magnification by 26% over a standard ophthalmoscopePatented Glare Extinguishment System prevents interference from unwanted glare and reflections.New Halogen HPX™ lamp provides bright, white light.Greater working distance improves the comfort of both examiner and patient.Works with all existing Welch Allyn 3.5v power sources (battery handle or wall transformer), saving additional investment.The patient eyecup establishes and maintains proper viewing distance, provides stabilization for the view, is a pivoting point for leverage in panning around the retina, occludes ambient light and helps with orientation.

Page 54: Bioidentià - Il Progetto Ottico

The dynamic focusing wheel adjusts the focus in a continuous, smooth action for more precise control and the optimum view, with a focusing range of -20 to +20 diopters.The aperture dial has micro, small and large spot sizes, a slit aperture and red-free filter. (Cobalt blue filter is available for an additional charge - Welch Allyn Model # 11820).The ergonomic design of the built-in, soft grip handle provides maximum comfort, balance and access to controls.

To see pictures of each feature on the PanOptic, click here to visit the Welch Allyn website.

Frequently Asked QuestionsQ: What is the PanOptic™ Ophthalmoscope?A: Welch Allyn's PanOptic™ Ophthalmoscope is a revolutionary new

concept in ophthalmoscopy. Developed and patented by Welch Allyn, the originator of the world's first hand-held, direct-illuminating ophthalmoscope, the PanOptic™ Scope incorporates an innovative and patented new optical design called Axial PointSource™ Optics. This enabling technology makes it easy to enter small pupils and provides a dramatically wider, more panoramic view of the fundus compared to a standard ophthalmoscope in an undilated eye

Q: What can the PanOptic™ Ophthalmoscope do for me that a standard ophthalmoscope can't?

A: The PanOptic™ Ophthalmoscope makes it easy to enter small pupils and provides a view of the fundus that's five times larger than ever before achieved with a standard ophthalmoscope in an undilated eye. The PanOptic™ Ophthalmoscope enables a 25° field-of-view, making it easier to see the different features of the fundus more efficiently than the standard 5° field-of-view. The scope's design also creates a much greater working distance between the practitioner and the patient, improving the comfort level of both during the exam. The PanOptic™ Scope also delivers a 26% increase in magnification compared to a standard ophthalmoscope, making it easier to see retinal details.

Q: How does the PanOptic™ Scope work?A: The PanOptic™ Opthalmoscope's patented new Axial PointSource

optics converges the illumination to a point at the cornea, allowing easy entry into even the smallest pupils. Then, Axial PointSource Optics enables the illumination pathway to diverge to the retina, creating a very wide illuminated area of the fundus.

Q: I have a 3.5V Power Source already; do I need to buy a specific one to use with my PanOptic?

A: No, the PanOptic is compatible with any standard 3.5v power source including: desk charger handles, convertible battery handles, wall transformers and the new Lithium Ion Power Handle.

Q: What is the focusing range with the PanOptic?A: Available focusing range is -20 to +20 diopters.

Q: What does the eyecup on my PanOptic do and can I reuse it?A: The eyecup establishes and maintains proper viewing distance,

provides image stability, serves as a pivoting point for panning around

Page 55: Bioidentià - Il Progetto Ottico

the retina, helps with orientation and screens our ambient light. eyecup is cleanable and reusable.

Q: What is better about the Halogen HPX Lamp?A: The Halogen HPX lamp provides whiter, brighter light.

Q: Is it difficult to learn how to use PanOptic™ Ophthalmoscope?A: No! Although the PanOptic™ Ophthalmoscope looks different and has

new features, users of standard ophthalmoscopes or even first-time beginners will find it easy to learn and easy to use.

Customer Testimonials To read numerous testimonials on the PanOptic Ophthalmoscope, visit the website.

Technical Specifications Dimensions: 5.12"L x 1.40"W x 3.75"H without eyecup, with eyecup: 1.45"LWeight: .48 lbs. without eyecup, .50 lbs. with eyecup

WarrantyOne-year warranty on the PanOptic Ophthalmoscope.

Other InformationTo view Pathologies such as normal fundus, toxoplasmas, retinal detachment…as seen through a PanOptic click here to visit the Pathologies page on the Welch Allyn website.

Page 56: Bioidentià - Il Progetto Ottico

La fisica dell’ottica

In questa sezione vengono riportati i principi fondamentali della fisica dell'ottica.

Tale riporto allo scopo di indicare le teorie che sono state utilizzate per il calcolo delle parti composte da lenti.Le onde elettromagnetiche sono descritte da componenti costituiti da campi elettrici e magnetici.

Una parte relativamente piccola dello spettro elettromagnetico viene fisicamente percepita dall'occhio come colore.

Normalmente siamo abituati a dare il nome di luce a questa porzione.

Qualsiasi campo elettrico o magnetico può essere misurato.

L'altezza dell'onda va via con il tempo.

La sua propagazione è descritta dalla formula :

La frequenza della luce e la lunghezza corrispondente sono relazionate dalla formula :

nel processo di formazione di un'immagine, capiamo che un punto di luce della sorgente deve essere piazzato in un punto dell'oggetto destinazione.Un'immagine particolarmente buona e quando tutti i raggi di una regione interferiscono in modo costruttivo.Per gli scopi che si prefigge di raggiungere ci interessa avere alcuni nozionismi legati alla teoria delle lenti.Le lenti esistenti sono dei tipi classificati qui a seguito:

Page 57: Bioidentià - Il Progetto Ottico

Nei sistemi ottici vengono generalmente utilizzate lenti rotazionalmente simmetriche.Alcune tipologie di lenti non rotazionalmente simmetriche sono quele cilindriche e quelle toroidali.

Alcune videocamere compatte utilizzano dei sistemi di lenti simmetriche ed asferiche.

Page 58: Bioidentià - Il Progetto Ottico

Utilizzando un sistema per la formazione di un'immagine reale utilizzando una lente singola di piacere per conoscere i parametri più importanti con i quali descrivere il nostro sistema.

Le lenti sono piazzate a certe distanze dal oggetto.

La direzione della propagazione è definita dal oggetto alle lenti.

La regione precedente alle lenti viene definita con il nome di spazio dell'oggetto.

La distanza tra la lente e l'immagine invece viene definita come distanza del immagine a.

La figura precedente ha sufficienti parametri per poter calcolare la maggior parte delle quantità dimensionali più importanti del sistema del immagine come ad esempio.

Page 59: Bioidentià - Il Progetto Ottico

Le seguenti formule servono a caratterizzare le lenti.

Page 60: Bioidentià - Il Progetto Ottico
Page 61: Bioidentià - Il Progetto Ottico

                     La Percezione Visiva

 

L’Ottica Geometrica e i Raggi luminosi

La luce è una radiazione elettromagnetica, cioè una perturbazione periodica dei campi elettrico e magnetico che si propaga nel vuoto e nei mezzi materiali. Da un punto di vista fisico non c’è alcuna differenza tra la luce emessa da una stella, il campo irradiato dall’antenna del nostro telefonino, il calore emanato da una stufa e i raggi X usati per le radiografie; è il nostro occhio che riesce a "captare" la prima ed è insensibile alle altre.

Analogamente a tutti i fenomeni propagativi ondulatori (come i suoni e le vibrazioni, per esempio) un’onda elettromagnetica è caratterizzata da una velocità di propagazione v (dipendente dal mezzo in cui avviene) e da una frequenza n (numero di oscillazioni che si susseguono nell’unità di tempo e di lunghezza; è indipendente dal mezzo); note queste due, si può ricavare la lunghezza d’onda l (la distanza tra due "picchi" vicini), applicando la relazione:

Page 62: Bioidentià - Il Progetto Ottico

 

v = ln

 

Nel vuoto v = c = 3·108 m/s; in tutti gli altri mezzi v è minore di c, notoriamente la massima velocità possibile secondo le leggi della fisica.

L’occhio umano riesce a percepire le lunghezze d’onda da un minimo dell’ordine di l = 0,4 mm (violetto) ad un massimo di l = 0,7 mm (rosso); tale intervallo (o banda) dello spettro elettromagnetico è detto, appunto, luce. L’unità di misura per le lunghezze in ottica è usualmente il micron (1 mm = 10-6 m).

 

Figura 5.1

 

Sarebbe estremamente complicato studiare la luce con le leggi fisiche generalizzate che si applicano a tutti i campi elettromagnetici. Nei casi in cui le lunghezze d’onda in gioco sono molto più piccole dei mezzi materiali con i quali interagiscono, si può adoperare una teoria approssimata, l’ottica geometrica, che si basa sulle proprietà geometriche della luce quando incide su discontinuità dello spazio come, ad esempio, specchi e lenti. Una discontinuità è una regione di spazio riempita con un materiale diverso dall’aria o dal vuoto (vetro, acqua, metallo, ecc..).

Senza aver la minima pretesa di una trattazione esaustiva dell’argomento, introduciamo ora quei pochi concetti fondamentali che ci serviranno per spiegare a grandi linee il funzionamento di lenti, specchi e telescopi (naturalmente...).

Si definisce raggio ottico (o luminoso) la direzione nella quale si propaga una determinata radiazione luminosa che, nei casi che ci interessano, è una linea retta.

Page 63: Bioidentià - Il Progetto Ottico

Ogni mezzo materiale è caratterizzato da un indice di rifrazione n che è inversamente proporzionale alla velocità di propagazione nel mezzo stesso secondo la relazione

 

 

Nel vuoto abbiamo n = 1; per l’aria n è praticamente pari a quello del vuoto; per tutti gli altri mezzi abbiamo n > 1.

 

Indice di rifrazione per alcuni mezzi alle frequenze ottiche

vuoto 1,0000

aria 1,0003

diamante 2,47¸ 2,75

quarzo 1,46

vetro crown 1,51¸ 1,57

vetro flint 1,54¸ 1,75

acqua 1,33

Un raggio ottico che incide su un materiale viene in parte riflesso e in parte rifratto, cioè si propaga all’interno del suddetto materiale secondo una nuova direzione. Per la fondamentale legge di conservazione dell’energia, la somma delle parti riflessa Er e rifratta Ei’ deve essere pari alla quantità di energia incidente Ei :

 

Ei = Er + Ei’

Possiamo, quindi, introdurre due coefficienti r e t, rispettivamente di riflessione e di rifrazione (o di trasmissione), in modo da avere:

Page 64: Bioidentià - Il Progetto Ottico

 

Er = r · Ei Ei’ = t · Ei

 

Sostituendo queste due espressioni nella prima relazione si ottiene:

r + t = 1

 

I coefficienti r e t sono legati alle caratteristiche dei due corpi tramite gli indici di rifrazione n1 e n2 e all’angolo di incidenza qi del raggio (vedi figg. 5.2a e 5.2b).

I mezzi trasparenti (come il vetro) sono caratterizzati da un alto coefficiente di rifrazione t e, di conseguenza, da un basso coefficiente di riflessione r; al contrario, i mezzi riflettenti (come gli specchi) sono caratterizzati da un alto coefficiente di riflessione r e un basso coefficiente di rifrazione t.

La riflessione della luce da parte di un corpo riflettente (specchio) è un fenomeno indipendente dalla frequenza della radiazione incidente, mentre la rifrazione attuata da una lente dipende da essa. L’indice di rifrazione, infatti, è funzione della frequenza ed è maggiore per la parte bassa dello spettro (rosso) e minore per la parte alta (violetto); tale fenomeno è detto dispersione e tutti i corpi trasparenti sono dispersivi nella banda ottica.

Per il raggio luminoso che incontra la superficie di discontinuità tra due mezzi di propagazione, valgono le seguenti proprietà fondamentali (vedi fig. 5.2a):

 

i raggi incidente, riflesso e rifratto e la perpendicolare alla superficie di discontinuità nel punto in cui arriva il raggio incidente, giacciono sullo stesso piano, detto piano di incidenza;

 

l’angolo di incidenza qi e l’angolo di riflessione qi’ sono uguali e giacciono da parti opposte rispetto alla perpendicolare alla superficie di discontinuità;

 

Page 65: Bioidentià - Il Progetto Ottico

- l’angolo di incidenza qi e l’angolo di rifrazione qr giacciono da parti opposte rispetto alla perpendicolare alla superficie di separazione tra i due mezzi e sono legati dalla legge di Snell:

 

n1 ·sen qi= n2·sen qr

 

 

Figura 5.2a

 

Quest’ultima relazione, importantissima per lo studio e la costruzione dei dispositivi ottici, deriva dal famoso principio di Fermat, un postulato che il geniale matematico francese Pierre de Fermat (1601-1665) pose alla base di ogni fenomeno ottico. Tale principio stabilisce che tra tutti i possibili percorsi ottici tra A e B (vedi fig. 5.2b), quello che fisicamente si realizza è quello minimo, cioè quello che richiede il minor tempo possibile. Il volenteroso lettore può provare a ricavare la legge di Snell tramite questo postulato, impostando geometricamente un problema di minimo.

 

Page 66: Bioidentià - Il Progetto Ottico

Figura 5.2b

 

A partire dal principio di Fermat e con le assunzioni da noi fatte sulle proprietà dei raggi luminosi, possiamo ricavare le equazioni che ci descrivono il comportamento dei raggi ottici quando incidono su discontinuità non piane come specchi e lenti. Questo è possibile perché si suppone che la superficie concava o convessa sia piana in prossimità del punto di incidenza. Inoltre, tutti i dispositivi ottici (come i telescopi) sono sistemi centrati, in cui le lenti o gli specchi che li compongono sono costituite da superficie simmetriche di rotazione con tutti i rispettivi assi centrati sulla stessa retta (asse ottico); è possibile, quindi, studiare il sistema ottico sul piano, lungo una qualsiasi sezione contenente l’asse ottico.

Senza ricorrere ad alcuna equazione, si può descrivere il dispositivo ottico tramite procedimenti grafici, tracciando direttamente alcuni fondamentali raggi luminosi che godono di ben determinate proprietà, alcune delle quali saranno esposte nei paragrafi che seguono.

 

 

5.2 Le Lenti e Gli Specchi

Le lenti sono costituite da una porzione di materiale trasparente (nei telescopi si adoperano particolari tipi di vetro) delimitato tra due superficie sferiche. Una lente può essere convergente o divergente, a seconda della concavità o della convessità di ognuna delle due superficie e in rapporto ai rispettivi raggi di curvatura.

Una lente è convergente quando tutti i raggi paralleli all’asse ottico che incidono su di essa fuoriescono convergenti in un unico

Page 67: Bioidentià - Il Progetto Ottico

punto F detto fuoco situato sull’asse ottico dalla parte opposta alla sorgente a distanza f dal centro della lente (vedi fig. 5.3a). In una lente divergente i raggi fuoriescono, ovviamente, divergenti, come se tutti provenissero da un punto F’ detto fuoco virtuale, situato tra la sorgente e la lente, a distanza f da quest’ultima; in altre parole sono gli immaginari prolungamenti dei raggi a convergere in F’. In entrambi i casi f è detta focale o distanza focale della lente (vedi fig. 5.3b).

Una lente centrata e simmetrica ha le medesime proprietà, indipendentemente dalla parte in cui è situata la sorgente: possiede, quindi, un solo centro e due fuochi situati alla medesima distanza da esso. Ci sono particolari tipi di lenti convergenti e divergenti, dette a menisco, in cui le due superficie che le delimitano hanno curvature diverse; di conseguenza i fuochi saranno situati a due diverse distanze dal centro.

Le lenti godono di tre importanti proprietà che ci permettono, come dicevamo prima, di studiarne il comportamento senza bisogno di fare alcun calcolo. In questo modo si può costruire la cosiddetta immagine (reale o virtuale) di una sorgente puntiforme o estesa "vista" attraverso una lente.

 

 

Figura 5.3a

 

 

Page 68: Bioidentià - Il Progetto Ottico

Figura 5.3b

 

 

 

I raggi ottici paralleli all’asse della lente convergono, realmente o virtualmente, in un unico punto detto fuoco che è situato dalla parte opposta (lenti convergenti), ovvero dalla stessa parte (lenti divergenti) rispetto alla sorgente.

 

I raggi ottici passanti per il centro della lente la attraversano senza essere deviati.

 

I raggi ottici, o i relativi prolungamenti virtuali, passanti per il fuoco, fuoriescono paralleli all’asse ottico.

 

Nelle due figure 5.4a e 5.4b, vediamo applicate queste tre regole per costruire graficamente l’immagine di una sorgente estesa. Nel primo caso (fig. 5.4a), l’oggetto è posto ad una distanza superiore rispetto alla focale: si vede che i raggi ottici convergono dall’altra parte e ci restituiscono un’immagine reale (potremmo proiettarla su uno schermo, ad esempio, oppure sfruttarla come sorgente per una seconda lente). Nel secondo caso (fig. 5.4b), l’oggetto è posto tra il fuoco e il centro della lente: i prolungamenti virtuali dei raggi si incontrano dietro la sorgente reale, dandoci in prossimità del secondo fuoco un’immagine ingrandita di essa che, essendo virtuale, può essere soltanto osservata dal nostro occhio ma non può essere proiettata su uno schermo, né usata come sorgente per una seconda lente.

 

 

 

Page 69: Bioidentià - Il Progetto Ottico

 

Figura 5.4a

 

Figura 5.4b

 

Gli specchi sono costituiti da un supporto di vetro ricoperto da un sottile ed uniforme strato di materiale riflettente, di solito platino, argento o alluminio. Le forme degli specchi che si usano nei telescopi astronomici sono piana, sferica, parabolica o iperbolica. La lavorazione di tali dispositivi deve avere un alto grado di accuratezza, al fine di assicurare un’elevatissima qualità degli strumenti ottici in cui sono adoperati.

Uno specchio ben costruito riflette la quasi totalità della radiazione incidente su di esso e non ha comportamenti dispersivi, ovverosia le sue proprietà non dipendono dalla frequenza.

Esaminiamo brevemente le proprietà degli specchi parabolici e sferici (vedi fig. 5.5). Uno specchio parabolico ha la proprietà di concentrare i raggi luminosi che incidono parallelamente all’asse ottico in un punto F (fuoco) dell’asse stesso situato ad una distanza f (focale) dal vertice del paraboloide. In uno specchio sferico, invece, i raggi ottici che incidono parallelamente all’asse non convergono in un unico punto, ma si distribuiscono in prossimità del centro della sfera generatrice su una superficie detta caustica.

 

 

Page 70: Bioidentià - Il Progetto Ottico

 

Figura 5.5

 

Entrambi questi specchi si adoperano nei telescopi riflettori (vedi §5.6); quello parabolico è più preciso, ma di più costosa lavorazione, mentre quello sferico necessita di dispositivi di correzione (vedi §5.5), ma il suo costo inferiore ne consente l’utilizzo anche in strumenti di fascia economica (e alla portata delle tasche degli astrofili...).

Per avere un’idea della precisione che ci vuole nella lavorazione delle superficie riflettenti dei telescopi, è interessante sapere che uno specchio "fuori misura" come il parabolico di 5 metri del telescopio Hale di Monte Palomar in California (inaugurato nel l948) è stato ottenuto a partire da uno sferico di 34 m di curvatura dopo molti anni di rifinitura visto che la differenza tra superficie sferica e parabolica era dell’ordine del decimo di millimetro e la precisione richiesta inferiore al decimillesimo di millimetro!

 

 

5.3 Il Cannocchiale

Il primo cannocchiale dovrebbe essere stato costruito da un ottico fiammingo all’inizio del XVII secolo. Galileo, avuta notizia dell’invenzione, ne produsse uno proprio, perfezionandolo in seguito, e lo rivolse subito al cielo, facendo le sue importantissime scoperte. Keplero ne migliorò ancora le prestazioni sostituendo con una lente convessa quella concava dell’oculare (vedi più avanti) di Galileo.

 

Page 71: Bioidentià - Il Progetto Ottico

 

Figura 5.6a

 

In figura 5.6a è riportato lo schema di un semplice cannocchiale; abbiamo un sistema centrato di due lenti convergenti, una detta obbiettivo e rivolta verso la sorgente, un’altra detta oculare, rivolta verso l’occhio dell’osservatore e con la possibilità di traslare lungo l’asse ottico del sistema. Nella figura l’oggetto da osservare è situato a distanza finita e molto maggiore della focale dell’obbiettivo (nel disegno la scala non è stata rispettata per ragioni di praticità); l’oculare viene posto in modo che l’immagine A’B’ della sorgente AB cada in prossimità del suo fuoco e agisce, in questo modo, come una lente di ingrandimento, dandoci un’immagine A"B" virtuale ingrandita e capovolta di AB (vedi §5.2). Il rapporto tra le dimensioni di A"B" e AB è detto ingrandimento lineare.

Le sorgenti astronomiche sono poste a distanza praticamente infinita dall’obbiettivo (vedi fig. 5.6b), quindi la funzione del cannocchiale è quella di ingrandire gli angoli sotto i quali sono visti gli oggetti celesti, migliorando l’acuità visuale dell’occhio nudo (vedi §5.10). L’oculare (di focale f) viene posto in modo che il suo fuoco coincida con quello dell’obbiettivo (di focale f’) Il rapporto a’ / a è detto ingrandimento angolare e si può dimostrare sfruttando la sola geometria piana che

 

 

essendo y e y’ rispettivamente le dimensioni trasversali di un fascio di raggi luminosi uscenti dall’obbiettivo e dall’oculare.

 

 

Page 72: Bioidentià - Il Progetto Ottico

Figura 5.6b

 

Un cannocchiale di questo tipo è inadatto all’osservazione terrestre perché l’immagine osservata è capovolta; con l’inserzione di una terza lente tra le prime due si può raddrizzare l’immagine, a scapito della sua qualità perché ogni lente introduce alcuni difetti (vedi §5.5); per l’uso astronomico l’inversione dei riferimenti non crea eccessivi problemi, quindi non si usano dispositivi raddrizzatori.

Numerosi miglioramenti sono stati fatti al "primitivo" cannocchiale che noi abbiamo esaminato, fino ad arrivare al monumentale rifrattore di Yerkes (Wisconsin, USA), con un obbiettivo di 102 cm di diametro...

Una lente, inoltre, assorbe una considerevole parte della radiazione luminosa incidente e questo degenera le prestazioni dei telescopi rifrattori al crescere del diametro e dello spessore delle lenti (vedi nota 4). Gli specchi che si usano negli strumenti ottici, al contrario, riflettono almeno il 90% della radiazione incidente e non sono dispersivi; per questo motivo i telescopi di qualità sono tutti riflettori (vedi §5.6).

L’Occhio Umano

Prima di tutto è opportuno dare una descrizione sommaria del funzionamento del "sensore" della percezione visiva, cioè l’occhio umano, le parti principali del quale sono rappresentate in figura 5.8.

La superficie esterna anteriore dell’occhio è ricoperta da una membrana trasparente, detta cornea, che, insieme al cristallino, una vera e propria "lente", focalizza un’immagine reale e capovolta degli oggetti sulla rètina, una membrana sensibile interna all’occhio. La luce che incide sulla retina viene convertita in segnali elettrici. Attraverso il nervo ottico, questi vengono condotti al cervello che provvede ad elaborarli e a generare la sensazione visiva.

La retina è costituita da uno strato di 0,2 mm di due tipi di cellule diverse: i coni e i bastoncelli, in totale 125 milioni di

Page 73: Bioidentià - Il Progetto Ottico

elementi. I bastoncelli sono sensibili all’intensità luminosa, i coni al colore. In situazioni di bassa luminosità (luce crepuscolare) i coni non sono eccitati ed è per questo che in tali condizioni vediamo "in bianco e nero". Siamo nella tipica situazione in cui ci si trova durante un’osservazione astronomica; solo delle stelle più luminose possiamo percepire il colore, mentre tutte le altre, come pure le sgargianti nebulose (nelle foto delle riviste specializzate...) che puntiamo col nostro telescopio, ci appaiono di un bianco un po’ sbiadito.

 

 

 

Figura 5.8

 

Di coni ce ne sono di tre tipi sensibili a tre colori fondamentali: il rosso, il verde e il blu. Essi, inoltre, sono circa un quarto in numero rispetto ai bastoncelli; ciò significa che il nostro occhio ha maggiore potere risolutivo per punti luminosi piuttosto che per punti colorati. Infatti, a meno di variazioni individuali, possiamo distinguere due punti luminosi su sfondo scuro che formano con la pupilla un angolo di un primo d’arco (due punti separati da 1 mm visti dalla distanza di 3,44 m), ma se i due punti fossero di diverso colore, non saremmo in grado di apprezzare anche la differenza cromatica se non raddoppiando (almeno) la distanza fra di essi.

I coni sono più concentrati al centro della retina (macchia lutea), i bastoncelli predominano all’esterno; per questo motivo, per aumentare l’acuità visuale e la sensibilità quando si osserva col telescopio, si consiglia di tenere l’occhio obliquo, affinché l’immagine si proietti in una zona della retina ricca di bastoncelli.

Page 74: Bioidentià - Il Progetto Ottico

L’occhio comprende anche un diaframma opaco, detto iride, che regola le dimensioni dell’apertura (la pupilla) attraverso la quale la luce entra: un’azione muscolare riflessa provvede a restringerla se l’intensità luminosa è troppo elevata e ad allargarla se è bassa. Il diametro della pupilla può variare tra un minimo di poco più di 1 mm (luce forte) e un massimo di circa 6 mm (al buio).

Anche la curvatura del cristallino può essere regolata tramite un’azione muscolare. In questo modo, l’occhio è in grado di mettere a fuoco oggetti posti a varie distanze da esso: una persona dotata di vista normale può focalizzare oggetti tra l’infinito e la distanza minima di visione distinta, il cui valore è di circa 20÷25 cm. Il processo di messa a fuoco è detto accomodamento.

La sensazione visiva è il risultato dell’elaborazione da parte dell’occhio stesso e del cervello delle due immagini focalizzate sulle retine dei due occhi. Si è scoperto, infatti, che i segnali elettrici provenienti dai 125 milioni di cellule sensibili della retina vengono affasciati in un numero molto minore di terminazioni nervose che costituiscono il nervo ottico; quest’ultimo porterà al cervello il risultato di questa prima elaborazione, il quale provvederà a darci la sensazione visiva.

Gli occhi possono presentare difetti che pregiudicano la corretta visione. Tra questi, i più comuni sono le ametropie, la presbiopia e l’astigmatismo.

Le ametropie sono connesse ad una deformazione dell’occhio lungo il suo asse longitudinale (vedi fig. 5.9). Nella miopia, l’immagine di un oggetto lontano, da cui provengono quindi raggi luminosi pressoché paralleli, viene a formarsi su un piano anteriore a quello retinico e l’oggetto viene visto sfocato; se, invece, l’oggetto si trova a distanza ravvicinata, esso può ancora essere visto distintamente. La miopia si corregge utilizzando lenti divergenti.

Nell’ipermetropia accade esattamente l’opposto: l’immagine si forma posteriormente alla retina e perciò sono gli oggetti vicini ad apparire sfocati. L’ipermetropia si corregge attraverso lenti convergenti.

La presbiopia è una progressiva perdita di elasticità del cristallino che riduce la capacità di accomodamento dell’occhio e, di conseguenza, fa aumentare la distanza minima di visione distinta. La presbiopia si instaura lentamente anche nell’occhio normale a partire dai 40-45 anni, ed è più avvertita dagli ipermetropi (che, come detto, hanno già problemi a vedere da vicino) che non dai miopi. Anche la presbiopia si corregge con lenti convergenti.

Page 75: Bioidentià - Il Progetto Ottico

L’astigmatismo è un’anomalia della curvatura della cornea la quale, da sferica, tende a diventare cilindrica: i raggi luminosi, allora, non sono più focalizzati in un punto ma lungo un determinato asse e l’oggetto viene visto sfocato indipendentemente dalla distanza a cui si trova. L’astigmatismo si corregge con lenti cilindriche.

In ogni caso, mai usare gli occhiali quando si osserva dall’oculare di un telescopio; tramite l’apposita manopola si può adattare la messa a fuoco al proprio occhio correggendo miopia e ipermetropia. Usare gli occhiali, oltre che rendere difficoltosa l’osservazione, può rigare la superficie antiriflesso dell’oculare, come pure le parti dure di quest’ultimo possono graffiare i vostri occhiali!

 

 

 

Figura 5.9

 

 

 

 

Generalità sulla Sensazione Visiva

La sensazione visiva è un fenomeno assai complesso che comporta informazioni di diversa natura. Tra di esse distinguiamo:

Page 76: Bioidentià - Il Progetto Ottico

 

1) informazione spazio-temporale: conformazione degli oggetti nel campo visivo, loro estensione, posizione e movimenti.

2) informazione luminosa e cromatica: intensità della sensazione di luminosità o brillantezza degli oggetti e loro caratteristiche cromatiche.

 

Nei limiti di queste dispense, ci interessa dare qualche elemento sulle informazioni del secondo tipo, studiate dalla fotometria e dalla colorimetria che costituiscono due branche della fisica tecnica.

Una caratteristica fondamentale della visione è che la sensazione di luminosità di un oggetto, sia esso una sorgente (una lampadina, una stella), o un corpo da essa illuminato (un dipinto, una parete), non è proporzionale alla potenza fisica emessa o riflessa dall’oggetto. Per potenza fisica W intendiamo l’intensità del campo elettromagnetico che costituisce i raggi luminosi (vedi § 5.1).

Il nostro occhio è più sensibile alla luce monocromatica giallo-verde di lunghezza 0,55 mm. Radiazioni monocromatiche di lunghezza maggiore (verso il rosso fino a 0,77 mm) o minore (verso il blu fino a 0,38 mm) vengono percepite sempre meno intensamente secondo una curva ricavata sperimentalmente (vedi fig. 5.10) e definita curva normale di visibilità V(l).

Tramite questa curva possiamo definire il flusso luminoso di una radiazione monocromatica

 

F = V(l) · W

 

che rappresenta una misura equivalente dello stimolo percepito; uguale flusso luminoso significa uguale sensazione di luminosità, essendo diverse, per quanto detto sopra, le potenze luminose W che danno tali sensazioni. Il flusso luminoso costituisce una grandezza psicofisica che lega, cioè, una grandezza fisica come la potenza ad una psichica come la visibilità. In figura 5.10 è rappresentato il grafico del coefficiente di visibilità v(l), ottenuto dividendo V(l) per il valore massimo Vmax che la curva raggiunge in corrispondenza della radiazione a 0,55 mm.

Altra grandezza psicofisica è l’intensità luminosa che rappresenta il flusso emesso in un angolo solido unitario; si misura in

Page 77: Bioidentià - Il Progetto Ottico

candele (cd) e costituisce l’unità di misura primaria della fotometria; la candela è inserita nel Sistema Internazionale (SI) delle unità di misura.

La magnitudine di un corpo celeste è basata proprio sull’intensità luminosa della radiazione dell’astro in questione.

Altre caratteristiche fotometriche della visione che influenzano l’osservazione astronomica sono l’acuità visuale, la soglia di visibilità e l’abbagliamento.

L’acuità visuale rappresenta la capacità di distinguere punti vicini (una stella doppia, per esempio); in condizioni ottimali è pari a 1’ d’arco.

La soglia di visibilità rappresenta la minima intensità luminosa percepibile.

Uno strumento ottico come il telescopio è in grado di aumentare sia l’acuità che la soglia proprie dell’occhio umano.

L’abbagliamento è la momentanea riduzione delle facoltà visive provocata dalla presenza nel campo visivo di un oggetto molto brillante rispetto agli altri circostanti.

 

 

Figura 5.10

 Questi parametri non sono assoluti; la visione è una sensazione "con memoria", ovvero è fortemente influenzata da ciò che si è osservato in precedenza. Il nostro cervello è in grado di adattare la percezione all’intensità globale dello stimolo. Se la

Page 78: Bioidentià - Il Progetto Ottico

luminosità media degli oggetti nel campo visivo è elevata, la soglia di visibilità tende a salire, mentre se è bassa, la soglia tende a scendere. Questo adattamento non è istantaneo, ma richiede un certo numero di minuti che dipende dalla differenza tra i due stimoli medi.

Quando si arriva sul campo di osservazione essendo prima passati per luoghi illuminati, si ha una ridotta percezione del cielo stellato; occorre aspettare al buio un po’ di tempo per permettere al cervello di adattarsi alle nuove condizioni di luminosità. Se il cambiamento è troppo repentino, si ha un abbagliamento momentaneo; è come quando si esce da un luogo buio verso uno spazio assolato, o quando qualcuno accende improvvisamente una luce nella nostra camera buia appena ci siamo svegliati...

Per questo motivo, durante le osservazioni astronomiche bisogna evitare di accendere luci di qualsiasi tipo; anche una semplice torcia elettrica può disturbare la visione per vari minuti.

La percezione dell’intensità luminosa è, inoltre, legata al contrasto presente nel campo visivo; le macchie solari ci appaiono quasi nere perché molto meno luminose del resto del disco solare, ma prese singolarmente sarebbero anch’esse molto brillanti, così come ad occhio nudo vediamo scuri i "mari" della Luna perché contrastati dalle altre zone della superficie più riflettenti, mentre isolati nel campo del nostro oculare gli stessi si rivelano molto più chiari.

Diamo ora qualche breve cenno di colorimetria. Oltre all’intensità, infatti, abbiamo altri due attributi della sensazione visiva legati alla percezione del colore: il tono (o tinta) e la saturazione.

Il tono si riferisce al colore base con cui classifichiamo la sensazione luminosa: rosso, verde, blu, giallo, ecc...

La saturazione si riferisce alla purezza del colore; possiamo avere un rosso più o meno vivo o sbiadito. Colori a bassa saturazione tendono al grigio, perdendo così l’attributo cromatico della sensazione. Il grigio, infatti, non è un colore, ma una sensazione di sola luminosità più o meno intensa.

Le radiazioni monocromatiche vengono percepite come colori puri (o saturi): i cosiddetti colori spettrali. Le radiazioni composte da onde di lunghezza diversa, come sono le tipiche sorgenti che illuminano il nostro campo visivo (luce del sole, lampadine, ecc.), sono percepite come colore più o meno saturo che rappresenta la sensazione risultante dalla combinazione di una radiazione di spettro continuo.

Luci di differenti caratteristiche cromatiche si possono sommare tra di loro per ottenere un terzo colore. Le regole sperimentali

Page 79: Bioidentià - Il Progetto Ottico

che definiscono l’additività dei vari colori sono le leggi di Grassmann. E’ grazie a tale principio che funzionano la televisione, il cinema, la fotografia e la stampa. Da tre sorgenti fondamentali, il rosso, il verde e il blu, si riescono ad ottenere, per additività, quasi tutti i colori normalmente visibili.

Se ricordiamo quanto detto nel §5.9, nel nostro occhio vi sono tre tipi di recettori (coni) per tre diverse bande luminose fondamentali: rosso, verde e blu; ognuno viene stimolato in modo differente a seconda dell’intensità della gamma cromatica a cui esso è sensibile. La sensazione risultante dall’elaborazione da parte del sistema nervoso dei tre diversi stimoli è il colore, che è una nostra percezione e non una proprietà fisica della radiazione luminosa. La sensazione del colore verde, per esempio, può essere data da una radiazione pura (monocromatica) a 0,5 mm, oppure da una radiazione costituita da onde nella banda del giallo insieme ad onde della banda del blu (vedi fig. 5.1). Nel primo caso "verde" è un attributo convenzionalmente dato ad una radiazione in un ben determinato campo spettrale, nel secondo caso è una caratteristica della sensazione visiva.

L’ 'ottica studia tutti quei fenomeni relativi alla visione e di conseguenza riguarda le proprietà della luce e degli strumenti ottici, cioè quegli strumenti in grado di alterare le immagini.

La luce è elemento fondamentale, indispensabile alla vita sulla terra. è naturale allora che l'interesse verso di essa e verso i fenomeni ad essa legati si manifestasse fin dall'antichità. Ma come spesso è accaduto nello studio dei fenomeni naturali in tempi remoti, l'osservazione propriamente scientifica si è confusa con congetture di carattere filosofico, e ciò ha ostacolato la giusta impostazione del problema. Si pensi ad esempio che filosofi e scienziati greci, seguaci di Pitagora, sostenevano che la visione degli oggetti dipendesse esclusivamente dal soggetto, grazie ad un fuoco che uscendo dagli occhi si posa sulle cose rendendole visibili.

è chiaro che una tale concezione cade in contraddizione di fronte a fenomeni molto semplici e comuni, quali il fatto che al buio non è possibile vedere. Molti illustri personaggi si cimentarono nel tentativo di dare una spiegazione al fenomeno della visione delle cose, fra gli altri Lucrezio, il quale osservò che avvicinando ad uno schermo bianco un oggetto vivamente colorato e fortemente illuminato, sullo schermo appaiono dei bagliori del colore dell'oggetto. Ne concludeva allora che ogni corpo emette delle Scorze che raggiungono l'occhio provocando la visione. Nessuno era però in grado di stabilire come tali scorze viaggiassero da un corpo all'altro e di che natura fossero, visto che erano in grado di attraversare oggetti trasparenti, contraddicendo il principio di impenetrabilità dei corpi.

Page 80: Bioidentià - Il Progetto Ottico

Fu solo nel 1600 che si riuscì a dare una impostazione corretta al problema, stabilendo che l'immagine da noi percepita si forma all'interno dell'occhio e non all'esterno, ed è provocata dall'interazione della luce, proveniente dalle diverse sorgenti luminose, con gli oggetti. Automaticamente il problema si spostava alla ricerca della natura della luce e del suo comportamento nell'interazione con gli altri elementi. Si apriva così uno dei capitoli più affascinanti dello sviluppo del pensiero scientifico, che avrebbe coinvolto le più grandi menti della fisica moderna, spesso impegnate in diatribe dai toni aspri, talvolta sconcertate e disorientate di fronte a fenomeni che apparivano contraddittori.

A posteriori sappiamo che tali difficoltà erano dovute ai limiti del modello classico della fisica, correttamente interpretati solo agli inizi di questo secolo con l'introduzione della fisica quantistica.

Lo studio dei fenomeni ottici si sviluppò in due direzioni: da un lato la ricerca di un modello matematico in grado di descrivere con buona approssimazione il comportamento della luce nei fenomeni osservabili, dall'altro la formulazione di teorie sulla natura della luce compatibili con il modello sperimentale di comportamento.

Lo studio condotto nella prima direzione portò alla scoperta delle leggi che regolano i fenomeni di RIFLESSIONE e RIFRAZIONE della luce e dei princpi di funzionamento dei vari tipi di specchi e di lenti. Quello condotto nella seconda direzione si dibattè a lungo in una disputa fra la teoria Corpuscolare, proposta da Newton e la teoria Ondulatoria, il cui principale fautore fu Huygens. Accenniamo brevemente a queste due teorie evidenziando, man mano che saranno presentate, come furono interpretati i diversi fenomeni nell'ambito di esse.

La teoria ondulatoria

La teoria ondulatoria trovò le sue basi nell'osservazione del fatto che la luce può attraversare un corpo trasparente senza interagire con le molecole che lo compongono. Inoltre, se due fasci di luce si intersecano, non modificano la loro direzione, e ciò a prova del fatto che la propagazione luminosa non comporta trasporto di materia. Pertanto, Huygens postulò che la luce, in analogia a quanto accade per il suono, si trasmette per mezzo di onde.

Scrive Huygens nel suo trattato della luce del 1690:

"... Quando si consideri l'estrema velocità con cui la luce si propaga tutt'intorno, e che quando essa proviene da differenti sorgenti, anche del tutto opposte, la luce dell'una traversa quella dell'altra senza alcun perturbamento, si comprende bene che quando vediamo un soggetto luminoso, ciò non sarà dovuto a

Page 81: Bioidentià - Il Progetto Ottico

trasporto di materia che dall'oggetto luminoso viene fino a noi, nella maniera che una palla e una freccia traversa l'aria. è dunque in altra maniera che essa si propaga, e quel che può condurci a comprenderla è la conoscenza che abbiamo della propagazione del suono nell'aria....".

La teoria corpuscolare

La maggiore difficoltà incontrata per l'accettazione della teoria ondulatoria è dovuta al fatto che le onde allora note avevano bisogno di un supporto di materia per potersi propagare, infatti il suono non si propaga nel vuoto. La luce invece viaggia dal sole fino a noi attraversando spazi privi di materia; inoltre se la luce si diffondesse mediante onde sferiche dovrebbe formare delle ombre confuse e non ben delineate come invece accade, segno che la propagazione della luce avviene lungo delle rette.

Huygens tentò di dare una spiegazione alla prima obiezione immaginando l'esistenza dell' Etere come mezzo di supporto alla propagazione postulando l'esistenza di una sostanza estremanente fluida e rarefatta tanto da non condizionare minimamente il moto dei corpi nello spazio, ma con straordinarie capacità di elasticità; ciò per giustificare l'elevata velocità con cui si trasmettono i segnali luminosi.

Secondo Huygens allora la luce era prodotta dalla vibrazione delle molecole dei corpi resi incandescenti.

Tali vibrazioni si trasmettono all'etere, che avrebbe dovuto permeare tutto l'universo, giungendo fino all'osservatore.

Scrive ancora Huygens:

"...... Il movimento della luce deve avere origine da ciascun punto dell'oggetto luminoso, perchè possa far percepire tutte le diverse parti dell'oggetto stesso. E io credo che in questo movimento trovi la sua migliore spiegazione supponendo che i corpi luminosi allo stato fluido, come la fiamma e apparentemente il Sole e le Stelle, composti di particelle che si muovono in una materia molto più sottile, che le agita con grande rapidità e le fa urtare contro le particelle dell'etere, che le circondano e che sono in molto minor numero di esse, e che nei corpi solidi come il carbone o un metallo arroventato al fuoco, questo movimento è causato da violento scuotimento delle particelle del metallo e del legno, delle quali, quelle che sono alla superficie urtano egualmente la materia eterea.

...... Mostrerò qui in qual modo io concepisco che avvenga la propagazione di movimento della luce. Prendendo un gran numero di palle di egual grandezza e di materia durissima e disponendole in linea retta e a contatto l'una con l'altra si trova che, urtando con una palla identica contro la prima, il movimento si trasmette

Page 82: Bioidentià - Il Progetto Ottico

rapidamente fino all'ultima, la quale si separa dal rango e non ci accorgiamo che le altre si siano mosse .....

Ora per applicare questa specie di movimento a quello che produce la luce, niente ci impedisce di supporre le particelle di etere costituito di materia che si avvicina alla durezza perfetta e di una elasticità tanto pronta quanto vogliamo ......"

Furono in molti però a rifiutare l'idea dell'esistenza dell'etere, poichè non esistevano prove sperimentali a conferma di questa congettura. Primo fra tutti Newton, il quale al riguardo scriveva nel suo trattato di Ottica del 1704:

``Per spiegare i moti regolari e perpetui dei pianeti e delle comete, è necessario svuotare i cieli da tutta la materia, ....., ed anche da questo mezzo etereo eccezionalmente rarefatto, ......., che non è di nessuna utilità ed ostacola le operazioni della natura; inoltre non vi è alcuna prova inconfutabile della sua esistenza, la quale perciò dovrebbe essere rifiutata.

E se si rifiuta questa esistenza, anche le ipotesi secondo le quali la luce consiste in un moto che si propaga attraverso tale mezzo vanno rigettate con esso.''

L'autorità e la grande considerazione di cui Newton godeva fece propendere la maggior parte degli studiosi dell'epoca verso la teoria corpuscolare sulla natura della luce, secondo la quale essa è composta da uno sciame di particelle di dimensioni infinitesime, soggette anch'esse alle leggi di gravitazione.

Rimanevano però aperti i gravi problemi già accennati insiti in tale teoria, e di conseguenza rimaneva aperto lo scontro dialettico fra l'una e l'altra ipotesi che doveva concludersi, come vedremo, con il trionfo del modello ondulatorio della luce e successivamente con il recupero di alcuni concetti espressi nella teoria corpuscolare, all'interno della fisica quantistica e con l'introduzione del concetto di Fotone.

La propagazione rettilinea della luce: la formazione delle ombre ed il modello del "fronte di onda" di Huygens

Abbiamo accennato, in precedenza, al fatto che il modello ondulatorio della luce fosse da taluni considerato in contrasto con la propagazione rettilinea della luce in qualunque mezzo trasparente ed omogeneo.

L' osservazione sperimentale di questo fenomeno (la propagazione rettilinea della luce) è molto semplice e certamente ognuno avrà avuto modo di osservarlo, ad esempio esaminando la luce che filtra dalle imposte e la formazione delle ombre.

Page 83: Bioidentià - Il Progetto Ottico

Vediamo brevemente le caratteristiche di tale fenomeno.

Una sorgente luminosa può essere Puntiforme o Estesa. Da essa partono i fasci di raggi di luce, che possono essere intercettati da un corpo. Se esso arresta completamente il cammino della luce si dirà Opaco, altrimenti sarà detto Trasparente.

Solitamente una sorgente luminosa qualsiasi emette un fascio di raggi divergenti, cioè essi costituiranno un cono di luce come in figura (3.1).

Si possono ottenere in laboratorio, utilizzando filtri e lenti anche dei fasci di luce paralleli o cilindrici e convergenti (fig. (3.2)).

Supponiamo di proiettare come in figura (3.3) su uno schermo la luce proveniente da una sorgente approssimativamente puntiforme.

Se ora intercettiamo il fascio di luce con un corpo opaco, vedremo prodursi sullo schermo una macchia scura, l'ombra dell'oggetto, dai contorni ben delineati. Tale figura costituisce la base del cono ideale che si ottiene considerando le rette che passano per il punto S dov'è la sorgente, e si appoggiano al contorno del corpo opaco, come in figura (3.3).

Se invece di considerare una sorgente puntiforme consideriamo una sorgente estesa, ma minore del corpo opaco, si determinano sullo schermo delle zone di penombra, cioè i contorni della zona d'ombra

Page 84: Bioidentià - Il Progetto Ottico

sullo schermo non sono ben delineati e si passa gradualmente dall'ombra alla luce piena.

\noindent La figura che si otterrà sullo schermo si costruisce geometricamente considerando le rette che passano per gli estremi della sorgente luminosa e che si appoggiano al contorno del corpo opaco. Si otterranno in tal modo due coni la cui intersezione delimita la zona d'ombra più marcata: il resto costituisce la penombra (fig. (3.4)).

Se, invece, la sorgente luminosa è più estesa del corpo, l'ombra è convergente, come appare in figura (3.5).

Al di là del vertice P non c'è più alcuna ombra.

Questo spiega anche il fenomeno delle ECLISSI. In tal caso la sorgente S è il sole, il corpo opaco C può essere la terra, nel caso delle eclissi di luna, oppure la luna nel caso delle eclissi di sole.

Nel secondo caso, ad esempio, se la terra viene a trovarsi fra C e P, nel cono d'ombra determinato da C, nella regione della terra su cui tale cono si proietta vi sarà una eclissi totale di sole. Nelle regioni che verranno a trovarsi nelle zone 1 o 2 di penombra, l'eclissi sarà parziale.

Come si vede, la descrizione dei fenomeni collegati alla formazione dell'ombra può avvenire utilizzando nozioni di tipo geometrico lecite solo se si ammette che la luce viaggia in linea retta. Newton riteneva che il modello ondulatorio proposto da Huygens non riuscisse a spiegare questo tipo di fenomeni e portava a riprova di ciò la seguente analogia:

Page 85: Bioidentià - Il Progetto Ottico

le onde sferiche si possono visualizzare ad esempio perturbando la superficie di uno stagno in quiete lanciandovi un sasso.

Se durante l'espansione le onde incontrano un ostacolo esse non formano dietro ad esso un profilo ben definito, ma si accavallano disordinatamente. La stessa cosa dovrebbe avvenire nella propagazione della luce.

Huygens ribatteva mediante un'altra analogia:

Se una barca naviga su un fiume, lascia dietro di sè una scia ben definita e dal contorno regolare. Ciò è dovuto al fatto che la superficie di un fiume è perturbata da una serie di piccole onde che si confondono se osservate macroscopicamente. Dava inoltre un modello matematico per spiegare la propagazione rettilinea della luce, partendo dalla teoria ondulatoria: il Principio di Huygens-Fresnel.

Vediamo l'enunciato di tale principio.

Abbiamo già detto che Huygens riteneva la luce composta da onde elementari sferiche, prodotte nei vari punti dello spazio. Esaminiamo la seguente situazione: alcune onde sferiche vengono

prodotte nei punti ; se C è la velocità di tali

onde, dopo un istante , il fronte di ogni singola onda di luce

sarà una circonferenza di raggio uguale a e centro in .

Ciò che noi percepiamo però è la sintesi dei vari fronti d'onda, o meglio l'inviluppo delle varie circonferenze che costituiscono ognuna il fronte di una singola onda, dove per "inviluppo" intendiamo quella particolare linea che risulta tangente a ciascuna circonferenza.

In particolare se i punti dove si producono le onde, sono allineati su una retta, l'inviluppo che percepiamo dopo

l'istante sarà ancora una retta. L'avanzamento che noi osserviamo pertanto è quello di un' onda piana che, come sappiamo, viaggia in linea retta (fig. (3.6)).

La determinazione della velocità della luce

Uno dei primi problemi quantitativi affrontati nello studio della natura della luce e della sua propagazione è la determinazione

Page 86: Bioidentià - Il Progetto Ottico

della sua velocità. Si riteneva giustamente che tale velocità, per quanto grande, non fosse infinita, anche se la finitezza non era percepibile nella maggior parte dei fenomeni naturali.

Il primo che tentò di dare una valutazione della velocità della luce fu Galileo Galilei.

Scriveva in un suo trattato:

" SIMPLICIO: Mostra l'esperienza quotidiana, l'espansione del lume esser istantanea; mentre che vedendo in gran lontananza sparar una artiglieria, lo splendor della fiamma senza interposizion di tempo si produce agli occhi nostri, ma non già il suono all'orecchie, se non dopo notabile intervallo di tempo.

SEGREDO: Ehi, Signor Simplicio, da codesta notissima esperienza non si raccoglie altro se non che il suono si conduce al nostro udito in tempo men breve di quello che si conduce il lume; ma non mi assicura se la venuta del lume sia perciò istantanea, più che temporanea, ma velocissima .... ''

L'esperimento che tentò Galileo fu quello di porre due persone l'una di fronte all'altra munite di due lumi. La prima persona scopre il proprio lume, la seconda esegue la medesima operazione non appena scorge il segnale. In tal modo la prima persona avrebbe dovuto avere la possibilità di misurare il tempo necessario alla luce per compiere il percorso di andata e ritorno. Ma tale velocità era veramente troppo grande per poter essere apprezzata su distanze terrestri, cosicchè l'esperimento, pur se ripetuto ponendo le persone a distanza di due o tre miglia, non diede alcun risultato.

In linea di principio la tecnica deve considerarsi corretta, ma c'è bisogno, per ottenere risultati apprezzabili, di osservare le cose su distanze estremamente grandi, dell'ordine di milioni di miglia!

Distanze di tale ordine di grandezza intervengono nelle osservazioni astronomiche, e fu proprio nell'ambito di studi astronomici che si ebbe la possibilità, molti anni dopo l'esperimento di Galileo e precisamente nel 1676, di ottenere una stima sufficientemente precisa della velocità della luce. Fu grazie al contributo del danese Romer (1644 - 1710), e dei suoi studi sulle eclissi dei satelliti di Giove. Come abbiamo già detto un'eclissi si osserva quando il satellite entra nel cono d'ombra del pianeta. Se il periodo di rivoluzione è costante allora le eclissi avvengono ad intervalli regolari. Ciononostante l'osservatore sulla terra sperimenta che tali intervalli variano durante l'anno e ciò è dovuto alla diversa distanza in cui viene a trovarsi la terra rispetto a Giove.

Page 87: Bioidentià - Il Progetto Ottico

Iniziamo la prima osservazione dell'eclissi quando la posizione dei vari astri è come quella descritta in figura (4.1).

Dall'analisi dei tempi di rivoluzione si calcola che la seconda eclissi dovrebbe osservarsi esattamente dopo sei mesi. In effetti l'osservazione avviene con un ritardo di tempo . Ciò è dovuto alla nuova posizione della terra: (lo spostamento di Giove in 6 mesi è trascurabile).

Per poter osservare la seconda eclissi la luce dovrà percorrere un tratto più lungo per raggiungere la terra: la differenza di lunghezza dei due percorsi è , pari al diametro dell'orbita

terrestre. Il ritardo di osservazione sarà pertanto: dove C è la velocità della luce.

Da ciò si ricava:

Romer misurando un ritardo pari a , noto il valore , ricavò per la luce una velocità pari a:

Successivi esperimenti più precisi gli consentirono di approssimare il valore a

Page 88: Bioidentià - Il Progetto Ottico

Altri esperimenti di tipo astronomico furono condotti da Bradley studiando il fenomeno della Aberrazione Astronomica; i risultati da lui ottenuti non si discostarono molto da quelli di Romer.

I primi a tentare la misurazione della velocità della luce con metodi non astronomici furono Fizeau e Foucault. Essi riuscirono ad applicare praticamente l'idea teorica di Galileo di misurare il tempo impiegato dalla luce a percorrere un certo cammino nei due sensi.

Fizeau utilizzò uno strumento così composto: una sorgente luminosa, uno specchio ed una ruota dentata posta fra di essi (fig. (4.3)).

Il raggio di luce parte dalla sorgente e passando attraverso uno spazio vuoto della ruota dentata raggiunge lo specchio, viene riflesso e ritorna al punto di partenza. Il raggio di ritorno può essere intercettato da un "dente" della ruota se essa gira con sufficiente velocità angolare. è proprio la misura della velocità angolare necessaria ad intercettare il raggio riflesso che consente la misurazione della velocità della luce. Infatti se la luce riflessa viene intercettata, vuol dire che il tempo impiegato dalla luce per percorrere due volte (andata e ritorno) la distanza ruota-specchio è uguale al tempo impiegato dalla ruota a

percorrere l'angolo , fra il centro di un faro e il centro di un dente.

Tale intervallo di tempo sarà dato, se è la velocità della ruota necessaria affinchè avvenga il fenomeno, da:

Questo fornisce:

Page 89: Bioidentià - Il Progetto Ottico

dove l è la distanza ruota-specchio.

Il valore di C ottenuto in tal modo fu:

L'imprecisione per eccesso era dovuta al fatto che l'osservazione della "sparizione della luce", segno che il raggio viene intercettato, è una operazione che risente dei "riflessi" dell'osservatore per cui è soggetta ad errori.

L'esperienza fu migliorata da Foucault, il quale anzicchè una ruota dentata utilizzò uno specchietto rotante.

Il raggio parte da S e viene riflesso dallo specchio rotante, raggiunge il secondo specchio e viene nuovamente riflesso dallo specchio rotante, che nel frattempo avrà compiuto una rotazione pari a un angolo (fig. (4.5)).

Dunque il raggio partito dal punto A sarà proiettato sul punto B.

La distanza fra A e B consente di ottenere l'angolo e se è nota, si ottiene il valore di , che è il tempo impiegato dalla luce per percorrere la distanza fra i due specchi per due volte.

Con questo metodo Foucault ottenne un valore per C pari a:

Altre esperienze condotte da Michelson agli inizi del secolo utilizzando gli stessi strumenti di Foucault, diedero un valore:

Page 90: Bioidentià - Il Progetto Ottico

Il valore più preciso finora ottenuto per la velocità della luce risale al 1970, ed è:

Nel 1983, la velocità della luce è stata utilizzata per definire l'unità di lunghezza. Oggi infatti si chiama metro la distanza percorsa dalla luce nel vuoto in un intervallo di tempo pari a 1/299792458 secondi. Dunque la velocità della luce è posta per definizione pari a

La luce come onda elettomagnetica

Analisi microscopica della emissione luminosa

Si deve a Maxwell l'identificazione della luce come fenomeno elettromagnetico; l'idea nacque osservando che la velocità delle onde elettromagnetiche nel vuoto

dove ed sono delle costanti, è pari alla velocità della luce.

La cosa più sorprendente che si è osservata nella prima metà di questo secolo è che il comportamento della luce avvalora in certi fenomeni la teoria corpuscolare ed in certi altri la teoria ondulatoria, ed in un certo senso contraddice alcune osservazioni ed interpretazioni di fenomeni che verso la fine del secolo XIX avevano portato al trionfo della teoria ondulatoria. Si ha infatti che la luce si comporta come un'onda nella sua propagazione attraverso lo spazio e si comporta come uno sciame di particelle (dette fotoni) nella sua interazione con la materia.

La spiegazione di tale ambivalenza si ha solo nell`ambito della Meccanica quantistica, per cui le particelle cui si accennava prima non sono altro che "Pacchetti" di onde elettromagnetiche di piccola lunghezza d'onda.

Cerchiamo ora di spiegare in termini semplici tali fenomeni.

L'emissione della luce avviene a livello atomico; sappiamo che un atomo è costituito da un nucleo centrale in cui sono concentrati protoni e neutroni e da un certo numero di elettroni che orbitano attorno al nucleo. In un certo senso l'atomo può essere pensato come un sistema planetario in cui al centro cè il nucleo atomico dove risiede quasi tutta la massa e le cariche positive (tenute dai protoni). Attorno ad esso, in maniera simile ai pianeti,

Page 91: Bioidentià - Il Progetto Ottico

orbitano i singoli elettroni che hanno carica negativa (fig. (5.1.1)).

Ogni orbita corrisponde ad un "livello energetico", cioè gli elettroni ruotano seguendo una data orbita a seconda della quantità di energia che è in loro possesso. Tale energia non è fissa: può anche essere ceduta o assorbita, nel qual caso l'elettrone cambierà orbita, passando ad un livello energetico rispettivamente più basso o più alto. Tale passaggio non avviene mediante spostamenti graduali e continui, ma "a salti", cioè direttamente da un'orbita all'altra.

\noindent Da notare anche che questi livelli energetici sono in numero finito. L'aumento di energia corrisponde all' assorbimento nell'atomo di un fotone di luce; in tal modo l'atomo viene a trovarsi in una condizione di eccitamento, con gli elettroni che si spostano su orbite corrispondenti a livelli energetici più alti. In modo del tutto casuale, gli elettroni ritornano al loro stato energetico di partenza. In tale situazione si ha una emissione di un fotone di luce, con l'insorgere spontaneo del raggio luminoso.

La produzione della luce avviene allora nel modo seguente: fornendo energia al corpo (ad esempio surriscaldandolo fino a farlo diventare incandescente) si provoca una eccitazione degli atomi. Ciò comporta una variazione del livello orbitale degli elettroni. Quando questi, casualmente, saltano alle orbite originarie, si ha emissione di luce.

Sorgenti luminose

Allora una sorgente luminosa non è altro che un corpo che emette una radiazione elettromagnetica pura.

Le sorgenti luminose si possono classificare in diversi modi: distinguiamo le Sorgenti primarie, che effettivamente emettono la radiazione luminosa, dalle Sorgenti secondarie, che riflettono la luce proveniente da altre fonti; le sorgenti Puntiformi dalle sorgenti Estese, intendendo per sorgenti Puntiformi le sorgenti sufficientemente piccole (cioè le cui dimensioni non superino 1/10 della distanza fra di esse ed una superficie in esame).

Page 92: Bioidentià - Il Progetto Ottico

A seconda del tipo di luce che viene emessa possiamo classificare le sorgenti in Coerenti e Incoerenti: le prime emettono radiazioni luminose in fase fra di loro, mentre le seconde emettono radiazioni sfasate. (Intendiamo per radiazioni in fase delle radiazioni i cui rispettivi minimi e massimi coincidono (fig. (5.2.1)).

In natura tutte le sorgenti sono incoerenti, poichè l'emissione di ciascuna radiazione avviene in modo casuale. Le radiazioni coerenti si ottengono solo in laboratorio mediante sofisticati strumenti ottici (ad esempio il LASER).

Intensità luminosa e d'illuminazione

Per quanto detto in precedenza, possiamo affermare che l'emissione di luce è sempre legata ad un assorbimento e ad un rilascio di energia; il bilancio energetico complessivo della quantità di energia assorbita e di quella emessa sotto forma di radiazione luminosa dipende dal corpo. Sappiamo ad esempio che alcuni corpi trattengono una maggiore quantità di energia, altri la trasformano in forme diverse dalla radiazione luminosa. è importante pertanto dare una classificazione dei corpi in base alla quantità di energia che irradiano sotto forma di luce. A tal fine si introducono i concetti di Intensità luminosa e di Intensità di illuminazione.

 L'intensità luminosa è la quantità di energia che un corpo irradia in un secondo.

Pertanto essa è misurata in Watt.

 L'intensità di illuminazione misura la quantità di energia che

arriva su una superficie di un a causa dell'illuminazione.

Essa sarà misurata in .

E' necessario anche introdurre una unità di misura diretta della sensazione luminosa percepita visivamente; ciò si ottiene introducendo l'unità Violle:

Page 93: Bioidentià - Il Progetto Ottico

 Un Violle è l'intensità luminosa prodotta dalla superficie di

di platino alla temperatura di fusione (1769 °C).

Ai fini pratici è molto più usata la Candela internazionale (CD) che vale 1/20 del Violle.

Bunsen costruì uno strumento detto Fotometro, in grado di misurare l'intensità luminosa utilizzando semplicemente un foglietto di carta abbastanza spesso in modo da non far passare la luce, con una macchia d'olio al centro. Posta di fronte ad una sorgente luminosa, tale macchia appare scura se la guardiamo dallo stesso lato della sorgente, appare chiara se la guardiamo dall'altro lato. Infatti l'olio rende la carta traslucida per cui lascia filtrare una certa quantità di luce.

Se la quantità di luce che filtra attraverso la macchia viene compensata ponendo dall'altra parte del foglio una sorgente della stessa intensità, allora la macchia non è più visibile. Il fotometro di Bunsen è costituito da un'asta graduata su cui possono scorrere tre sostegni di cui uno al centro porta la carta con la macchia e gli altri due le sorgenti luminose, per una delle quali è nota la sua intensità luminosa (fig. (5.3.1)).

Se le due sorgenti sono poste alla stessa distanza dal foglio ed hanno la stessa intensità, la macchia sparirà alla vista; ma se ad esempio poniamo la seconda sorgente ad una distanza dal foglio di carta doppia rispetto alla prima, si osserverà che la macchia scomparirà solo se l'intensità luminosa della seconda sorgente è M volte maggiore della prima.

Questo suggerisce che l'intensità di illuminazione sul foglio dipende dalla distanza della sorgente, e varia in ragione del quadrato della distanza, cioè se tale distanza raddoppia l'intensità diventa 1/4; se triplica diventa 1/9, etc. Cioè se K è l'intensità prodotta alla distanza unitaria, alla distanza d si

avrà l'intensità .

Se , sono rispettivamente le intensità luminose delle

sorgenti e se sono le distanze di dal foglio di carta, vale allora la seguente legge:

Page 94: Bioidentià - Il Progetto Ottico

da cui si ottiene:

Se è nota, si può così facilmente ottenere il valore di .

Una spiegazione di tale fenomeno sperimentale può essere data partendo dalla propagazione rettilinea della luce.

Sia S una sorgente che possiede una intensità luminosa I e sia A una qualsiasi superficie posta a distanza d da S.

La luce che passa attraverso A, passerà anche attraverso una superficie B posta a distanza 2d da S e costruita in modo che risulti essere la base del cono che si ottiene considerando le rette spiccate da S e tangenti al contorno di A (fig. (5.3.3)).

Ma la superficie di B è, per come è costruita, quattro volte maggiore rispetto a quella di A, pertanto l'intensità d'illuminazione su A sarà I/A, mentre su B sarà I/B e poichè B=4A, ne segue che su B l'intensità è

Osserviamo che la luce, attraversando mezzi trasparenti, viene rifratta. Tale fenomeno sarà interpretato per mezzo della teoria

Page 95: Bioidentià - Il Progetto Ottico

ondulatoria e corpuscolare e permetterà di studiare il comportamento della luce nelle lenti.

La rifrazione

Consideriamo un raggio luminoso che viaggia attraverso un mezzo trasparente, ad esempio l'aria. Se sul suo cammino incontra un nuovo mezzo trasparente, ad esempio acqua o vetro, nel passaggio dall'uno all'altro mezzo il raggio subisce una deviazione abbastanza netta. Si dice in tal caso che il raggio viene rifratto.

 La rifrazione è la causa di numerosi fenomeni visivi facilmente osservabili.

Ad esempio se immergiamo una sbarretta in un bicchiere pieno d'acqua, avremo l'impressione che essa sia spezzata, poichè la parte immersa non appare allineata con la parte fuori dall'acqua; oppure collocando una monetina in una bacinella non trasparente e ponendosi in modo che il bordo del recipiente impedisca di scorgere la moneta, si osserva che riempendo d'acqua la bacinella, si vedrà ricomparire la monetina. Ciò accade perchè in presenza dell'acqua i raggi luminosi seguono una traiettoria "spezzata" che consente di aggirare l'ostacolo costituito dal bordo.

Le leggi sperimentali che regolano la rifrazione furono date per la prima volta da Cartesio e da Snellius.

Il raggio luminoso, prima di incontrare la superficie di separazione dei due mezzi trasparenti, viene detto raggio incidente; dopo la rifrazione raggio rifratto.

L'angolo di incidenza è quello formato dal raggio incidente con la normale alla superficie di separazione; l'angolo di rifrazione è invece quello formato con la stessa normale dal raggio rifratto.

La prima osservazione che si può fare è la seguente:

 il raggio incidente, quello rifratto e la normale giacciono su di uno stesso piano

Page 96: Bioidentià - Il Progetto Ottico

Inoltre sussiste la seguente relazione: se sono rispettivamente gli angoli di incidenza e di rifrazione, si osserva che:

(1.1)

La (1.1) trova una spiegazione differente a seconda che si consideri valida la teoria corpuscolare o quella ondulatoria.

Vediamo come la teoria corpuscolare spiega il fenomeno di rifrazione: Newton suppose che la variazione dell'angolo subita dal raggio a causa della rifrazione fosse dovuta ad una variazione di velocità delle particelle luminose che si determina nel passaggio dall'uno all'altro mezzo, e portava la seguente analogia: se una sferetta rotola su un piano inclinato con una

traiettoria inclinata di un angolo rispetto alla normale al bordo del piano, tale angolo può essere ridotto se la sferetta subisce un aumento repentino di velocità, ad esempio a causa di un dislivello sul piano stesso (fig. (1.2)).

Riferendo l'analogia alla rifrazione, il piano inclinato a corrisponde al primo mezzo; il piano inclinato b, al secondo. La superficie di separazione corrisponde invece al dislivello fra i due piani a, b.

Se quindi un raggio luminoso arriva a contatto della superfie con velocità , secondo l'idea di Newton, le particelle di luce sono sottoposte ad una forza perpendicolare alla superficie di separazione, per effetto della quale la componente perpendicolare della velocità varia, mentre rimane inalterata la componente parallela.

Se è tale componente parallela, e è la stessa componente relativa alla velocità del raggio rifratto, varrà:

(1.2)

Page 97: Bioidentià - Il Progetto Ottico

Ma come sappiamo, si ha

(1.3)

e quindi risulta:

(1.4)

Diciamo che il mezzo 2 è più rifrangente del mezzo 1 se l'angolo di incidenza è maggiore di quello di rifrazione quando un raggio luminoso passa dal mezzo 1 al mezzo 2.

Se allora conduciamo il nostro esperimento scegliendo, ad esempio, i mezzi aria e vetro, oppure aria ed acqua (l'acqua e il vetro sono più rifrangenti dell'aria), si avrà:

per cui dalla teoria corpuscolare si ricava che

 la velocità della luce è maggiore nei mezzi più rifrangenti.

Vediamo come la teoria corpuscolare spiega invece il fenomeno della rifrazione.

Costruiamo, quindi, il raggio rifratto con il metodo dell'inviluppo piano già introdotto precedentemente.

Siano A,B due punti qualsiasi del fronte d'onda. Se la direzione

di propagazione del fronte è inclinata di un angolo rispetto alla normale alla superfice, o il punto A o il punto B giungerà prima dell'altro a contatto della superfice. Assumiamo che sia A tale punto. Dal momento in cui l'onda in A viene rifratta, il punto B

Page 98: Bioidentià - Il Progetto Ottico

giungerà sulla superfice dopo un tempo , cioè dopo aver percorso

un segmento di lunghezza pari a .

Nello stesso intervallo di tempo, il punto A si sarà spostato di

un segmento pari a , che non è uguale a , poichè si

suppone che

Allora, come è mostrato in figura (1.5), l'inviluppo dopo il tempo

avrà cambiato direzione di propagazione, e quindi, se l è la lunghezza del segmento A'B,

(1.5)

da cui:

(1.6)

Risulta pertanto dalla teoria ondulatoria una legge inversa da quella ricavata nella teoria corpuscolare, cioè:

e quindi la velocità della luce è maggiore nei mezzi meno rifrangenti.

Questo fatto costituì la chiave di volta che permise di stabilire definitivamente quale delle due teorie era valida: poichè l'acqua

Page 99: Bioidentià - Il Progetto Ottico

risulta più rifrangente dell'aria, bastava misurare la velocità della luce nei due mezzi.

Tale prova venne realizzata intorno al 1860 da Foucault utilizzando la tecnica dello specchio girevole e fornì un risultato che diede ragione alla teoria ondulatoria: la luce si

propaga nell'acqua con la velocità di , uguale a circa 3/4 del valore con cui si propaga nell'aria.

Indice di rifrazione relativo e assoluto

Il rapporto:

viene indicato solitamente con e si chiama indice di rifrazione relativo ai mezzi 1 e 2, quando la luce passa dal mezzo 1 al mezzo

2. Per le osservazioni precedenti possiamo dire che se il mezzo 1 è meno rifrangente del mezzo 2; viceversa se

Osserviamo che anche nel caso della rifrazione vale il principio della reversibilità del cammino luminoso. Questo ci permette di dedurre la relazione

Si chiama indice di rifrazione assoluto l'indice calcolato rispetto al vuoto. Per la (1.6) possiamo esprimere l'indice di rifrazione come il rapporto fra la velocità della luce nei due mezzi, cioè:

da questo, l'indice di rifrazione assoluto sarà:

Se consideriamo due mezzi il cui indice di rifrazione assoluto è

rispettivamente si ottiene facilmente:

Page 100: Bioidentià - Il Progetto Ottico

(2.1)

relazione che lega l'indice di rifrazione relativo con gli indici di rifrazione assoluto dei due mezzi. Nella tabella abbiamo gli indici di rifrazione assoluto per alcuni mezzi.

 MEZZO  INDICE Aria  1,000294 Idrogeno  1,000139 Ossigeno  1,000272 Acqua  1,33 Alcol etilico  1,36 NaCl  1,53 Vetro Flint  1,579 Vetro Crown  1,516 Diamante  2,419 Zaffiro  1,76 Glicerina  1,474 Olio di cedro  1,515 Quarzo  1,544 Quarzo fuso  1,46 Etere  1,352

Angolo limite e riflessione totale

Se consideriamo un raggio che passa da un mezzo più rifrangente ad uno meno rifrangente, si potrà considerare un particolare valore dell'angolo di incidenza per il quale il raggio rifratto risulta parallelo e radente alla superficie di separazione (fig. (3.1)).

Se è tale valore, per un angolo di incidenza maggiore di , non si avrà la formazione di nessun raggio rifratto, ma il raggio verrà deviato totalmente all'interno del mezzo più rifrangente, dando luogo al fenomeno della cosiddetta riflessione totale. prende il nome di angolo limite.

Page 101: Bioidentià - Il Progetto Ottico

Il fenomeno ora descritto trova numerose applicazioni, ad esempio nella costruzione delle fibre ottiche, che imprigionano la luce all'interno di esse facendole percorrere anche dei cammini curvi.

Un'altra applicazione è la costruzione dei periscopi, in cui viene utilizzata una doppia riflessione totale.

Dalla (2.1), poichè

si ricava anche

Se è uguale all'angolo limite, si ha

allora conoscendo gli indici di rifrazione assoluta dei mezzi, si può ottenere il valore dell'angolo limite dalla formula:

(3.1)

Page 102: Bioidentià - Il Progetto Ottico

La rifrazione è anche causa di numerosi fenomeni naturali, ad esempio il miraggio e la fata morgana. Entrambi sono dovuti alla diversa densità degli strati di aria, per cui quelli più densi risultano più rifrangenti rispetto a quelli meno densi.

Nelle giornate molto calde, l'aria vicina al suolo è molto più calda di quella che si trova negli strati superiori, e di conseguenza è più rarefatta. Se un raggio luminoso parte dalla cima di un albero diretto verso il basso, esso subisce una deviazione man mano che incontra gli strati meno rifrangenti, finchè l'inclinazione del raggio raggiunge e supera l'angolo limite, ed è diretto verso l'alto. Se il raggio, dopo questa traiettoria, incontra un osservatore, questi avrà l'impressione che esso ha compiuto un cammino in linea retta, per cui scorgerà l'albero e la sua immagine come se fosse riflessa in uno specchio d'acqua. Si ha in tal caso il miraggio.

Viceversa se le condizioni atmosferiche sono tali che l'aria più rarefatta è in superfice, un raggio diretto verso l'alto può venire rifratto fino ad essere deviato verso il basso. In tal caso l'oggetto può apparire sollevato dal suolo.

Tale fenomeno si verifica in modo evidente sullo stretto di Messina: la costa siciliana in particolari condizioni può apparire sospesa nell'aria. Si ha in tal caso il fenomeno detto fata morgana.

Le lenti

Chiameremo lente un qualsiasi corpo trasparente limitato da due superfici curve o da una superficie piana ed una curva, in grado di modificare la traiettoria di un raggio luminoso che la attraversi.

Le lenti si distinguono in convergenti, riconoscibili per una forma più spessa al centro e più sottile ai bordi, oppure divergenti, di forma più spessa ai bordi e più sottile al centro.

A loro volta le lenti convergenti si suddividono in biconvesse, piano-convesse e menisco-convesse (fig. (4.1));

Page 103: Bioidentià - Il Progetto Ottico

e quelle divergenti in biconcave, piano-concave e menisco-concave (fig. (4.2)).

Chiamiamo: raggi di curvatura di una lente i raggi delle sfere cui le calotte che costituiscono la lente appartengono. L'asse che congiunge i centri di tali sfere è detto asse principale. Il punto in cui l'asse ottico incontra la lente è detto invece centro ottico. Ogni retta per il centro ottico è detta asse secondario.

Lenti convergenti

Cominciamo ad analizzare gli effetti che una lente convergente produce sui raggi luminosi.

Consideriamo un fascio di raggi paralleli all'asse principale. Si sperimenta facilmente che tutti i raggi vengono rifratti in modo da occorrere in un unico punto detto FUOCO della lente.

Ogni lente ovviamente possiede due fuochi simmetrici, posti dall'una e dall'altra parte della lente, poichè l'effetto prodotto dalla lente è indipendente dalla faccia impressionata dalla luce. Lo stesso si osserva per un qualsiasi altro asse, per il quale si determina un fuoco secondario F', che contribuisce a formare il piano focale della lente.

Per costruire geometricamente l'immagine prodotta da una len\-te è sufficiente tenere presente che:

1) Il raggio passante per il centro ottico attraversa la lente senza essere deviato.

2) Un raggio parallelo all'asse principale viene deviato sul fuoco della lente.

Page 104: Bioidentià - Il Progetto Ottico

3) Un raggio che passa per il fuoco è deviato parallelamente all'asse principale.

A differenza degli specchi sferici, il fuoco di una lente non può essere determinato mediante costruzioni puramente geometriche, poichè la rifrazione dipende dal materiale che costituisce la lente.

Se consideriamo una sorgente luminosa puntiforme posta davanti ad una lente, notiamo che tutti i raggi provenienti da tale sorgente vengono rifratti in modo da intersecarsi in un altro punto, che sarà il punto coniugato del punto oggetto in questione.

Possiamo allora affermare che

 una lente convergente di piccola apertura e di piccolo spessore trasforma un fascio omocentrico di raggi di vertice S in un altro fascio omocentrico di vertice S'; S ed S' sono punti coniugati.

E andiamo ora ad analizzare il tipo di immagine prodotta da una lente convergente quando si considera un oggetto esteso, che graficamente rappresentiamo mediante una freccetta.

L'immagine dipenderà dalla distanza dell'oggetto dalla lente.

Indichiamo con i due fuochi principali della lente e con C il centro ottico.

Situazione 1: Oggetto distante dalla lente più del doppio della distanza focale

L'immagine è capovolta, rimpicciolita e posta dall'altra parte

della lente tra .

Page 105: Bioidentià - Il Progetto Ottico

Situazione 2: L'oggetto è ad una distanza doppia di quella focale.

L'immagine è capovolta ma delle stesse dimensioni dell'oggetto,

posta in .

Situazione 3: L'oggetto è fra

L'immagine è capovolta, ingrandita e ad una distanza maggiore del doppio di quella focale.

Situazione 4: Oggetto posto nel fuoco della lente.

L'immagine appare all'infinito, ingrandita al massimo e capovolta.

Situazione 5: Oggetto posto tra il fuoco e la lente.

L'immagine stavolta è virtuale; compare dalla stessa parte dell'oggetto, diritta e ingrandita rispetto ad esso.

Page 106: Bioidentià - Il Progetto Ottico

Formule per i punti coniugati di lenti convergenti

Dato un punto oggetto A, la sua immagine B sarà il punto in cui occorrono tutti i raggi provenienti da A. In particolare per determinare la posizione del punto coniugato nota quella del punto oggetto, è sufficiente disegnare la traiettoria di due raggi. Il problema è ulteriormente semplificato se l'oggetto è sull'asse principale. In tal caso sappiamo che un raggio che coincide con tale asse attraversa la lente senza subire deviazioni. Basta allora esaminare un solo raggio e vedere in quale punto esso, rifratto (o il suo prolungamento), interseca l'asse principale.

Discorso analogo vale per oggetti estesi. In tal caso la costruzione dovrebbe essere ripetuta per tutti i punti.

Consideriamo un segmento di estremi X,Y posto davanti ad una lente convergente. Se esso è posto prima del fuoco della lente, avrà un' immagine costituita dal segmento X', Y' come in figura (4.2.1).

Per costruzione, i triangoli XYC e X'Y'C sono simili; pertanto si ricava:

(4.2.1)

Se poniamo le distanze XC e CX' pari rispettivamente a p e a q, la (4.2.1) si scrive:

(4.2.2)

Sono inoltre simili i triangoli e .

Da ciò possiamo ricavare:

Page 107: Bioidentià - Il Progetto Ottico

(4.2.3)

dove f è la distanza focale.

Ovviamente si ha XY =AC, per cui la (4.2.3) è analoga alla

(4.2.4)

e confrontando la (4.2.2) e la (4.2.4) otteniamo

quindi

(4.2.5)

e dividendo ogni termine per pqf

(4.2.6)

Come si vede, la (4.2.6) è analoga alla formula dedotta per gli specchi sferici.

Abbiamo ricavato inoltre la formula per l' ingrandimento trasversale, definito dal rapporto fra la lunghezza dell'oggetto e quella della sua immagine. La (4.2.4) infatti fornisce:

Si può anche ricavare dalla (4.2.5):

Page 108: Bioidentià - Il Progetto Ottico

(4.2.7)

per cui si ha:

(4.2.8)

Lenti divergenti

La principale differenza di una lente divergente rispetto ad una convergente è costituita dal fatto che se consideriamo un fascio di raggi paralleli all'asse principale della lente, essi verranno rifratti non in modo da intersecarsi in un punto, ma in modo da "divergere" senza mai intersecarsi.

Se però consideriamo i prolungamenti dei raggi rifratti, essi occorrono in un punto sull'asse principale.

Dunque il fuoco di una lente divergente è un punto virtuale, nel senso che è determinato non direttamente dai raggi rifratti, ma dai loro prolungamenti.

Poichè discorso analogo si può riferire ad un qualsiasi altro asse che non sia quello principale, diremo che il piano focale di una lente divergente è di tipo virtuale e sarà definito come il piano nel quale si forma l'immagine virtuale di un oggetto posto all'infinito.

La formazione delle immagini mediante le lenti divergenti si ottiene utilizzando i metodi già visti in precedenza.

Per quanto osservato avremo che qualunque sia la posizione dell'oggetto rispetto alla lente, la sua immagine è sempre

Page 109: Bioidentià - Il Progetto Ottico

virtuale, diritta e rimpicciolita, posta dalla stessa parte dell'oggetto.

Anche per le lenti divergenti valgono le formule dei punti coniugati prima ricavate: si ottengono in modo analogo purchè si consideri negativa la distanza focale f della lente.

Se per studiare i fenomeni della riflessione e della rifrazione è possibile utilizzare un modello geometrico in grado di "simulare" con buona approssimazione i fatti fisici reali, ciò non si può fare per i fenomeni legati al colore. Il colore riguarda la natura della luce non disgiunta, e dalla costituzione fisiologica degli organi visivi (gli occhi) dà la sensazione visiva.

Dispersione della luce: il colore

Il problema di dare una spiegazione alla natura e alla formazione del colore si trascinò per lunghissimo tempo su impostazioni sbagliate ed anche dopo che gli studi sulla natura della luce avevano raggiunto livelli accettabili, ci volle un bel pò prima che si riuscisse a capire che il colore non sussiste solo come entità oggettiva, ma è condizionato da numerosi fattori. Noi infatti siamo in grado di attribuire, in base alle nostre percezioni, ad ogni oggetto il proprio colore; però verifichiamo continuamente come questo colore risenta delle condizioni ambientali circostanti, del grado di illuminazione ed anche delle particolari condizioni in cui si trovano i nostri occhi, come facili e comuni esperienze ci consentono di verificare. Ad esempio se proviamo a guardare il sole con gli occhi chiusi, essi risulteranno impressionati per un certo periodo di tempo dalla luce rosso-arancio che filtra attraverso le palpebre, sì da diventare particolarmente sensibili a questo colore. Quando riapriremo gli occhi tutte le tinte ci appariranno "povere" di rosso-arancio e quindi di tonalità più fredda, tendente al verde-azzurro.

I fattori fisiologici accennati pur non formando oggetto di studio dell'ottica fisica, sono importanti poichè possono anche suggerire delle piste di ragionamento che portano a conclusioni sbagliate, come in effetti è successo.

Fu Newton il primo a stabilire che il colore non è una qualità intrinseca degli oggetti che la luce mette in evidenza, ma

Page 110: Bioidentià - Il Progetto Ottico

l'effetto dell'interazione del raggio luminoso con la sostanza; cioè è la luce che ha in sè il colore. Ciò è stato provato con la scoperta, da parte di Newton, del fenomeno della dispersione della luce, già intuito da Cartesio nel tentativo di spiegare la formazione dell'arcobaleno.

Newton osservò un raggio di luce che filtrando attraverso un foro dell'imposta, attraversava un prisma di vetro. L'immagine così prodotta si raccoglieva sulla parete opposta formando una fascia illuminata oblunga suddivisa in bande di sette colori diversi, che andavano dal rosso al violetto.

Se mediante una lente la luce viene concentrata nuovamente, si riottiene un fascio di luce bianca, segno inequivocabile che la luce bianca è la sintesi dei raggi colorati e che la loro formazione dipende dal raggio luminoso e non dal prisma. Newton provò inoltre che ogni singolo colore non è ulteriormente scomponibile: grazie ad un diaframma egli isolò dal fascio un raggio di un unico colore, e lo filtrò mediante un prisma, ma il fascio di luce non subì alcuna ulteriore modificazione.

Nel dare una spiegazione al fenomeno della dispersione Newton restò fedele ai principi della teoria corpuscolare. La luce, evidentemente, è composta da particelle che non subiscono tutte la medesima rifrazione. Poichè secondo la teoria corpuscolare, la rifrazione è dovuta ad una forza che agisce quando la luce attraversa la superficie di separazione fra due sostanze, ne segue che le particelle che hanno una massa più piccola subiscono una maggiore deviazione, e vanno a costituire le bande luminose colorate più esterne.

D'altro canto anche nell'ambito della teoria ondulatoria la dispersione trova una spiegazione plausibile semplicemente supponendo che ogni fascia di colore comprende onde di una certa frequenza e che quindi un fascio di luce bianca è composto da onde con differenti lunghezze d'onda. Poichè, come sappiamo, in certi mezzi onde di differente frequenza viaggiano con differente velocità, ecco spiegato il fenomeno della dispersione.

A prima vista, entrambe le spiegazioni appaiono ugualmente accettabili, ma grazie agli studi condotti da Eulero e dall'inglese J. Dallan, si è provato che la prima ipotesi è errata.

Una prova si è avuta nell'ambito degli studi sulla Aberrazione cromatica, fenomeno che si ha quando si osserva un corpo luminoso con una lente. Essa, infatti, in una certa misura, si comporta come un prisma, disperdendo parte della luce proveniente dall'oggetto osservato, che apparirà così con un contorno sfumato di colore. Ciò è fastidioso soprattutto nelle osservazioni astronomiche poichè i telescopi forniscono immagini sfocate. Il fenomeno dell'aberrazione riguarda la rifrazione della luce ma non

Page 111: Bioidentià - Il Progetto Ottico

la riflessione, pertanto Newton ebbe l'idea di utilizzare un sistema di specchi per eliminarla costruendo così il primo telescopio "acromatico".

L'idea di ricorrere agli specchi gli era suggerita anche dalla concezione che aveva sulla natura della luce; se infatti l'aberrazione è dovuta alle differenti masse delle particelle di luce, un qualsiasi sistema di lenti non potrà mai correggere l'aberrazione, poichè particelle con masse differenti devono sempre essere deviate in modo diverso. Eulero teoricamente e Dallan praticamente provarono invece il contrario, cioè utilizzando solo delle lenti, costruirono un obiettivo acromatico.

Questo risultato è compatibile solo con la teoria ondulatoria. In essa infatti è lecito che, combinando opportunamente lenti differenti, si riesca a rifrangere allo stesso modo componenti monocromatiche diverse.

Analisi del colore: gli spettri

Se consideriamo un raggio di luce che proviene da una qualsiasi sorgente, è interessante studiare quali sono le componenti monocromatiche che lo compongono. Questo tipo di studio si chiama Spettroscopia.

Lo"spettro" dunque è la composizione monocromatica che determina un certo tipo di luce. Negli esperimenti condotti da Newton la luce conteneva tutte le componenti monocromatiche. In tal caso si dice che lo spettro di emissione è continuo. Molte altre sorgenti naturali però emettono una luce che contiene solo alcune componenti monocromatiche rispetto alle sette individuate da Newton. Ad esempio se osserviamo allo spettroscopio la luce emessa da una lampada al neon, lo spettro che ci apparirà non è continuo, cioè composto da un'unica striscia luminosa orizzontale che comprende i vari colori, ma discontinuo, cioè composto da tante righe verticali.

In generale la luce emessa da sostanze gassose quando sono eccitate , elettricamente è sempre di tipo discontinuo. Inoltre se la sostanza è allo stato atomico, le righe sono molto distanziate. Se è allo stato molecolare, le righe sono riunite in modo da formare delle bande verticali.

Un altro modo per ottenere lo spettro di emissione di una sostanza è quello di dirigere su di essa un fascio di luce il cui spettro è di tipo continuo e di analizzare la luce dopo l'interazione con la sostanza.

Si osserva che una sostanza che è in grado di emettere ad esempio una luce gialla, "sottrae" al fascio di luce bianca la componente monocromatica del giallo, come è provato dal fatto che lo spettro della luce riflessa dalla sostanza, presenta una striscia scura

Page 112: Bioidentià - Il Progetto Ottico

nella zona del giallo. Si ha allora il Principio di inversione dello spettro, secondo il quale una sostanza assorbe le radiazioni monocromatiche che è in grado di emettere.

Ciò spiega anche perchè gli oggetti ci appaiono di un determinato colore: è dovuto all'assorbimento di particolari componenti monocromatiche della luce che li colpisce. Ad esempio se analizziamo la luce diffusa da un limone, notiamo che lo spettro presenta delle zone scure nelle regioni del blu, del rosso e del violetto. Dunque dal limone noi riceviamo una luce prevalentemente composta dal giallo e dal verde. La sintesi di questi due colori fornisce la sfumatura di colore giallo che è caratteristica del limone.

Diffrazione ed interferenza

Una volta assunta valida la teoria ondulatoria, c'è da aspettarsi che per la luce sussistono alcuni fenomeni che si osservano in generale per le onde, cioè la diffrazione e l'interferenza.

Questi fenomeni sono facilmente riscontrabili per quel che riguarda ad esempio le onde sonore, ma non è così per la luce poichè le onde che compongono il raggio luminoso sono di dimensioni notevolmente più piccole rispetto alle onde sonore, per cui fenomeni che si producono a livello microscopico sono talvolta non bene osservabili a livello macroscopico. Ciò nonostante fenomeni di diffrazione e di interferenza furono osservati già nel 1600 dal Bolognese Padre Francesco Maria Grimaldi, il quale pubblicava nel 1665 la sua opera "Physicamathesis de Lumine, Coloribus et Tride", in cui per la prima volta si parlava di diffrazione della luce. Ma solo successivamente tali fenomeni venivano interpretati a conferma della teoria ondulatoria: per lungo tempo, anche a causa della grande autorità di cui Newton godeva negli ambienti scientifici, furono oggetto di discussioni che erano destinate a non portare alcun contributo alla comprensione dei fenomeni, poichè non si sganciavano dalla concezione errata della luce come sciame di particelle materiali.

Vediamo ora in dettaglio di cosa si tratta: supponiamo che un raggio di luce venga diretto su uno schermo nel quale sia praticato un piccolo foro (con diametro dell'ordine del millimetro). Se la luce che attraversa il foro viene raccolta su di un secondo schermo, si noterà che essa delimita un contorno le cui dimensioni sono ben più grandi di quelle del foro. è questo il fenomeno della diffrazione. Ma qual è la sua causa?

Page 113: Bioidentià - Il Progetto Ottico

Appare evidente che quanto descritto contrasta con l'ipotesi corpuscolare, poichè non c'è alcuna causa che possa alterare il moto rettilineo uniforme delle particelle di luce; mentre l'ipotesi ondulatoria fornisce una spiegazione abbastanza precisa delle cose.

Il raggio che colpisce il primo schermo si può approssimare come inviluppo di onde sferiche, secondo il principio di Huygeus-Fresnel. Ogni punto di ogni singola onda sferica diventa a sua volta centro di un'onda elementare, così avviene l'avanzamento globale del fronte d'onda piana. Ma nel passaggio attraverso il foro, solo poche onde elementari filtrano attraverso di esso, per cui l'inviluppo che determina il fronte d'onda non sarà più piano ma tenderà ad allargarsi a ventaglio.

Se il foro è piuttosto largo allora le onde che riescono a passare attraverso di esso sono numerose, per cui si conserva il fronte d'onda piano, a parte piccole sfrangiature sui bordi.

Il fenomeno dell' interferenza invece è dovuto al fenomeno generale, valido per qualsiasi tipo di onda, noto come il Principio di sovrapposizione.

 La somma vettoriale degli spostamenti prodotti da singoli moti ondulatori è uguale ad uno spostamento reale ancora di tipo ondulatorio.

In particolare da ciò si ricava che quando due o più vibrazioni di uguale frequenza o due o più onde di uguale lunghezza d'onda si sovrappongono si può avere un rafforzamento del risultante moto ondulatorio.

Nel primo caso si avrà una interferenza costruttiva che si ottiene quando la differenza di fase è pari a ; nel secondo caso si avrà una interferenza distruttiva, quando la differenza di fase è

dove n è un numero intero.

Nel caso della luce, per avere l'interferenza è necessario disporre di due sorgenti luminose coerenti, cioè in fase o in opposizione di fase per un periodo sufficientemente lungo. Per ottenerle si può dirigere un fascio di luce su uno schermo su cui siano praticati due forellini molto piccoli e molto vicini: essi

Page 114: Bioidentià - Il Progetto Ottico

costituiranno le nostre due sorgenti (questo dispositivo è stato utilizzato da Young), oppure (dispositivo di Fresnel) si può considerare una superficie speculare che forma un angolo di ampiezza molto vicina ai 180deg.. Dirigendovi un fascio di luce, esso verrà riflesso come se provenisse da due sorgenti virtuali

.

In tal modo, poichè le due sorgenti derivano da una sola sorgente, le radiazioni emesse sono sempre coerenti poichè le variazioni casuali delle onde che le generano si ripercuotono su entrambe nella stessa misura. Così le condizioni di intererenza costruttiva e distruttiva sussistono per un periodo sufficientemente lungo da poter essere osservate.

L'immagine prodotta in questo modo, raccolta su uno schermo, presenta le seguenti caratteristiche: è una tipica figura di diffrazione, sovrapposta alla quale vi è una figura di interferenza costituita da una serie di sottili striscie di colore scuro, disposte perpendicolarmente rispetto al piano che contiene le sorgenti.

Se consideriamo un punto sullo schermo interessato dal fascio di luce proveniente dalle due sorgenti coerenti, si osserva

 che in tale punto si ha la condizione di interferenza costruttiva e quindi un massimo luminoso, quando la differenza delle distanze dal punto in questione dalle due sorgenti è un multiplo della lunghezza d'onda della luce.

Cioè se sono le distanze rispettive del punto P dalle

sorgenti è la lunghezza d'onda della luce, la condizione di interferenza costruttiva è

(3.1)

La condizione di interferenza distruttiva si ha invece quando si verifica:

Page 115: Bioidentià - Il Progetto Ottico

(3.2)

Infatti nell'esperimento, la differenza di fase che genera l'interferenza è dovuta proprio al fatto che le onde luminose prodotte dalla stessa sorgente segnano due cammini differenti.

Come si vede dalle formule l'interferenza dipende anche dalla lunghezza d'onda della luce.

Se si utilizzano diversi tipi di luce monocromatica, si otterranno diversi tipi di figure d'interferenza, in particolare le fasce scure di interferenza distruttiva hanno larghezza massima se si utilizza luce rossa e minima se si utilizza luce violetta.

E' anche possibile, analizzando l'ampiezza delle fasce scure, ottenere la lunghezza d'onda della luce. Infatti se chiamiamo d la distanza fra le due sorgenti coerenti, per un qualsiasi punto P sullo schermo la differenza fra i cammini effettuati dalla luce proveniente dalle due sorgenti per raggiungerlo, è data da

(3.3)

dove è l'angolo indicato in figura (3.3).

Allora la (3.2) e la (3.3) diventano:

(3.4)

Ora se è la distanza fra i due schermi e è la distanza fra il massimo di luminosità centrale (che si ottiene per k=0) e quello adiacente (per k=1), cioè l'ampiezza della prima fascia scura, si può porre:

Page 116: Bioidentià - Il Progetto Ottico

(3.5)

per cui

(3.6)

Polarizzazione

Fu solo agli inizi del 1800 che alcune importanti esperienze condotte soprattutto da Fresnel provarono una importante caratteristica delle onde luminose che era insospettata fino ad allora, cioè le onde luminose sono trasversali e non longitudinali, come quelle sonore. Ricordiamo che un'onda si dice trasversale quando lo spostamento avviene perpendicolarmente alla direzione di propagazione; si dice longitudinale se lo spostamento è parallelo alla direzione di propagazione. Tale scoperta è legata allo studio del fenomeno della polarizzazione. Abbiamo visto che la luce si forma per le vibrazioni che avvengono a livello atomico corrispondenti ad assorbimento e successiva emissione di energia. Pertanto da una sorgente luminosa vengono emessi numerosissimi treni d'onda che oscillano in differenti piani, senza che se ne possa individuare qualcuno privilegiato.

Esistono in natura alcuni materiali che hanno una sorprendente capacità. Se un raggio luminoso viene fatto passare attraverso di essi, sono in grado di riallineare tutti i piani di vibrazione dei vari treni d'onda. La luce che si ottiene in tal modo viene detta polarizzata e la sostanza utilizzata viene detta polarizzatore.

Per usare una analogia meccanica, possiamo pensare un polarizzatore come una grata composta da sbarre verticali.

Una qualsiasi lamina, che nell'analogia sta per piano di oscillazione potrà passare tra le sbarre solo se è allineata con esse (fig. (4.2)).

Page 117: Bioidentià - Il Progetto Ottico

Se consideriamo un altro elemento in grado di polarizzare la luce e lo applichiamo ad un raggio polarizzato, se esso è disposto nello stesso verso del primo polarizzatore, il raggio non subisce alcuna modificazione. Se invece facciamo ruotare il secondo polarizzatore, che per la funzione che svolge nell'esperimento chiamiamo analizzatore, l'intensità luminosa va sempre diminuendo, fino ad annullarsi completamente quando la rotazione è di 90deg.. La spiegazione di tale fenomeno è immediata se pensiamo all'analogia della grata (fig. (4.3)).

La variazione dell'intensità luminosa è epressa dalla Legge di Malus:

(4.1)

dove è l'angolo di cui è dotato l'analizzatore rispetto al

polarizzatore, e è la massima intensità finale del raggio.

La conferma del fatto che le onde luminose sono trasversali è dovuta al fatto che se ripetiamo gli esperimenti che producono l'interferenza con raggi di luce polarizzata, non si produce sullo schermo alcuna figura d'interferenza. Questa proprietà è tipica delle onde trasversali.

La natura ed il comportamento della luce ci consentono di interpretare alcuni fenomeni tramite i raggi luminosi, ognuno dei quali si può pensare come un segmento di retta che ha la direzione di propagazione del fronte d'onda.

Tale modello, noto come "ottica geometrica", fu introdotto da Keplero e costituisce una buona approssimazione della realtà ed è di estrema utilità nello studio dei fenomeni di riflessione e rifrazione, nonchè degli effetti prodotti dai vari tipi di specchi (piani, concavi e convessi) e dalle lenti.

Page 118: Bioidentià - Il Progetto Ottico

Abbiamo già utilizzato questo modello nella spiegazione del fenomeno della formazione delle ombre. Ovviamente i fenomeni interpretati mediante l'ottica geometrica possono essere spiegati anche con la teoria ondulatoria della luce sebbene con maggiore difficoltà nell'effettuare i calcoli.

Riflessione e diffusione della luce

Si consideri una sorgente luminosa che emette un raggio di luce; se esso viene proiettato su una superficie molto ben levigata, ritorna indietro come se fra il raggio e la superficie fosse avvenuto un urto elastico.

Il fenomeno descritto è la riflessione della luce ed è facilmente osservabile munendosi semplicemente di una lampadina e di uno specchio. Il raggio che parte dalla sorgente luminosa viene detto raggio incidente. Quello che esce dalla superficie riflettente si chiama raggio riflesso. L'angolo che forma il raggio riflesso con la normale alla superficie è l' angolo di riflessione.

La riflessione della luce verifica la seguente legge sperimentale, nota sotto il nome di Legge di Snellius-Cartesio:

 i) Il raggio incidente, la normale alla superficie riflettente nel punto di incidenza ed il raggio riflesso giacciono sullo stesso piano;

ii) L'angolo di incidenza è uguale all'angolo di riflessione.

Se la luce viene proiettata su una superficie non levigata, assistiamo al fenomeno della diffusione. La superficie scabra su cui si proietta il fascio luminoso può essere approssimata microscopicamente con una spezzata composta da tanti segmentini ognuno piano.

I raggi, colpendo i segmentini, vengono riflessi secondo le leggi della riflessione, ma globalmente il fascio non viene deviato uniformemente ma diffuso in tante direzioni (fig. (1.2)).

Page 119: Bioidentià - Il Progetto Ottico

Formazione dell'immagine su uno specchio

Se poniamo un oggetto di fronte ad uno specchio, osserviamo facilmente che la sua immagine viene riprodotta in una regione di spazio che sembra trovarsi all'interno dello specchio. Noi infatti normalmente abbiamo la visione di un oggetto grazie ai raggi che partendo da esso giungono in linea retta fino ai nostri occhi. Nel caso dello specchio i raggi giungono a noi dopo aver subito una riflessione, però noi percepiamo l'immagine ugualmente come se i raggi avessero viaggiato in linea retta, cioè come se l'oggetto si trovasse dall'altra parte della superficie. Tale immagine viene detta Immagine virtuale dell'oggetto.

Specchi sferici

 Una superficie riflettente a forma di calotta sferica sarà da noi chiamato specchio sferico

Se la superficie riflettente è interna alla calotta, parleremo di specchio concavo; se è esterna, di specchio convesso. Analizzeremo dapprima il comportamento dei raggi luminosi nei confronti degli specchi concavi.

Le leggi che regolano la riflessione valgono ovviamente anche nel caso degli specchi sferici. Però le normali ai diversi punti degli specchi sono disposte radialmente e non parallelamente come negli specchi piani. Questo significa che raggi paralleli che colpiscono lo specchio in due punti diversi avranno un angolo di riflessione diverso. Ciò ha come conseguenza una deformazione delle immagini riflesse dallo specchio. Tale deformazione dipenderà dalla posizione relativa dell'oggetto rispetto allo specchio.

Il centro della sfera cui la calotta riflettente appartiene viene chiamato centro di curvatura. L'asse di simmetria della calotta che passa per il centro di curvatura, si chiama asse ottico principale, mentre ogni altra retta per il centro di curvatura che incontra la superficie riflettente si chiama asse secondario (fig. (2.1.1)).

L'angolo di apertura è invece l'angolo compreso fra due rette che passano per il centro di curvatura e sono tangenti al bordo della calotta.

Page 120: Bioidentià - Il Progetto Ottico

Fissato un punto della superficie, la normale ad essa nel punto dato sarà la retta per il punto passante per il centro di curvatura; un raggio che parte dalla sorgente S posta ad esempio sull'asse ottico principale, sarà riflesso in modo che, rispetto alla normale relativa al punto, l'angolo di incidenza è uguale all'angolo di riflessione (fig. (2.1.2)).

Il raggio incidente viene riflesso in modo da intersecare l'asse principale nel punto S'. Si osserva sperimentalmente che se poniamo la sorgente luminosa in S' e consideriamo un raggio che colpisce lo specchio nel medesimo punto A (fig. (2.1.2)), il raggio riflesso intersecherà in S l'asse principale; in altre parole

 si può invertire il raggio incidente con il raggio riflesso lasciando inalterata la costruzione geometrica. Questo fenomeno costituisce il principio di reversibilità del cammino luminoso. I punti S ed S' che si individuano in questo modo costituiscono una coppia di punti coniugati.

Da qui discende l'importante conseguenza:

 Se poniamo una sorgente luminosa in S, tutti i raggi da essa uscenti saranno riflessi in modo da concorrere in S'.

Consideriamo ora un fascio di raggi tutti paralleli all'asse principale. è facile osservare, mediante la costruzione geometrica vista, ed anche sperimentalmente, che essi sono riflessi in modo da intersecare l'asse principale nello stesso punto F che prende il nome di Fuoco (fig. (2.1.3)).

Page 121: Bioidentià - Il Progetto Ottico

Se poniamo una sorgente luminosa nel fuoco di uno specchio concavo, poichè per il principio di reversibilità del cammino luminoso i raggi saranno riflessi tutti parallelamente all'asse principale, non potremo determinare per F alcun punto coniugato, a meno di considerare il punto all'infinito. Questa osservazione ci permette di definire il fuoco come il punto coniugato del punto all'infinito.

Il fuoco di uno specchio concavo viene a trovarsi, con buona approssimazione, a metà fra il centro c e la superficie riflettente. Cioè, se f è la distanza focale, ovvero la distanza del fuoco dallo specchio, si ha:

dove r è il raggio della sfera cui la calotta riflettente appartiene.

Il discorso fatto per un fascio di raggi parallelo all'asse principale, si può ripetere per un fascio parallelo ad un qualsiasi altro asse, cosicchè per ogni asse secondario si può determinare un fuoco secondario. L'insieme dei fuochi che si individuano in tal modo al variare degli assi, costituisce un piano, che si chiama piano focale. In analogia alla definizione che abbiamo dato del fuoco principale, diciamo che il piano focale di uno specchio concavo è il piano nel quale bisogna porre un oggetto luminoso per ottenere la sua immagine all'infinito (fig. (2.1.4)).

Costruzione dell'immagine di un oggetto

Page 122: Bioidentià - Il Progetto Ottico

Se poniamo un punto luminoso davanti ad uno specchio concavo, la sua immagine sarà il punto in cui concorrono tutti i raggi riflessi dallo specchio. Chiamiamo "punto oggetto" la sorgente puntiforme e "punto immagine" il corrispondente punto coniugato. Per il principio di reversibilità del cammino luminoso, è possibile scambiare il punto immagine con il punto oggetto e viceversa. Abbiamo già avuto modo di verificare che se un punto oggetto è collocato ad una distanza maggiore di 2f dalla superficie speculare, la corrispondente immagine verrà a formarsi davanti allo specchio, in un punto reale, tanto da poter essere raccolta su di uno schermo (fig. (3.1)).

Inoltre abbiamo visto che se il punto oggetto è posto esattamente nel fuoco, tutti i raggi che partono da esso vengono riflessi parallelamente, per cui diciamo che il punto immagine è posto all'infinito. L'immagine riflessa potrà essere percepita solo se i raggi riflessi "intercettano" l'osservatore, ma non può essere raccolta su uno schermo.

Vediamo ora cosa succede se l'oggetto viene posto ad una distanza minore di quella focale. In tal caso i raggi riflessi sono divergenti. Come nel caso dell'oggetto posto nel fuoco, potrà essere osservata una immagine solo se l'osservatore si trova sulla traiettoria dei raggi. Inoltre stavolta, come accade per gli specchi piani, l'immagine appare al di là della superficie riflettente, poichè essa si determina come il punto di intersezione del prolungamento dei raggi riflessi. Diremo in tal caso che l'immagine è virtuale.

Se invece di considerare un singolo punto oggetto consideriamo un oggetto di dimensioni estese, per determinare la sua immagine si dovrebbe teoricamente costruire l'immagine di ogni punto che lo compone. In pratica l'immagine si può ottenere considerando solo alcuni raggi, il cui cammino risulta di facile determinazione.

Page 123: Bioidentià - Il Progetto Ottico

Si considerano di solito i seguenti raggi:

1) quello parallelo all'asse principale, il cui raggio riflesso passa per il fuoco dello specchio;

2) quello che passa per il fuoco principale, che sarà riflesso parallelamente all'asse principale;

3) quello che passa per il centro, che in quanto coincidente con la normale, verrà riflesso su sè stesso.

Vediamo, utilizzando le figure (3.3) - (3.7), come può essere costruita l'immagine.

Il nostro oggetto sarà simboleggiato da una freccetta. Supponiamo per semplicità, che la sua base poggi sull'asse ottico principale. In tale situazione l'immagine riflessa si potrà ottenere una volta noto il punto immagine della punta della freccetta. Basterà da tale punto considerare la perpendicolare sull'asse ottico. Il segmento che l'asse taglia su questa perpendicolare costituirà l'immagine cercata del nostro oggetto.

Situazione 1: oggetto posto ad una distanza maggiore di 2f, pertanto oltre il centro.

L'oggetto appare rimpicciolito e capovolto, tra il fuoco ed il centro (fig. (3.3)).

Situazione 2: oggetto posto ad una distanza pari a 2f nel centro.

L'immagine ha le stesse dimensioni dell'oggetto, anch'essa nel centro ma capovolta (fig. (3.4)).

Situazione 3: oggetto tra il fuoco ed il centro.

Page 124: Bioidentià - Il Progetto Ottico

L'immagine è capovolta ed ingrandita, posta ad una distanza maggiore di 2f (fig. (3.5)).

Situazione 4: oggetto nel piano focale.

L'immagine risulta ingrandita al massimo, all'infinito.

Situazione 5: oggetto tra lo specchio e il fuoco.

\fig{}

L'immagine è virtuale: appare al di là dello specchio, diritta e ingrandita.

Quanto descritto vale per specchi sferici che soddisfano approssimativamente le seguenti condizioni:

1) angolo di apertura piccolo, cioè la sfera che contiene la calotta speculare è molto estesa rispetto ad essa.

2) raggi parassiali, i raggi luminosi formano con l'asse ottico angoli molto piccoli.

Se tali condizioni, dette approssimazioni di Gauss, non sono rispettate, la formazione delle immagini avviene in modo meno nitido; ciò è dovuto al fatto che un fascio di raggi luminosi paralleli all'asse ottico principale, non concorrerà esattamente nel fuoco, ma in una regione più ampia che viene chiamata superficie caustica.

Relazioni fra punti coniugati

Vediamo ora di dare una interpretazione teorica dei fenomeni descritti precedentemente. Studiamo le relazioni fra due punti coniugati, tenendo conto delle approssimazioni di Gauss.

Page 125: Bioidentià - Il Progetto Ottico

\fig{}

Come abbiamo visto, un punto oggetto S posto dinanzi ad uno specchio concavo avrà una immagine S' determinato dal punto di occorrenza di tutti i raggi che partono da S.

Se, per semplicità, il punto oggetto è collocato sull'asse principale il punto immagine si determina considerando un singolo raggio incidente e l'intersezione del raggio riflesso con l'asse ottico, poichè ogni raggio che coincide con un asse viene riflesso su sè stesso.

Sia SA il raggio incidente nel punto A della superficie speculare e AS' il segmento del raggio riflesso tagliato dall'asse principale. Per le leggi della riflessione, se CA è il segmento normale allo specchio nel punto A, gli angoli SAC e CAS' sono uguali cioè

(4.1) SAC=CAS

Come sappiamo, la bisettrice di un angolo interno di un triangolo divide il lato opposto in parti proporzionali agli altri due lati. Applicando questa regola al triangolo SAS', se ne ricava:

(4.2)

Poichè stiamo supponendo valide le approssimazioni di Gauss, esse ci consentono di utilizzare le seguenti espressioni approssimate:

(4.3)

Sostituendo la (4.3) in (4.2) si ottiene:

(4.4)

Poniamo ora la distanza VS pari a p e la distanza VS' pari a q. Da ciò ne segue

dove R è il raggio della sfera cui appartiene la calotta speculare.

Allora la (4.4) diventa:

Page 126: Bioidentià - Il Progetto Ottico

(4.5)

ovvero

(4.6)

e dividendo ogni termine per pqR, rimane:

(4.7)

ma come sappiamo la distanza focale f è pari a: f=R/2, per cui si può riscrivere la (4.7) come:

(4.8)

Vediamo quali informazioni si possono ricavare dall'analisi di tale formula:

anzitutto otteniamo una conferma del principio di reversibilità del cammino luminoso, poichè la (4.8) risulta simmetrica rispetto a p e q, per cui

 se poniamo il punto oggetto in S', la sua immagine verrà riprodotta in S.

Inoltre al crescere del valore di p, il rapporto 1/p diventa sempre più piccolo, per cui se pensiamo p infinitamente grande, 1/p tenderà a zero. In tale situazione, la (4.8) assume la forma seguente:

e ciò giustifica l'asserto che avevamo ottenuto sperimentalmente secondo il quale

 per ottenere il punto immagine nel fuoco dello specchio occorre collocare il punto oggetto ad una distanza infinita.

Page 127: Bioidentià - Il Progetto Ottico

Per converso, grazie al principio di reversibilità del cammino luminoso, un punto oggetto nel fuoco, produrrà una immagine "all'infinito". Partendo dalla (4.8) avremo

e dividendo per p sia il numeratore che il denominatore

(4.9)

dalla quale possiamo determinare le informazioni sulla distanza q dell'immagine relativamente alla distanza p dell'oggetto.

Ad esempio se , la frazione f/p sarà minore di 1 e quindi

con

Dunque

(poichè ).

Ciò esprime il fatto che

 l'immagine si forma sempre ad una distanza maggiore di quella focale se l'oggeto è posto più lontano del fuoco.

Per ottenere delle ulteriori informazioni, conviene riscrivere la (4.9) nella forma:

Page 128: Bioidentià - Il Progetto Ottico

(4.10)

che si ottiene sostituendo ad f la sua espressione rispetto ad R:

. Allora se si avrà:

ovvero

 l'immagine di un punto che si trova al di là di C apparirà in un punto fra C ed F.

Se

questo assicura che

 un punto oggetto coincide con la sua immagine se viene posto in C.

Se , per la (4.9) l'immagine sarà ad una distanza maggiore di quella focale; per la (4.10),

ovvero

 per un punto posto ad una distanza minore del raggio ma maggiore di quella focale, l'immagine si troverà ad una distanza maggiore del raggio.

Page 129: Bioidentià - Il Progetto Ottico

Infine, se il punto oggetto è collocato fra il fuoco e lo

specchio, per cui , dalla (4.9) ricaviamo:

In questo ambito il valore negativo della distanza non è assurdo, ma sta semplicemente ad indicare che

 l'immagine appare all'osservatore come se fosse dietro lo specchio, cioè è virtuale.

Le considerazioni ora esposte valgono anche se utilizziamo degli oggetti estesi. In tal caso però è utile anche indagare sull'ingrandimento o la deformazione dell'immagine dell'oggetto, già osservata sperimentalmente.

Nel modello geometrico adottato per descrivere i fenomeni, simuliamo un oggetto con una freccetta. Ci proponiamo di descrivere mediante relazioni matematiche l'allungamento o l'accorciamento che subisce l'immagine fornita dallo specchio sferico. Descriviamo cioè l' ingrandimento lineare dovuto ad uno specchio concavo.

\fig{}

I triangoli ABC e A'B'C risultano simili, per cui si ottiene:

(4.11)

Poniamo ora

AB=h e A'B'=h'.

Inoltre si osserva che B'C=q-R e CB=R-p, pertanto si ha:

(4.12)

ma per la (4.5), la (4.12) diventa:

Page 130: Bioidentià - Il Progetto Ottico

(4.13)

ovvero per la (4.9):

(4.14)

La (4.14) esprime il rapporto fra la lunghezza dell'oggetto e della sua immagine.

Come si vede, nota la distanza focale,

 il rapporto fra la lunghezza dell'oggetto e della sua immagine dipende solo dalla posizione dell'oggetto nei confronti dello specchio

Specchi convessi

Le regole della riflessione valgono ovviamente anche per gli specchi convessi.

Per determinare la traiettoria di un raggio riflesso da uno specchio convesso, occorre tenere presente che la normale alla superficie è la semiretta spiccata nel punto di riflessione e che appartiene alla retta che congiunge il punto stesso con il centro, il quale si trova stavolta dall'altra parte della superficie speculare (fig. (4.1.1)).

\fig{}

Come appare evidente dalla figura (4.1.1) il punto immagine di un qualsiasi punto oggetto posto dinanzi ad uno specchio convesso è sempre virtuale.

Se consideriamo un fascio di raggi paralleli all'asse principale, i corrispondenti raggi riflessi saranno tutti divergenti, ma in modo che i loro prolungamenti si intersecano in un punto virtuale.

Dunque

 il fuoco di uno specchio convesso è virtuale; anche tutti gli altri fuochi relativi agli assi secondari sono virtuali; si conclude allora che il piano focale di uno specchio convesso è situato dietro la superficie speculare.

Page 131: Bioidentià - Il Progetto Ottico

Se consideriamo un oggetto esteso, la sua immagine si otterrà sfruttando la stessa costruzione geometrica adoperata per gli specchi concavi. Si constata facilmente che qualunque sia il punto dove l'oggetto viene situato, la sua immagine sarà virtuale, diritta e rimpicciolita

Valgono inoltre per i punti coniugati le stesse formule ricavate nel caso degli specchi concavi, con la sola differenza che la distanza focale deve essere considerata stavolta col segno negativo.

La spiegazione della riflessione nella teoria ondulatoria

Per spiegare fisicamente il fenomeno della riflessione, assumendo la teoria corpuscolare è sufficiente supporre che le particelle che compongono la luce urtino elasticamente la superficie riflettente.

Nell'ambito della teoria ondulatoria occorre ricorrere al principio di Huygens-Fresnel. Ogni singola onda elementare che compone il fronte d'onda viene riflessa secondo la legge sperimentale prima citata. Poichè la velocità è la stessa per tutte le onde, a causa dell'inclinazione che il raggio ha rispetto alla normale, il fronte non verrà riflesso simultaneamente, ma verranno riflesse prima le onde elementari più vicine alla superficie speculare e via via le altre, cosicchè globalmente il fronte d`onde subisce la riflessione rispettando la legge secondo cui l'angolo di incidenza è uguale all'angolo di riflessione (fig. (5.1) - (5.2)).

Page 132: Bioidentià - Il Progetto Ottico

Riporta le specifiche relative alla modalità di utilizzo delle lenti della camera di ripresa.

I materiali utilizzate per le lenti possono essere di fatto vetro e plastica.

La scelta del vetro o della plastica, come materiale da utilizzare per una lente include un grosso numero di vantaggi e svantaggi per ciascuna delle due.

Il vetro è generalmente il materiale più utilizzato nell'ambito dell'ottica.

Esiste una grossa selezione di vetri disponibile con differenti gli indizi di riflessione e di dispersione.

Le lenti di vetro sono più dura e quindi anche più durature rispetto alle controparti di plastica.

Oltre a questo le lenti di vetro sono anche molto meno sensibile alla temperatura e all'umidità.

Le tecniche di costruzione utilizzate per la fabbricazione delle lenti di vetro, ad ogni modo, sono generalmente più costose comparate alle metodologie utilizzate per la costruzione delle lenti di plastica.

La tecnologia utilizzata per la costruzione comprende in genere due fasi ovvero la rottura del detto e la sua lucidatura successiva.

La scelta dei materiali per le lenti di plastica e limitata a un paio di dozzine.

I disegnatori ottici devono utilizzare un limitato numero di indizi di riparazione per permettere alla lente un miglior utilizzo di applicazione.

I ottica di plastica sono anche intolleranti alle alte temperature e quindi non devono essere utilizzate quando queste superano i 70 to 90° gradi.

Questo tipo di lente viene prodotto mediante iniezione del materiale plastico per cui rispetto alla metodologia di produzione delle lenti di vetro risulta essere molto meno costosa.

Inizialmente optammo per un tipo di CCD della National in quanto questa disponeva una risoluzione adeguata oltre ad essere un ci era molto elastico a livello di funzionalità.

Ad esempio l'azione attiva è accettabile mediante un sistema che permette che di controllare il chip.

Page 133: Bioidentià - Il Progetto Ottico

National vende anche il kit di sviluppo composto da un supporto per la CCD, un grabber e da un kit ha di lenti utilizzabile per la creazione dell'obiettivo e per sperimentazioni in campo ottico.

La prima lente è costituita da un sistema a quattro elementi di vetro a basso profilo.

Il secondo obiettivo invece è composto da un sistema al cinque lenti di vetro.

L'immagine formata da una lente è rotonda e ed è conosciuta con il termine di cerchio dell'immagine.

Page 134: Bioidentià - Il Progetto Ottico

Le alterazione patologiche dell’occhio.

Durante il periodo di addestramento relativo a tutte le nozioni necessarie per la creazione di un sistema di identificazione della retina è stato necessario anche tenere in considerazione tutte quelle patologie che ha avrebbero potuto modificare l'occhio durante il ciclo di vita dell'animale.

Un alcuni tipi di patologie sono relative alla retina mentre altre riguardano la parte esterna dell'occhio, il cristallino e la sclera.

Nel primo caso la valutazione doveva essere fatta per valutare quanto una determinata patologia avrebbe potuto modificare la configurazione di de l'immagine della retina.

Se la alterazione risulta essere contenuta entro determinate percentuali di identificazione rimane comunque possibile in quanto il software è addestrato per poter tenere in considerazione

determinati livelli di modificazione.

Ad esempio alcune tipologie di macula sono portate da patologie come ad esempio il diabete.

Alcune alterazione, invece, delle parti esterne dell'occhio causano l'impossibilità di eseguire l'identificazione in quanto quelle parti che normalmente sono trasparenti, come nel caso del cristallino, diventano opachi e quindi risulta impossibile acquisire l'immagine del fondo retinale se non dopo un intervento di tipo chirurgico.

La tipologia più conosciuta di questo tipo di alterazione della parte trasparente dell'occhio e quella legata alle catarrata.

Come possibile vedere nelle seguenti immagine questo tipo di patologia rende opaca il cristallino dell'occhio.

Le patologie più importanti della cornea sono:

Page 135: Bioidentià - Il Progetto Ottico

cheratite ulcerativa o ulcera corneale, causata da malattie batteriche, micotiche, virali e clamydiosi, traumi, corpi estranei, danni di natura chimica.

Page 136: Bioidentià - Il Progetto Ottico

Tutte le informazioni contenute in questo volume sono rigorosamente sotto © COPYRIGHT di AMC ITALY e non

possono essere distribuite o utilizzate senza permesso scritto della stessa.

QUALSIASI ABUSO SARA’ PERSEGUITO A TERMINI DI LEGGE

Versione 0.1.2

Flavio Bernardotti – [email protected] MANAGER BIOTRACCIABILITA’

© Copyright 2004 AMC ItalyVia La Pira, 21

10028 Trofarello (TO)ITALY

[email protected]

Page 137: Bioidentià - Il Progetto Ottico

INTRODUZIONE

Circa un anno fà si inizio a pensare seriamente a tutte le possibili soluzioni ai problemi che componevamno il progetto definito con il termine di BIOTRACCIABILITA’.Questo era costituito da diversi componenti tra i quali alcuni hardware e altri software.

Lo scopo di tutto il progetto era quelloi di fornire un ambiente completo che permettesse di tracciare la produzione e vendita della carne bovina in modo sicuro e autenticato.Il problema alla base di tutto era quello di trovare una particolarità biometria capace di permettere l’identificazione di un certo capo.L’unica disponibile era di fatto la retina.Questo attributo biometrico analizzato da due punti di vista era sicuramente il più complesso da gestire.La prima complicazione era di fatto l’acquisizione stessa.Essendo una parte biologica interna all’occhio dentro al quale si accede solo tramite la pupilla la prima difficoltà era proprio quella di progettare una telecamera capace di fare questo tipo di acquisizione.

Page 138: Bioidentià - Il Progetto Ottico

La seconda complicazione era di fatto quella algoritmica legata al sistema di identificazione.In altre parole il problema è abbinato alla domanda :

Come confrontare due retine per affermare che si tratta di quella relativa ad una mucca o no ?

Sin dall’inizio il problema è subito apparso essere collegato all’informatica che si interessa dell’identificazione di oggetti all’interno di immagini composte.Questa scienza di fatto è composta da un infinità di teorie, alcune applicabili al nostro problema e altre no.La complicazione di fatto è stata quella che per poter dire se il problema era risolvibile in un modo o in un altro si doveva, dopo aver ipotizzato la soluzione, eseguire delle prove mediante i linguaggi o le librerie adatte.Tutto questo si è risolto in un lungo periodo di ricerca e sviluppo durante il quale ho :

Raccolto informazioniIpotizzato soluzioniScritto programmi

In questo volume ho raccolto tutto il percorso tecnologico legato allo sviluppo della soluzione informatica del riconoscimento retinale.Le soluzioni sono riportate ad una certa versione è saranno soggette alle modifiche che le ricerche e lo sviluppo indurranno.Il tutto serve a testimoniare e a mantenere il livello culturale a cui il lavoro relativo al problema ci ha condotto.

Page 139: Bioidentià - Il Progetto Ottico

Premessa

Identificare una retina per accertare l’identità di un capo animale dopo averla ripresa dinamicamente da una telecamera è una funzione per la quale diventa necessario utilizzare diverse metodologie informatiche a partire dai sistemi di reti neurali per giungere sino a quelli che vengono definiti con il termine di HIDDEN MARKOV MODELLS (modelli di Markov nascosti e ibridi neurali/markoviani).Tutte queste tecnologie sono considerate avanzate e se considerate dal punto di vista algoritmico sono anche complicate da scrivere e mettere a punto.Le tipologie di problemi sono quelli legati alla COMPUTER VISION.La computer vision è quella branca dell’informatica che si interessa di implementare funzionalità proprie dell’interpretazione visiva umana.Per svolgere queste funzioni ci si avvale di parti di software algoritmico e di altre legate a sistemi che riproducono le reti neurali.Alcune funzionalità che a volte sembrano molto semplici da svolgere a “vista” di fatto se analizzate dal punto di vista algoritmico possiedono complicazioni notevoli.Per questo motivo spesso lo svolgimento di tali funzioni vengono eseguite mediante sistemi misti che utilizzano parti algoritmiche e parti a reti neurali.Le reti neurali riproducono mediante un modello matematico il funzionamento del cervello umano simulando I modelli relativi a neuroni, sinapsi e dendridi.Tali sistemi mettono a punto la loro ‘intelligienza’Un sottoinsieme della computer vision e quella definita con il termine di object recognition il cui compito è quello di identificare, all’interno di un immagine che riproduce il nostro spazio reale, degli oggetti particolari.Collegate alle teorie dell’object recognition troviamo moltissime metodologie algoritmiche che permettono lo svolgimento di compiti particolari come ad esempio la segmentazione delle immagini.Vedremo alcuni concetti nei capitoli che seguono.Alcuni tipi di valutazioni legate all’individuazione di una metodologia da applicare con la retina erano sorte dalla necessità di estraniarsi da valutazioni di tipo geometrico-spaziale le quali, come vedremo successivamente, non possono essere eseguite per alcuni precisi motivi.Solo per accennare a quelli che sono i problemi legati all’identificazione di una retina possiamo riportare la diversità tra una ripresa e l’altra legata semplicemente al modo di tenere la camera di acquisizione da parte dell’operatore.Questo semplice problema inizialmente ci fece capire che determinati metodi di confronto delle immagini utilizzanti dati spaziali e geometrici non potevano essere utilizzati.Trovandosi davanti al problema di confrontare due immagini il metodo più semplice ed immediato dovrebbe essere quello RAW ovvero

Page 140: Bioidentià - Il Progetto Ottico

il confronto diretto di ogni singolo pixel dell’immagine.

E’ == ?Purtroppo questo per il motivo appena detto e per altri che vedremo successivamente non può essere utilizzato.Il principio della ricerca venne orientata verso quelle che erano le metodologie utilizzate per altri sistemi biometrici.L’impronta digitale possedeva alcune caratteristiche che avrebbero potuto essere simili ai problemi presenti con la retina.L’immagine acquisita di un dito avrebbe ipoteticamente essere differente tra una ripresa e l’altra.Nel caso dell’impronta digitale ad esempio vengono utilizzate metodologie per la segmentazione dinamica dell’immagine dell’impronta e successivamente calcolando il centro di ogni oggetto segmentato viene creato un poligono il quale verrà successivamente utilizzato per il confronto.In questo caso il procedimento software, una volta eseguite tutte le calibrazioni necessarie, serve ad informare il programma su quali oggetti dell'immagine noi vogliamo che egli esegua l'analisi. La parola oggetto è usata per identificare ogni regione di interesse all'interno dell'intera immagine. Per segmentazione dell'immagine si intendono tutti quei passaggi che consentono una descrizione dettagliata degli oggetti stessi come il numero di pixels costituenti l'oggetto e le loro coordinate, tutte le informazioni necessarie a tracciare i loro contorni ecc.. Ogni oggetto viene quindi identificato per mezzo di un set descrittivo di dati che vengono memorizzati e successivamente impiegati per le operazioni di misura sugli oggetti stessi.

Page 141: Bioidentià - Il Progetto Ottico

In questo caso le zone in cui vengono successivamente applicate le funzioni di segmentazione sono delimitate dai flussi delle tracce dell’impronta.

Sicuramente un algoritmo che venne preso in considerazione era quello relativo all’iride.In questa metodologia di fatto esistono molti metodi che potrebbero essere utilizzati anche per quanto riguarda la retina.L’immagine iridea viene acquisita da una telecamera e successivamente mediante una trasformata WAVELET vengono estratti dei particolari.

L’immagine catturata contiene solo una parte interessata all’elaborazione e precisamente quella indicata nell’immagine qui a fianco.Questa porzione deve essere estratta e riportata ad un immagine rettangolare in cui esistono solo le informazioni della zona relativa all’iride.

Page 142: Bioidentià - Il Progetto Ottico

In una seconda fase la ricerca venne indirizzata per somiglianza di problema.In altre parole se si guarda un immagine di una retina di fatto sembra di vedere una traccia fluviale presa da un immagine satellitare.Anche in questo caso l’acquisizione potrebbe rendere un immagine ruotata, zoomata ecc.

I percorsi fluviali possono essere in piena o con il fiume in secca.

Dicevamo prima dei problemi legati alle diverse immagini acquisite in tempi differenti.Per capire I problemi bisogna pensare all’operatore quando esegue l’acquisiizione.In pratica avviene quanto segue :

1 - L’operatore si mette davanti al capo animale e punta con la telecamera l’occhio della mucca. Ad un certo punto nel visore comparirà l’immagine della retina. Il software deve essere in grado di capire quando l’immagine è corretta e quindi deve eseguire il ritaglio della porzione interessata all’operazione di riconoscimento.

2 - L’immagine ritagliata deve essere identificata tra quelle esistenti

Come dicevamo prima tali operazioni possono essere classificate tra quelle definite con il termine di OBJECT RECOGNITION.In effetti la retina non è un oggetto reale ma ad ogni modo possiede caratteristiche tali da poter essere considerata un oggetto astratto dotato di proprie caratteristiche strutturali che gli permettono di essere distinta da altri oggetti appartenenti al background dell’immagine.Il sistema software potrebbe essere considerato come indirizzato a risolvere quattro funzioni particolari:

Regolazione e calibrazione telecamera Creazione parametrizzazioni e training classificatori Gestione dell’identificazione della retina Acquisizione e riconoscimento

Nella prima fase si tratta solo di identificare una retina all’interno dell’immagine mentre nella seconda fase l’identificazione non può essere generalizzata.In altre parole la prima parte del programma dovrà essere in grado di identificare una retina generica in modo tale da poter delimitare la zona di immagine in cui questa è inclusa.La progettazione del software deve tenere conto di diverse problematiche tra le quali le diversità che possono esserci tra le

Page 143: Bioidentià - Il Progetto Ottico

varie immagini provenienti da acquisizione fatte in tempi differenti.Tali differenze possono essere di tipo cromatico e di tipo spaziale-geometrico.Le differenze cromatiche possono essere causate da cambiamenti del tappeto retinale dovuto all’età del capo.

Le differenze geometrico-spazali invece potrebbero essere indotte da patologie particolari come anche solo una differente pressione sanguigna.Per questo motivo ci troviamo nella necessità di individuare un metodo di riconoscimento in grado di ignorare o perlomeno minimizzare tali effetti collegati alla metodologia di ripresa:

1 - L’angolatura dell’immagine retinale può essere ruotata verso destra o verso sinistra a causa della posizione della camera stessa nelle mani dell’operatore.

2 - L’immagine può essere dimensionalmente differente a causa della diversa distanza di ripresa.

3 - Le trame venose possono essere più o meno marcate a causa di iper/ipo tensione venosa.

4 - La trama potrebbe essere leggermente differente a causa di alcune patologie.

5 - Il colore di fondo potrebbe essere differente anche solo a causa dell’invecchiamento del capo.

In senso generale il problema è da risolvere con una delle metodologie legate all’object recognition le quali si basano sullo schema che segue.

Il progetto si sarebbe potuto affrontare in molti modi mediante l’utilizzo di reti neurali e di classificatori.Nell’ambito della cultura informatica legata alla computer vision esistono infinite teorie e metodi indirizzati alla soluzione di

Page 144: Bioidentià - Il Progetto Ottico

questo tipo di problemi.Nel limite del possibile tutte le ricerche sono state indirizzate per individuare un pacchetto di libreria che disponesse al suo interno delle funzioni idonee ad eseguire tutte le funzionalità richieste.Considerando nuovamente le due fasi in cui vengono prima individuate I Sistemi di Classificatori Multipli (MCS) si basano sulla combinazione delle uscite di un insieme di classificatori differenti. Se si progetta una funzione di combinazione appropriata, e se i classificatori dell'insieme commettono errori "diversi", un MCS consente di ottenere una maggiore accuratezza di classificazione.Ogni classificatore automatico è caratterizzato da una probabilità d'errore intrinseca (errore bayesiano), che può essere ridotta con tecniche di rigetto. Il rigetto consiste nella possibilità di non eseguire la classificazione automatica di un pattern se questa risultasse troppo incerta: il costo del trattamento "manuale" di un pattern rigettato può infatti essere inferiore al costo di una classificazione errata (si pensi al caso della classificazione automatica di patologie per scopi di diagnosi medica).La regola di classificazione (regola di Chow) che consente di ottenere il compromesso ottimale tra probabilità d'errore e di rigetto è basata sull'uso di una soglia di rigetto sui valori delle probabilità a posteriori delle classi. La regola di Chow è ottimale se tali probabilità sono note con esattezza. Tuttavia in applicazioni pratiche i classificatori forniscono solo stime delle probabilità a posteriori.Un termine non ancora riportato è quello legato alla pattern recognition in cui alcune metodologie algoritmiche vengono utilizzate per il riconoscimento e l’estrazione di particolari da un immagine.Il Pattern Recognition è la disciplina scientifica che si occupa delle teorie e dei metodi per la progettazione di macchine in grado di riconoscere automaticamente "oggetti" in dati complessi.Alcune tipiche applicazioni sono il riconoscimento di caratteri manoscritti, la classificazione di immagini telerilevate, l'identificazione di persone sulla base di caratteristiche biometriche come le impronte digitali.

Page 145: Bioidentià - Il Progetto Ottico

Gli ambienti di sviluppo

Il sistema è composta da un certo numero di moduli funzionali i quali possiedono determinate caratteristiche e particolarità tali da essere canditati idonei per determinati sistemi di sviluppo.La prima scelta da fare era quella legata al sistema operativo utilizzato nell’ambiente hardware scelto.

Molti modelli di POCKET PC utilizzano sistemi operativi particolari, spesso proprietari.La nostra scelta è andata verso un sistema palmare dotato di WINDOWS CE il quale possiede una certo numero di scelta per tutto quello che riguarda il software utilizzabile.Le scelte software sono, ad ogni modo, indirizzate

a risolvere due tipi di problemi fondamentali.

1 – Linguaggio di programmazione2 – Librerie di sviluppo

Come abbiamo accennato precedentemente la teoria per la scrittura dell’algoritmo di riconoscimento pretende per l’individuazione in un background di un immagine retinale l’uso di classificatori HAAR opportunamente istruiti mediante un periodo di training.INTEL fortunatamente ha messo a disposizione una libreria scientifica indirizzata alla gestione delle immagini in cui molte funzioni sono già implementate e quindi l’uso di questa permette di omettere la creazione di moduli software molto complessi sia dal punto di vista concettuale che da quello della scrittura e della messa a punto.Per la scrittura di tale software sono quindi utilizzati i seguenti sistemi di sviluppo :

MICROSOFT VISUAL C++ 6.0 MICROSOFT EMBEDDED VISUAL C++ 4.0 per Windows CE OPENCV INTEL IMAGE PROCESSING LIBRARY INTEL MICROSOFT DIRECT X

Il metodo di programmazione è legato al C++ per ambiente WINDOWS utilizzando le classi MFC (Microsoft Foundation Class).In altre parole le problematiche legate alla gestione dell’interfaccia utente devono essere risolte con le API (Application Programming Interface) specifiche del sistema operativo scelte.Nel caso di WINDOWS le API sono generalmente presenti all’interno del SDK.Tali funzioni sono state successivamente incapsulate all’interno di classi da parte di MICROSOFT la quale ha dato il nome di MICROSOFT FOUNDATION CLASS a queste.L’uso del C++ in ambiente WINDOWS è stato dettato dalla scelta del sistema operativo WINDOWS CE utilizzato per la gestione del

Page 146: Bioidentià - Il Progetto Ottico

palmare operativo.

L’uso del sistema di sviluppo MICROSOFT permette di utilizzare il Microsoft Visual C++ in ambiente Windows XP e Visual C++ 4.0 in ambiente Windows CE senza apportare modifiche al software se non quelle relative alla gestione dell’interfaccia utente.Uno dei fattori che hanno indirizzato la scelta della libreria di sviluppo è stata la sua portabilità e quindi la sua distribuzione con tanto di sorgenti.La gestione delle immagini può essere considerata a due livelli.In quello definito “Basso livello” troviamo tutte quelle funzioni che servono per la gestione dell’immagine mediante funzioni come quelle legate alla lettura,m alla scrittura o a quelle modifiche geometriche e cromatiche della stessa.Questa tipologia di funzioni è gestita mediante la libreria INTEL IPL.Questa liberia faceva parte di quelle che INTEL distribuiva mediante la filosofia OPEN SOURCE.Da un po’ di tempo tale libreria è stata soppiantata da un'altra libreria INTEL e precisamente IPP.Le funzioni indirizzate alle immagini a più alto livello sono presenti dentro alla libreria OPENCV.Questa per tutte le funzioni come ad esempio la lettura di un immagine da disco si supporta su IPL o su IPP.E’ sufficiente l’uso di una delle due librerie.In effetti le librerie si supportano gerarchicamente una sull’altra.Non esiste nell’ambito del sistema di riconoscimento retinale un accenno direttoAlcuni software li ho creati utilizzando il sistema di sviluppo Visual Studio .NET, l’ultima versione del compilatore di casa

Page 147: Bioidentià - Il Progetto Ottico

Microsoft.Il sistema di sviluppo possiede, a parte maggiori funzionalità legate all’aspetto della progettazione, alcune estensioni del C++ particolarmente utili per quanto riguarda la stesura del progetto di riconoscimento.

Page 148: Bioidentià - Il Progetto Ottico

Gli studi iniziali.

Come abbiamo detto precedentemente all’inizio si è cercato di individuare i metodi corretti per poter eseguire il confronto di immagini provenienti da acquisizioni fatte in tempi differenti.Un immagine possiede molti tipi di attributi, alcuni che si notano immediatamente ed altri invece che derivano da metodologie di valutazione.Un immagine digitale è di fatto un insieme di pixels i quali possiedono determinate coordinate spaziali descritte dal valore di X e Y e da un codice di colore.Per questo motivo la descrizione di un immagine, e quindi i metodi per confrontare una con un'altra, può avvenire mediante le proprie proprietà spaziali-geometriche ma anche mediante caratteristiche legate alle proprie proprietà cromatiche.I primi moduli software scritti avevano come scopo quello di

valutare come caratteristiche alternative a quelle spaziali-geometriche potessero avere un determinato livello di elasticità nei confronti di modifiche fatte alla stessa immagine.Determinate teorie alla base di quella disciplina definita con il termine di IMAGE RETRIEVAL utilizzano valori come quelli relativi agli istogrammi calcolati su certi tipi di valori come base per

l’esecuzione delle interrogazioni, o query, indirizzate a identificare certe immagini in mezzo a molte altre.Un esempio di tale uso è il sistema IBM chiamato QBIC.Un altro metodo utilizzato per calcolare le differenze tra immagini è quello basato sulla metodologia PCA (Principal Component Analysis).L'analisi delle componenti principali o trasformata di Karhunen-Loéve effettua un mapping lineare tra un insieme di vettori multidimensionali ed uno spazio di dimensione minore in modo tale da minimizzare la somma dei quadrati degli errori commessi approssimando i vettori originari con quelli ottenuti rimappando sullo spazio di partenza i vettori dello spazio di dimensionalità minore.

Page 149: Bioidentià - Il Progetto Ottico

Tale programma è stato scritto utilizzando le funzioni di OpenCV.

#include "stdafx.h"

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){

#include "stdafx.h"#include "cv.h" // include core library interface#include "highgui.h" // include GUI library interface#include "Recog.h"#include <stdio.h>#include <cmath>#include <string.h>#include <ctime>

int main(){

const int n = 6; // number of images usedconst int nEigens = n-1; // number of eigen objsint i, j, k, digit = 6;char name[30] = "../pca1.bmp"; // 6 bmp imageschar nums[7] = "012345"; // each image has a different numberdouble max, val, dist; // dist between images in nEigens-d

spaceFILE* outFile; // file to store resultsCvMemStorage* storage = cvCreateMemStorage(0);

IplImage* images[n]; // input imagesIplImage* eigens[nEigens]; // eigenobjectsIplImage* proj[n]; // decomposed object projection

to the eigen sub-spaceIplImage* avg; // averaged objectCvTermCriteria criteria; // criteria to stop calculating eigen

objectsfloat vals[nEigens]; // eigenvaluesfloat coeffs[n][nEigens]; // decomposition coefficientsfloat normCoeffs[n][nEigens]; // normalised coefficients

cvvNamedWindow( "projections", 1);cvvNamedWindow( "images", 1);

// ************initialise variables************if((outFile = fopen("values.txt", "w")) == NULL)

printf(" error creating file\n");

for( i=0; i<n; i++ ){name[digit] = nums[i]; / // get file name of

images

IplImage* temp = cvvLoadImage( name ); // load images into IplImage objects

images[i] = cvCreateImage( cvGetSize( temp ), IPL_DEPTH_8U, 1 );

Page 150: Bioidentià - Il Progetto Ottico

cvCvtColor( temp, images[i], CV_BGR2GRAY );cvReleaseImage( &temp );

cvvShowImage( "images", images[i] );cvvWaitKey(0);

proj[i] = cvCreateImage( cvGetSize( images[0] ), IPL_DEPTH_8U, 1 );}

for( i=0; i<nEigens; i++ )eigens[i] = cvCreateImage( cvGetSize( images[0] ), IPL_DEPTH_32F,

1 );

avg = cvCreateImage( cvGetSize( images[0] ), IPL_DEPTH_32F, 1 );criteria.type = CV_TERMCRIT_ITER|CV_TERMCRIT_EPS;

criteria.maxIter = 10; criteria.epsilon = 0.1;

// ************calc eigenobjects & eigenvals************cvCalcEigenObjects( n, images, eigens, 0, 0, 0, &criteria, avg, vals );

fprintf(outFile, "eigenvalues\n" );

for( i=0; i<nEigens; i++ )fprintf(outFile, "%15.2lf\n", vals[i] );

// ************calc decomposition coefficients************fprintf(outFile, "decomposition coefficients\n" );

for( i=0; i<n; i++ ){cvEigenDecomposite( images[i], nEigens, eigens, 0, 0, avg, coeffs[i]

);

fprintf(outFile, "obj:%d\t", i );

for( j=0; j<nEigens; j++ )fprintf(outFile, "%25.2lf", coeffs[i][j] );

fprintf(outFile, "\n" );}

// ************normalise decomposition coefficients************for( i=0; i<nEigens; i++ ){

max = -100000.00;

for( j=0; j<n; j++ ){val = fabs( coeffs[j][i] );

if( val > max )max = val;

}for( j=0; j<n; j++ )

normCoeffs[j][i]=coeffs[j][i]/max;}

fprintf(outFile, "decomposition coefficients-normalised\n" );

for( i=0; i<n; i++ ){

Page 151: Bioidentià - Il Progetto Ottico

fprintf(outFile, "obj:%d\t", i );

for( j=0; j<nEigens; j++ )fprintf(outFile, "%7.2lf", normCoeffs[i][j] );

fprintf(outFile, "\n" );}

// ************compare vectors************for( i=0; i<n; i++ ){

fprintf(outFile, "\nvector %d\n", i );

for( j=i+1; j<n; j++ ){dist = 0;

for( k=0; k<nEigens; k++ )dist += fabs( normCoeffs[i][k] - normCoeffs[j][k] );

fprintf(outFile, "%d:\tdist = %10.5lf\n", j, dist );}

}

// ************calc projection into the eigen subspace************for( i=0; i<n; i++ )

cvEigenProjection( eigens, nEigens, 0, 0, coeffs[i], avg, proj[i] );

for( i=0; i<n; i++ ){cvvShowImage( "projections", proj[i] );cvvWaitKey(0);

}for( i=0; i<n; i++ ){

cvReleaseImage( &images[i] );cvReleaseImage( &proj[i] );

}

for( i=0; i<nEigens; i++ )cvReleaseImage( &eigens[i] );

cvReleaseImage( &avg );

cvClearMemStorage( storage );

return 0;}

L’utilizzo della libreria OPENCV si basa a sua volta sulla libreria grafica dell’INTEL IPL ovvero Image Processing Library.In questa libreria sono supportate le funzioni di base relative alla gestione delle immagini a basso livello.Infatti all’interno di OPENCV non sono presenti funzioni indirizzate all’eleborazione delle immagini.Ad ogni modo mediante l’utilizzo delle due librerie permette qualsiasi tipo di elaborazione grafica sia indirizzata alla modifica delle caratteristiche geografiche e cromatiche dell’immagine che a quelle funzioni che possono essere considerate ad un livello di astrazione superiore.Medi9ante l’uso delle due librerie sarebbe possibile creare un programma di TEMPLATE MATCHING con pochissime linee di programma.

Page 152: Bioidentià - Il Progetto Ottico

E’ un esempio quello che segue.

#ifdef _CH_#pragma package <opencv>#endif

#ifndef _EiC#include "cv.h"#include "highgui.h"#include <stdio.h>#endif

IplImage *Lena = 0;// Main Source ImageIplImage *Lena_Color = 0;IplImage *sonuc = 0;// Names's of windowschar barname01[] = "Threshold";char wndname1[]="BINARY";char wndname2[]="BINARY INV";char wndname3[]="TRUNC";char wndname4[]="TO ZERO";char wndname5[]="TO ZERO INV";

/*******/CvPoint pp1, pp2;//points for min & max valuesdouble minVal, maxVal;// min & max values/*******/

int main( int argc, char** argv ){

Lena = cvLoadImage( "lena.bmp",0);Lena_Color = cvLoadImage( "lena.bmp",3);IplImage *arama = cvLoadImage( "lena_ara.bmp",0);// Create Windows for each image.cvNamedWindow("Lena", CV_WINDOW_AUTOSIZE);cvNamedWindow("CV_TM_SQDIFF_NORMED", CV_WINDOW_AUTOSIZE);cvNamedWindow("CV_TM_CCORR", CV_WINDOW_AUTOSIZE);cvNamedWindow("CV_TM_CCORR_NORMED", CV_WINDOW_AUTOSIZE);cvNamedWindow("CV_TM_CCOEFF", CV_WINDOW_AUTOSIZE);cvNamedWindow("CV_TM_CCOEFF_NORMED", CV_WINDOW_AUTOSIZE);cvNamedWindow("CV_TM_SQDIFF", CV_WINDOW_AUTOSIZE);cvNamedWindow("Aranan", CV_WINDOW_AUTOSIZE);int a = Lena->width;int b = Lena->height;int a2 = arama->width;int b2 = arama->height;sonuc = cvCreateImage( cvSize(a - a2 + 1,b - b2 +1),IPL_DEPTH_32F ,1);cvShowImage( "Aranan",arama);// Display imageIplImage *Thresh_Sonuc5 = cvCreateImage( cvSize(a - a2 + 1,b - b2

+1),IPL_DEPTH_32F ,1);IplImage *Thresh_Sonuc1 = cvCreateImage( cvSize(a - a2 + 1,b - b2

+1),IPL_DEPTH_32F ,1);IplImage *Thresh_Sonuc2 = cvCreateImage( cvSize(a - a2 + 1,b - b2

+1),IPL_DEPTH_32F ,1);IplImage *Thresh_Sonuc3 = cvCreateImage( cvSize(a - a2 + 1,b - b2

+1),IPL_DEPTH_32F ,1);IplImage *Thresh_Sonuc4 = cvCreateImage( cvSize(a - a2 + 1,b - b2

+1),IPL_DEPTH_32F ,1);IplImage *Thresh_Sonuc6 = cvCreateImage( cvSize(a - a2 + 1,b - b2

+1),IPL_DEPTH_32F ,1);

//cvCreateTrackbar( barname01, "Lena", &slider_pos[0], 255,

Page 153: Bioidentià - Il Progetto Ottico

my_threshold );cvMatchTemplate( Lena, arama,Thresh_Sonuc1, CV_TM_SQDIFF );cvMinMaxLoc(Thresh_Sonuc1, &minVal, &maxVal, &pp1, &pp2);// Find min and max locations in prob. denstiy image.//cvCircle( Lena_Color, pp1, 15, CV_RGB(255,0,0),1 );cvCircle( Lena_Color, pp2, 15,CV_RGB(0,0,255), 1 );// draw circle at pos. w/ max probablity.

cvShowImage( "CV_TM_SQDIFF", Thresh_Sonuc1);// Other ways of doing this. :)/*cvMatchTemplate( Lena, arama,Thresh_Sonuc2, CV_TM_SQDIFF_NORMED );cvShowImage( "CV_TM_SQDIFF_NORMED", Thresh_Sonuc2);

cvMatchTemplate( Lena, arama,Thresh_Sonuc3, CV_TM_CCORR );cvShowImage( "CV_TM_CCORR", Thresh_Sonuc3);

cvMatchTemplate( Lena, arama,Thresh_Sonuc4, CV_TM_CCORR_NORMED );cvShowImage( "CV_TM_CCORR_NORMED", Thresh_Sonuc4);

cvMatchTemplate( Lena, arama,Thresh_Sonuc5, CV_TM_CCOEFF );cvShowImage( "CV_TM_CCOEFF", Thresh_Sonuc5);

cvMatchTemplate( Lena, arama,Thresh_Sonuc6, CV_TM_CCOEFF_NORMED );cvShowImage( "CV_TM_CCOEFF_NORMED", Thresh_Sonuc6);*/cvShowImage( "Lena", Lena_Color);

cvWaitKey( -1 );

return 0;}

#ifdef _EiCmain(1,"main.cpp");#endif

Nei capitoli legati ai concetti di base sono stati visti alcuni algoritmi come ad esempio quello legato alla definizione dei contorni delle immagini.In alcuni casi le prove fatte hanno utilizzato le funzioni di OPENCV mentre in altri casi ho utilizzato programmi a se stanti.In effetti la scelta di OPENCV è stata fatta dopo un certo tempo dopo aver provato moltissime soluzioni.Alcune volte il linguaggio con cui ho scritto i moduli di prova era JAVA e non C++.Il seguente è un esempio di programma indirizzato alla creazione dei contorni di un oeggto dentro ad un immagine.

/* * contour.c * */

/* CONTOUR: program determines contour boundaries for binary image * usage: contour infile.img outfile.img * */

#include <stdio.h>

Page 154: Bioidentià - Il Progetto Ottico

#include <string.h>#include <stdlib.h>#include "tiffimage.h" /* picfile info on images */#include "images.h"extern void print_sos_lic ();

#define ON 0 /* binarization values */#define OFF 255#define ONM1 1#define CONTOUR 32 /* value of contour pixel */#define CENTROID 31 /* value of centroid location pixel */#define MAX_CONTOUR 10000 /* maximum length of contour */#define DISPLAY_FLAG_DFLT 0 /* =0 contours; =1 centroids; =2 both */

#define SQUARE(IMG,X,Y) IMG[Y][X] = ONM1, IMG[Y-1][X-1] = ONM1,\ IMG[Y-1][X] = ONM1, IMG[Y-1][X+1] = ONM1,\ IMG[Y][X+1] = ONM1, IMG[Y+1][X+1] = ONM1,\ IMG[Y+1][X] = ONM1, IMG[Y+1][X-1] = ONM1,\ IMG[Y][X-1] = ONM1

int nextcntr (unsigned char **, long *, long *, long *);long usage (short);long input (int, char **, long *, short *, short *);

main (argc, argv) int argc; char *argv[];{ Image *imgIO; /* I/O image structure */ unsigned char **image; /* input/output image */ long height, width; /* size of I/O images */ long xEndM1, yEndM1; /* end of rows/columns minus one */ struct cntr { /* structure for each contour pt */ long x, y; /* location */ long iDirn; /* chain code direction */ long curve; /* local curvature */ } *cntr; long maxContour; /* max. contour length (for memory alloc.) */ short displayFlag; /* =0 contours; =1 centroids; =2 both */ short printFlag; /* =1 print contour info; =0 don't */ long nContour; /* number of contours */ long lContour; /* length of contour */ long maxLContour; /* max. length of contour */ long lContourSum; /* sum of contour lengths */ double xCentroid, yCentroid; /* x,y centroid location for contour */ long xStart, yStart; /* starting pixels of contour */ long iDirn; /* direction coming into contour */ long x, y; long temp;

/* user input */ if (input (argc, argv, &maxContour, &displayFlag, &printFlag) < 0) return (-1);

imgIO = ImageIn (argv[1]); image = imgIO->img; height = ImageGetHeight (imgIO); width = ImageGetWidth (imgIO); printf ("image size is %dx%d\n", width, height);

/* allocate contour memory */ if ((cntr = (struct cntr *) calloc (maxContour, sizeof (struct cntr)))

Page 155: Bioidentià - Il Progetto Ottico

== NULL) { printf ("CONTOUR: not enough memory -- sorry.\n"); return (-1); }

/* determine contours */ yEndM1 = height - 1; xEndM1 = width - 1; nContour = 0; maxLContour = 0; lContourSum = 0; for (y = 1; y < yEndM1; y++) { for (x = 1; x < xEndM1; x++) { /* when find ON-pixel, trace contour */ if (image[y][x] == ON && image[y][x - 1] == OFF) { nContour++; iDirn = 2; cntr[0].x = xStart = x; cntr[0].y = yStart = y; xCentroid = (double) x; yCentroid = (double) y; cntr[0].iDirn = iDirn; cntr[0].curve = 0; lContour = 1; do { image[y][x] = CONTOUR; nextcntr (image, &x, &y, &iDirn); cntr[lContour].x = x; cntr[lContour].y = y; cntr[lContour].iDirn = iDirn; xCentroid += (double) x; yCentroid += (double) y; temp = iDirn - cntr[lContour - 1].iDirn; if (temp > 4) temp -= 8; else if (temp < -4) temp += 8; cntr[lContour].curve = temp; lContour++; if (lContour == MAX_CONTOUR) { printf ("Nuts -- maximum contour length reached = %d\n", lContour); return (-1); } } while (!(x == xStart && y == yStart)); if (lContour > maxLContour) maxLContour = lContour; xCentroid = xCentroid / (double) lContour; yCentroid = yCentroid / (double) lContour; lContourSum += lContour; if (displayFlag > 0) image[(long) (yCentroid + 0.5)][(long) (xCentroid + 0.5)] = CENTROID; if (printFlag != 0) printf ("contour %ld: length = %ld, centroid = (%5.2f,%5.2f)\n", nContour - 1, lContour, xCentroid, yCentroid); } } }

switch (displayFlag) { case 0: for (y = 0; y < height; y++) for (x = 0; x < width; x++)

Page 156: Bioidentià - Il Progetto Ottico

image[y][x] = (image[y][x] == CONTOUR) ? ON : OFF; break; case 1: for (y = 0; y < height; y++) for (x = 0; x < width; x++) { if (image[y][x] == CENTROID) SQUARE (image, x, y); else if (image[y][x] == ONM1); else image[y][x] = OFF; } break; case 2: for (y = 0; y < height; y++) for (x = 0; x < width; x++) { if (image[y][x] == CENTROID) SQUARE (image, x, y); else if (image[y][x] == CONTOUR) image[y][x] = ON; else if (image[y][x] == ONM1); else image[y][x] = OFF; } break; default: for (y = 0; y < height; y++) for (x = 0; x < width; x++) image[y][x] = (image[y][x] == CONTOUR) ? ONM1 : OFF; }

if (nContour == 0) printf ("no image regions\n"); else printf ("no. contours = %d, max length = %d, avg. length = %d\n", nContour, maxLContour, lContourSum / nContour);

ImageOut (argv[2], imgIO);

return (0);}

/* NEXTCNTR: function examines neighborhood for next contour pixel */

intnextcntr (image, x, y, iDirn) unsigned char **image; long *x, *y; /* temporary x and y storage for trace */ long *iDirn; /* direction from last pixel on contour */{ long ring[16]; /* neighborhood ring of pixels */ long i, j;

/* find neighborhood ring of pixels */ ring[0] = ring[8] = image[*y - 1][*x]; ring[1] = ring[9] = image[*y - 1][*x + 1]; ring[2] = ring[10] = image[*y][*x + 1]; ring[3] = ring[11] = image[*y + 1][*x + 1]; ring[4] = ring[12] = image[*y + 1][*x]; ring[5] = ring[13] = image[*y + 1][*x - 1];

Page 157: Bioidentià - Il Progetto Ottico

ring[6] = ring[14] = image[*y][*x - 1]; ring[7] = ring[15] = image[*y - 1][*x - 1];

i = (*iDirn + 4 + 1) % 8;

for (j = 0; j < 8; j++, i++) if (ring[i] != OFF && ring[i - 1] == OFF) break;

if (j == 8) return (0); /* isolated pixel */

*iDirn = i % 8;

switch (i) { case 1: case 9: *x = *x + 1; *y = *y - 1; break; case 2: case 10: *x = *x + 1; break; case 3: case 11: *x = *x + 1; *y = *y + 1; break; case 4: case 12: *y = *y + 1; break; case 5: case 13: *x = *x - 1; *y = *y + 1; break; case 6: case 14: *x = *x - 1; break; case 7: case 15: *x = *x - 1; *y = *y - 1; break; case 8: case 0: *y = *y - 1; break; default:; }

return (0);}

/* USAGE: function gives instructions on usage of program * usage: usage (flag)

Page 158: Bioidentià - Il Progetto Ottico

* When flag is 1, the long message is given, 0 gives short. */

longusage (flag) short flag; /* flag =1 for long message; =0 for short message */{

/* print short usage message or long */ printf ("USAGE: contour inimg outimg [-d DISPLAY] [-p] \n"); printf (" [-m MAX_CONTOUR_LENGTH] [-L]\n"); if (flag == 0) return (-1);

printf ("\ncontour identifies contours, or boundaries, of regions\n"); printf ("in a binary image, and determines features of the regions.\n\n"); printf ("ARGUMENTS:\n"); printf (" inimg: input image filename (TIF)\n"); printf (" outimg: output image filename (TIF)\n\n"); printf ("OPTIONS:\n"); printf (" -d DISPLAY: display just centroids (1), or both\n"); printf (" contours and centroids (2);\n"); printf (" default displays just contours.\n"); printf (" -p: PRINT DATA FLAG if set, prints contour\n"); printf (" number, length, and centroid data.\n"); printf (" -m MAX_CONTOUR_LENGTH: maximum contour length in pixel\n"); printf (" connections. (Default = %d)\n", MAX_CONTOUR); printf (" -L: print Software License for this module\n");

return (-1);}

/* INPUT: function reads input parameters * usage: input (argc, argv, &maxContour, &displayFlag) */

#define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}

longinput (argc, argv, maxContour, displayFlag, printFlag) int argc; char *argv[]; long *maxContour; /* maximum contour length (for memory alloc) */ short *displayFlag; /* =0 contours; =1 centroids; =2 both */ short *printFlag; /* =1, print contour data; =0 don't */{ long n;

if (argc == 1) USAGE_EXIT (1); if (argc == 2) USAGE_EXIT (0);

*maxContour = MAX_CONTOUR; *displayFlag = DISPLAY_FLAG_DFLT; *printFlag = 0;

for (n = 3; n < argc; n++) { if (strcmp (argv[n], "-m") == 0) { if (++n == argc || argv[n][0] == '-')

Page 159: Bioidentià - Il Progetto Ottico

USAGE_EXIT (0); *maxContour = atol (argv[n]); } else if (strcmp (argv[n], "-d") == 0) { if (++n == argc || argv[n][0] == '-') USAGE_EXIT (0); *displayFlag = (short) atol (argv[n]); } else if (strcmp (argv[n], "-p") == 0) { *printFlag = 1; } else if (strcmp (argv[n], "-L") == 0) { print_sos_lic (); exit (0); } else USAGE_EXIT (0); }

return (0);}

Un esempio che ho creato mediante l’uso delle funzioni di OPENCV è quello che segue.

Il progetto è essenzialmente costituito dal seguente file .cpp al quale è demandato il richiamo dell’interprete di processo.

#include "stdafx.h"#include "cvapp.h"

ImageProcessor *proc = 0;

Page 160: Bioidentià - Il Progetto Ottico

SequenceProcessor *procseq = 0;

void process(void* img) {

IplImage* image = reinterpret_cast<IplImage*>(img); cvErode( image, image, 0, 2 );

}

void ImageProcessor::execute() {

process(img);}

IPin *GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir){ BOOL bFound = FALSE; IEnumPins *pEnum; IPin *pPin;

pFilter->EnumPins(&pEnum); while(pEnum->Next(1, &pPin, 0) == S_OK) { PIN_DIRECTION PinDirThis; pPin->QueryDirection(&PinDirThis); if (bFound = (PinDir == PinDirThis)) break; pPin->Release(); } pEnum->Release(); return (bFound ? pPin : 0); }

Inizialmente lo studio fu indirizzato verso l’identificazione di quali potevano essere quelle caratteristiche in grado di descrivere un immagine che non variassero a seguito di lievi modifiche geometrico spaziali.Per tale studio ho utilizzato la librearia grafica

IMAGEEN (www.hicomponents.com)

Con questa libreria grafica in cui erano presenti le funzioni di base per la gestione di immagini come la lettura, la visualizzazione ecc. ho scritto un programma in cui venivano calcolati determinati tipi di istogrammi, mediante le funzioni CalcDensityHistogram, e venivano valutati dei valori che succesimante descriverò.

#include <vcl.h>#pragma hdrstop#include <stdlib.h>

#include "ComparePrj.h"//---------------------------------------------------------------------------#pragma package(smart_init)#pragma link "ieopensavedlg"#pragma link "ieview"#pragma link "imageenio"#pragma link "imageenproc"

Page 161: Bioidentià - Il Progetto Ottico

#pragma link "imageenview"#pragma link "histogrambox"#pragma link "kfiledir"#pragma link "ievect"#pragma resource "*.dfm"TForm1 *Form1;//---------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner){}//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender){ LoadImage2();}//---------------------------------------------------------------------------void __fastcall TForm1::Button3Click(TObject *Sender){

double psnr_min1,psnr_max1; double mse_min1,mse_max1; double rmse_min1,rmse_max1; double pae_min1,pae_max1; double mae_min1,mae_max1; long ww, hh; ww = ImageEnView1->Bitmap->Width; hh =ImageEnView1->Bitmap->Height; if (ww!=ImageEnView2->Bitmap->Width || hh!=ImageEnView2->Bitmap->Height)

ImageEnView2->Proc->Resample( ww,hh, rfNone);

if(ImageEnProc2->ComputeImageEquality(ImageEnView1->IEBitmap, psnr_min1, psnr_max1, mse_min1, mse_max1, rmse_min1, rmse_max1, pae_min1, pae_max1, mae_min1, mae_max1)) Edit1->Text = "SI"; else Edit1->Text = "NO";

psnr_min->Text = psnr_min1; psnr_max->Text = psnr_max1;

mse_min->Text = mse_min1; mse_max->Text = mse_max1;

rmse_min->Text = rmse_min1; rmse_max->Text = rmse_max1;

pae_min->Text = pae_min1; pae_max->Text = pae_max1;

mae_min->Text = mae_min1; mae_max->Text = mae_max1;

HistogramBox1->Update(); HistogramBox2->Update();

}

Page 162: Bioidentià - Il Progetto Ottico

void __fastcall TForm1::Button4Click(TObject *Sender){ long ww, hh; double gradi = Edit2->Text.ToDouble(); ImageEnProc2->Rotate(gradi, true, ierFast, 0); Elaborate2();}//---------------------------------------------------------------------------

void TForm1::LoadImage1(){ if( OpenImageEnDialog1->Execute() ) { ImageEnView1->IO->LoadFromFileJpeg( OpenImageEnDialog1->FileName ); ImageEnVect1->IO->LoadFromFileJpeg( OpenImageEnDialog1->FileName ); Elaborate1(); }}

void TForm1::LoadImage2(){ if( OpenImageEnDialog1->Execute() ) { ImageEnView2->IO->LoadFromFileJpeg( OpenImageEnDialog1->FileName ); ImageEnVect2->IO->LoadFromFileJpeg( OpenImageEnDialog1->FileName );

Elaborate2(); }}void __fastcall TForm1::Button1Click(TObject *Sender){ LoadImage1();}//---------------------------------------------------------------------------

void TForm1::Elaborate1(){ long ww, hh, dimens; ww = ImageEnView1->Bitmap->Width; hh =ImageEnView1->Bitmap->Height; dimens = hh - 60; ImageEnView1->SelectEllipse( ww/2,hh/2, dimens,dimens,iespReplace ); HistogramBox1->Update(); ImageEnView1->Update(); }

void TForm1::Elaborate2(){

long ww, hh, dimens; ww = ImageEnView1->Bitmap->Width; hh =ImageEnView1->Bitmap->Height; if (ww!=ImageEnView2->Bitmap->Width || hh!=ImageEnView2->Bitmap->Height) ImageEnView2->Proc->Resample( ww,hh, rfNone); dimens = hh - 60;

Page 163: Bioidentià - Il Progetto Ottico

ImageEnView2->SelectEllipse( ww/2,hh/2, dimens,dimens,iespReplace ); HistogramBox2->Update(); ImageEnView2->Update();}

void TForm1::DensityHisto1(){ int *VertHist,*HorizHist; AnsiString temp; int VertHistHeight,HorizHistWidth,VertHistWidth,HorizHistHeight; int i;

VertHistWidth = ImageEnView3->ClientWidth; VertHistHeight = ImageEnView1->Bitmap->Height; HorizHistWidth =ImageEnView1->Bitmap->Width; HorizHistHeight =ImageEnView4->ClientHeight;

VertHist = (int *)malloc(VertHistHeight*sizeof(int)); HorizHist = (int *) malloc(HorizHistWidth*sizeof(int));

ImageEnView1->Proc->CalcDensityHistogram(VertHist,HorizHist,VertHistWidth,HorizHistHeight);

ImageEnView3->Bitmap->Height =HorizHistHeight; ImageEnView3->Bitmap->Width=HorizHistWidth;

// vertical

ImageEnView4->Bitmap->Height=VertHistHeight; ImageEnView4->Bitmap->Width=VertHistWidth; // draw histograms

ImageEnView3->Bitmap->Canvas->Pen->Color=clBlack; ImageEnView4->Bitmap->Canvas->Pen->Color=clBlack;

for(int u=0;u!=ListBox1->Items->Count;u++) ListBox1->Items->Delete(u);

for(i=0;i!=HorizHistWidth-1;i++) { temp.printf("%d",HorizHist[i]); ListBox1->Items->Add(temp); ImageEnView3->Bitmap->Canvas->MoveTo(i, HorizHistHeight ); ImageEnView3->Bitmap->Canvas->LineTo(i, HorizHistHeight - HorizHist[i] ); } for(int u=0;u!=ListBox2->Items->Count;u++) ListBox2->Items->Delete(u); for(i=0;i!=VertHistHeight-1;i++) { temp.printf("%d",VertHist[i]); ListBox2->Items->Add(temp); ImageEnView4->Bitmap->Canvas->MoveTo(0, i ); ImageEnView4->Bitmap->Canvas->LineTo(VertHist[i],i); } free(VertHist); free(HorizHist);

ImageEnView3->Update(); ImageEnView4->Update();}void __fastcall TForm1::Button5Click(TObject *Sender){

Page 164: Bioidentià - Il Progetto Ottico

DensityHisto1();}//---------------------------------------------------------------------------

void __fastcall TForm1::Button6Click(TObject *Sender){ int *VertHist,*HorizHist; AnsiString temp; int VertHistHeight,HorizHistWidth,VertHistWidth,HorizHistHeight; int i;

TIEFtImage *ftimage = new TIEFtImage;

ftimage = ImageEnProc1->FTCreateImage(ieitRGB,180,120); ImageEnProc3->FTDisplayFrom(ftimage); ftimage->Free();

VertHistWidth = ImageEnView9->ClientWidth; VertHistHeight = ImageEnView5->Bitmap->Height; HorizHistWidth =ImageEnView5->Bitmap->Width; HorizHistHeight =ImageEnView8->ClientHeight;

VertHist = (int *)malloc(VertHistHeight*sizeof(int)); HorizHist = (int *) malloc(HorizHistWidth*sizeof(int));

ImageEnView5->Proc->CalcDensityHistogram(VertHist,HorizHist,VertHistWidth,HorizHistHeight);

ImageEnView9->Bitmap->Height =HorizHistHeight; ImageEnView9->Bitmap->Width=HorizHistWidth;

// vertical

ImageEnView8->Bitmap->Height=VertHistHeight; ImageEnView8->Bitmap->Width=VertHistWidth; // draw histograms

ImageEnView9->Bitmap->Canvas->Pen->Color=clBlack; ImageEnView8->Bitmap->Canvas->Pen->Color=clBlack;

for(i=0;i!=HorizHistWidth-1;i++) { ImageEnView9->Bitmap->Canvas->MoveTo(i, HorizHistHeight ); ImageEnView9->Bitmap->Canvas->LineTo(i, HorizHistHeight - HorizHist[i] ); } for(i=0;i!=VertHistHeight-1;i++) { ImageEnView8->Bitmap->Canvas->MoveTo(0, i ); ImageEnView8->Bitmap->Canvas->LineTo(VertHist[i],i); } free(VertHist); free(HorizHist);

ImageEnView8->Update(); ImageEnView9->Update();

}//---------------------------------------------------------------------------

void TForm1::DensityHisto2(void)

Page 165: Bioidentià - Il Progetto Ottico

{ AnsiString temp; int *VertHist,*HorizHist; int VertHistHeight,HorizHistWidth,VertHistWidth,HorizHistHeight; int i;

VertHistWidth = ImageEnView6->ClientWidth; VertHistHeight = ImageEnView2->Bitmap->Height; HorizHistWidth =ImageEnView2->Bitmap->Width; HorizHistHeight =ImageEnView7->ClientHeight;

VertHist = (int *)malloc(VertHistHeight*sizeof(int)); HorizHist = (int *) malloc(HorizHistWidth*sizeof(int));

ImageEnView2->Proc->CalcDensityHistogram(VertHist,HorizHist,VertHistWidth,HorizHistHeight);

ImageEnView6->Bitmap->Height=HorizHistHeight; ImageEnView6->Bitmap->Width=HorizHistWidth;

// vertical

ImageEnView7->Bitmap->Height=VertHistHeight; ImageEnView7->Bitmap->Width=VertHistWidth; // draw histograms

ImageEnView7->Bitmap->Canvas->Pen->Color=clBlack; ImageEnView6->Bitmap->Canvas->Pen->Color=clBlack; for(int u=0;u!=ListBox3->Items->Count;u++) ListBox3->Items->Delete(u);

for(i=0;i!=HorizHistWidth-1;i++) { temp.printf("%d",HorizHist[i]); ListBox3->Items->Add(temp); ImageEnView6->Bitmap->Canvas->MoveTo(i, HorizHistHeight ); ImageEnView6->Bitmap->Canvas->LineTo(i, HorizHistHeight - HorizHist[i] ); } for(int u=0;u!=ListBox4->Items->Count;u++) ListBox4->Items->Delete(u);

for(i=0;i!=VertHistHeight-1;i++) { temp.printf("%d",VertHist[i]); ListBox4->Items->Add(temp); ImageEnView7->Bitmap->Canvas->MoveTo(0, i ); ImageEnView7->Bitmap->Canvas->LineTo(VertHist[i],i); } free(VertHist); free(HorizHist); ImageEnView6->Update(); ImageEnView7->Update();}void __fastcall TForm1::Button7Click(TObject *Sender){ DensityHisto2();}//---------------------------------------------------------------------------

Page 166: Bioidentià - Il Progetto Ottico

void __fastcall TForm1::Button8Click(TObject *Sender){ int *VertHist,*HorizHist; AnsiString temp; int VertHistHeight,HorizHistWidth,VertHistWidth,HorizHistHeight; int i;

TIEFtImage *ftimage = new TIEFtImage;

ftimage = ImageEnProc1->FTCreateImage(ieitRGB,180,120); ImageEnProc2->FTDisplayFrom(ftimage); ftimage->Free();

VertHistWidth = ImageEnView12->ClientWidth; VertHistHeight = ImageEnView10->Bitmap->Height; HorizHistWidth =ImageEnView10->Bitmap->Width; HorizHistHeight =ImageEnView11->ClientHeight;

VertHist = (int *)malloc(VertHistHeight*sizeof(int)); HorizHist = (int *) malloc(HorizHistWidth*sizeof(int));

ImageEnView10->Proc->CalcDensityHistogram(VertHist,HorizHist,VertHistWidth,HorizHistHeight);

ImageEnView12->Bitmap->Height =HorizHistHeight; ImageEnView12->Bitmap->Width=HorizHistWidth;

// vertical

ImageEnView11->Bitmap->Height=VertHistHeight; ImageEnView11->Bitmap->Width=VertHistWidth; // draw histograms

ImageEnView12->Bitmap->Canvas->Pen->Color=clBlack; ImageEnView11->Bitmap->Canvas->Pen->Color=clBlack;

for(i=0;i!=HorizHistWidth-1;i++) { ImageEnView12->Bitmap->Canvas->MoveTo(i, HorizHistHeight ); ImageEnView12->Bitmap->Canvas->LineTo(i, HorizHistHeight - HorizHist[i] ); } for(i=0;i!=VertHistHeight-1;i++) { ImageEnView11->Bitmap->Canvas->MoveTo(0, i ); ImageEnView11->Bitmap->Canvas->LineTo(VertHist[i],i); } free(VertHist); free(HorizHist);

ImageEnView12->Update(); ImageEnView11->Update();

}//---------------------------------------------------------------------------

In tale programma mediante l’suo di una funzione della libreria ComputeImageEquality venivano valutati i seguenti valori :

psnr_min,psnr_max : minimum and maximum peak signal to noise ratiomse_min,mse_max : minimum and maximum mean squared errorrmse_min,rmse_max : minimum and maximum root mean squared error

Page 167: Bioidentià - Il Progetto Ottico

pae_min,pae_max : minimum and maximum peak absolute errormae_min,mae_max : minimum and maximum mean absolute error

Il risultato fu scadente in quanto questi valori erano troppo soggetti alle mutazioni di angolazione dell’immagine.Nel programma venivano considerate anche diversi tipi di trasformazioni finalizzate allo studio dell’identificazione di oggetti.

Page 168: Bioidentià - Il Progetto Ottico

Aggancio alla telecamera

OpenCV è una libreria per le elaborazioni in REALTIME sulle immagini acquisite da una telecamera.La libreria possiede al suo interno tutte le funzioni per la gestione di queste.Inoltre OpenCV può lavorare anche su filmati AVI allo stesso modo con cui lavora sulle riprese dirette.Sul sito in cui è gestita la maillist di OpenCV è presente un file di configurazione di Visual C++ che permette di creare un WIZARD per l’inizializzazione delle applicazioni OpenCV.In pratica il file è

OpenCV Framework.awx

Utilizzando tale modello per la creazione di un applicativo viene generata una serie di files tra i quali sono anche presenti quelli che includono la classe di gestione della telecamera.La classe generata possiede i seguenti metodi e membri :

class CCamera {protected: CImage m_frame; bool m_isRunning; CAPDRIVERCAPS m_caps;

HIC m_hic;public:

BITMAPINFO bmi, bmi_out; HWND m_capWnd; CImage& GetFrame() { return m_frame; } CCamera();

virtual ~CCamera(); bool IsInitialized() { return m_capWnd != 0; }; bool IsRunning() { return m_isRunning; };

void OnFrame( BYTE* data, int width, int height, int format, int bpp ); bool Initialize(HWND parent ); void Uninitialize();

void ClearRect(); void Start(); void Stop(); void VideoFormatDlg(); void VideoSourceDlg(); void UpdateParent( bool whole );

};

La dialog generata di default possiede alcuni pulsanti indirizzati alla gestione delle funzionalità di base sulla telecamera e sui

Page 169: Bioidentià - Il Progetto Ottico

files AVI.Andando ad analizzare la classe generata dal wizard troviamo una serie di funzioni che possiedono la specifica CAP prima del nome della funzione.Precedentemente abbiamo detto che OPENCV si basa sulle librerie directx per alcuni tipi di gestioni e tra queste esistono quelle legate alla telecamera.Originariamente in WINDOWS la gestione dei filmati veniva fatta dal pacchetto VIDEO FOR WINDOWS.Le funzioni utilizzate per la gestione della camera provengono da questa.Ad esempio l’interrogazione del formato viene eseguita mediante il metodo :

void CCamera::VideoFormatDlg(){ if( m_capWnd && m_caps.fHasDlgVideoFormat ) { capDlgVideoFormat( m_capWnd ); }

capGetVideoFormat (m_capWnd, &bmi, sizeof(bmi));// install decompressorm_hic=ICOpen (ICTYPE_VIDEO, bmi.bmiHeader.biCompression,

ICMODE_DECOMPRESS);ICDecompressGetFormat (m_hic, &bmi, &bmi_out);

}

All’interno di questo viene utilizzata la funzione capGetVideoFormat.La definizione delle funzioni cap è quella che segue.

#define capSetCallbackOnError(hwnd, fpProc) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_CALLBACK_ERROR, 0, (LPARAM)(LPVOID)(fpProc)))#define capSetCallbackOnStatus(hwnd, fpProc) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_CALLBACK_STATUS, 0, (LPARAM)(LPVOID)(fpProc)))#define capSetCallbackOnYield(hwnd, fpProc) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_CALLBACK_YIELD, 0, (LPARAM)(LPVOID)(fpProc)))#define capSetCallbackOnFrame(hwnd, fpProc) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_CALLBACK_FRAME, 0, (LPARAM)(LPVOID)(fpProc)))#define capSetCallbackOnVideoStream(hwnd, fpProc) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, (LPARAM)(LPVOID)(fpProc)))#define capSetCallbackOnWaveStream(hwnd, fpProc) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_CALLBACK_WAVESTREAM, 0, (LPARAM)(LPVOID)(fpProc)))

Page 170: Bioidentià - Il Progetto Ottico

#define capSetCallbackOnCapControl(hwnd, fpProc) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_CALLBACK_CAPCONTROL, 0, (LPARAM)(LPVOID)(fpProc)))

#define capSetUserData(hwnd, lUser) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_USER_DATA, 0, (LPARAM)lUser))#define capGetUserData(hwnd) (AVICapSM(hwnd, WM_CAP_GET_USER_DATA, 0, 0))

#define capDriverConnect(hwnd, i) ((BOOL)AVICapSM(hwnd, WM_CAP_DRIVER_CONNECT, (WPARAM)(i), 0L))#define capDriverDisconnect(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_DRIVER_DISCONNECT, (WPARAM)0, 0L))#define capDriverGetName(hwnd, szName, wSize) ((BOOL)AVICapSM(hwnd, WM_CAP_DRIVER_GET_NAME, (WPARAM)(wSize), (LPARAM)(LPVOID)(LPTSTR)(szName)))#define capDriverGetVersion(hwnd, szVer, wSize) ((BOOL)AVICapSM(hwnd, WM_CAP_DRIVER_GET_VERSION, (WPARAM)(wSize), (LPARAM)(LPVOID)(LPTSTR)(szVer)))#define capDriverGetCaps(hwnd, s, wSize) ((BOOL)AVICapSM(hwnd, WM_CAP_DRIVER_GET_CAPS, (WPARAM)(wSize), (LPARAM)(LPVOID)(LPCAPDRIVERCAPS)(s)))

#define capFileSetCaptureFile(hwnd, szName) ((BOOL)AVICapSM(hwnd, WM_CAP_FILE_SET_CAPTURE_FILE, 0, (LPARAM)(LPVOID)(LPTSTR)(szName)))#define capFileGetCaptureFile(hwnd, szName, wSize) ((BOOL)AVICapSM(hwnd, WM_CAP_FILE_GET_CAPTURE_FILE, (WPARAM)(wSize), (LPARAM)(LPVOID)(LPTSTR)(szName)))#define capFileAlloc(hwnd, dwSize) ((BOOL)AVICapSM(hwnd, WM_CAP_FILE_ALLOCATE, 0, (LPARAM)(DWORD)(dwSize)))#define capFileSaveAs(hwnd, szName) ((BOOL)AVICapSM(hwnd, WM_CAP_FILE_SAVEAS, 0, (LPARAM)(LPVOID)(LPTSTR)(szName)))#define capFileSetInfoChunk(hwnd, lpInfoChunk) ((BOOL)AVICapSM(hwnd, WM_CAP_FILE_SET_INFOCHUNK, (WPARAM)0, (LPARAM)(LPCAPINFOCHUNK)(lpInfoChunk)))#define capFileSaveDIB(hwnd, szName) ((BOOL)AVICapSM(hwnd, WM_CAP_FILE_SAVEDIB, 0, (LPARAM)(LPVOID)(LPTSTR)(szName)))

#define capEditCopy(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_EDIT_COPY, 0, 0L))

#define capSetAudioFormat(hwnd, s, wSize) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_AUDIOFORMAT, (WPARAM)(wSize), (LPARAM)(LPVOID)(LPWAVEFORMATEX)(s)))#define capGetAudioFormat(hwnd, s, wSize) ((DWORD)AVICapSM(hwnd, WM_CAP_GET_AUDIOFORMAT, (WPARAM)(wSize), (LPARAM)(LPVOID)(LPWAVEFORMATEX)(s)))

Page 171: Bioidentià - Il Progetto Ottico

#define capGetAudioFormatSize(hwnd) ((DWORD)AVICapSM(hwnd, WM_CAP_GET_AUDIOFORMAT, (WPARAM)0, (LPARAM)0L))

#define capDlgVideoFormat(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0L))#define capDlgVideoSource(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0L))#define capDlgVideoDisplay(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_DLG_VIDEODISPLAY, 0, 0L))#define capDlgVideoCompression(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_DLG_VIDEOCOMPRESSION, 0, 0L))

#define capGetVideoFormat(hwnd, s, wSize) ((DWORD)AVICapSM(hwnd, WM_CAP_GET_VIDEOFORMAT, (WPARAM)(wSize), (LPARAM)(LPVOID)(s)))#define capGetVideoFormatSize(hwnd) ((DWORD)AVICapSM(hwnd, WM_CAP_GET_VIDEOFORMAT, 0, 0L))#define capSetVideoFormat(hwnd, s, wSize) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_VIDEOFORMAT, (WPARAM)(wSize), (LPARAM)(LPVOID)(s)))

#define capPreview(hwnd, f) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_PREVIEW, (WPARAM)(BOOL)(f), 0L))#define capPreviewRate(hwnd, wMS) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_PREVIEWRATE, (WPARAM)(wMS), 0))#define capOverlay(hwnd, f) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_OVERLAY, (WPARAM)(BOOL)(f), 0L))#define capPreviewScale(hwnd, f) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_SCALE, (WPARAM)(BOOL)f, 0L))#define capGetStatus(hwnd, s, wSize) ((BOOL)AVICapSM(hwnd, WM_CAP_GET_STATUS, (WPARAM)(wSize), (LPARAM)(LPVOID)(LPCAPSTATUS)(s)))#define capSetScrollPos(hwnd, lpP) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_SCROLL, (WPARAM)0, (LPARAM)(LPPOINT)(lpP)))

#define capGrabFrame(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_GRAB_FRAME, (WPARAM)0, (LPARAM)0L))#define capGrabFrameNoStop(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_GRAB_FRAME_NOSTOP, (WPARAM)0, (LPARAM)0L))

#define capCaptureSequence(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_SEQUENCE, (WPARAM)0, (LPARAM)0L))#define capCaptureSequenceNoFile(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_SEQUENCE_NOFILE, (WPARAM)0, (LPARAM)0L))#define capCaptureStop(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_STOP, (WPARAM)0, (LPARAM)0L))#define capCaptureAbort(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_ABORT, (WPARAM)0, (LPARAM)0L))

Page 172: Bioidentià - Il Progetto Ottico

#define capCaptureSingleFrameOpen(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_SINGLE_FRAME_OPEN, (WPARAM)0, (LPARAM)0L))#define capCaptureSingleFrameClose(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_SINGLE_FRAME_CLOSE, (WPARAM)0, (LPARAM)0L))#define capCaptureSingleFrame(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_SINGLE_FRAME, (WPARAM)0, (LPARAM)0L))

#define capCaptureGetSetup(hwnd, s, wSize) ((BOOL)AVICapSM(hwnd, WM_CAP_GET_SEQUENCE_SETUP, (WPARAM)(wSize), (LPARAM)(LPVOID)(LPCAPTUREPARMS)(s)))#define capCaptureSetSetup(hwnd, s, wSize) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_SEQUENCE_SETUP, (WPARAM)(wSize), (LPARAM)(LPVOID)(LPCAPTUREPARMS)(s)))

#define capSetMCIDeviceName(hwnd, szName) ((BOOL)AVICapSM(hwnd, WM_CAP_SET_MCI_DEVICE, 0, (LPARAM)(LPVOID)(LPTSTR)(szName)))#define capGetMCIDeviceName(hwnd, szName, wSize) ((BOOL)AVICapSM(hwnd, WM_CAP_GET_MCI_DEVICE, (WPARAM)(wSize), (LPARAM)(LPVOID)(LPTSTR)(szName)))

#define capPaletteOpen(hwnd, szName) ((BOOL)AVICapSM(hwnd, WM_CAP_PAL_OPEN, 0, (LPARAM)(LPVOID)(LPTSTR)(szName)))#define capPaletteSave(hwnd, szName) ((BOOL)AVICapSM(hwnd, WM_CAP_PAL_SAVE, 0, (LPARAM)(LPVOID)(LPTSTR)(szName)))#define capPalettePaste(hwnd) ((BOOL)AVICapSM(hwnd, WM_CAP_PAL_PASTE, (WPARAM) 0, (LPARAM)0L))#define capPaletteAuto(hwnd, iFrames, iColors) ((BOOL)AVICapSM(hwnd, WM_CAP_PAL_AUTOCREATE, (WPARAM)(iFrames), (LPARAM)(DWORD)(iColors)))#define capPaletteManual(hwnd, fGrab, iColors) ((BOOL)AVICapSM(hwnd, WM_CAP_PAL_MANUALCREATE, (WPARAM)(fGrab), (LPARAM)(DWORD)(iColors)))

Mediante queste funzioni è possibile inserire altre funzione per lo svolgimento di determinate esigenze.

Page 173: Bioidentià - Il Progetto Ottico

Il lavoro di preparazione.

Il lavoro di preparazione prevede diverse funzioni tra le quali alcune legate alla correzione grafica dell’immagine acquisita ed altre invece indirizzate alla calibrazione della telecamera.Tale funzionalità viene eseguita per trovare i parametri intrinsechi ed estrinsechi della telecamera.Tra i primi ci sono :

Lunghezza focale Posizione del centro dell’immagineDimensione effettiva del pixelCoefficiente della distorsione radiale delle lenti

I parametri estrinsechi invece sono :

La matrice di rotazioneIl vettore di traslazione

La fase di calibrazione è necessaria per determinare alcuni parametri che identificano la posizione della telecamera nel mondo. Alcuni di questi parametri sono dati direttamente dal produttore della telecamera (come il numero di pixel del CCD, le dimensioni dei pixel stessi, …), altri invece dipendono dalla sua posizione (come la matrice di rototraslazione). Per la determinazione di questi parametri in una fase iniziale è stato utilizzato l’algoritmo di Horn. Questo algoritmo sebbene di facile implementazione ed utilizzo (necessitava di soli 5 punti), non dava una precisione sufficiente al nostro fine, così abbiamo optato per un algoritmo più complesso ma maggiormente stabile e preciso: il metodo di Tsai. Nel caso specifico le maggiori imprecisioni del metodo di Horn erano dovute alla soluzione di un sistema non lineare mediante l’algoritmo di Newton-Rapson. Il metodo di Tsai invece si basa sulla scomposizione del sistema non lineare in due sottosistemi dei quali uno è lineare. Un ulteriore vantaggio nell’utilizzo di Tsai è il calcolo della distanza focale. Lo svantaggio sta nel numero di punti minimo richiesto per la calibrazione: almeno 11 per ogni telecamera.La calibrazione della camera nella sua forma più semplice viene eseguita dalla funzione :

CalibrateCamera

Calibrates camera with single precision

void cvCalibrateCamera( int numImages, int* numPoints, CvSize imageSize,CvPoint2D32f* imagePoints32f, CvPoint3D32f*

Page 174: Bioidentià - Il Progetto Ottico

objectPoints32f, CvVect32f distortion32f, CvMatr32f cameraMatrix32f, CvVect32f transVects32f, CvMatr32f rotMatrs32f,int useIntrinsicGuess );

Tale funzionalità è indirizzata a correggere fattori legati all’uso delle lenti all’interno del sistema.

Uno dei metodi usati è quello definito con il termine di :

Direct Linear Transformation (DLT)

Registrare un immagine è l’equivalente di mappare un punto dell’oggetto O presente nello spazio di questo in un punto dell’immagine l presente nello spazio del film.Nel caso di digitazione l’immagine registrata viene proiettata nuovamente in un immagine l all’interno del piano di proiezione.Per semplicità comqunue è possibile relazionare direttamente l’immagine

proiettata e l’oggetto.

Inizialmente abbiamo detto che esistono parametri intrinsechi ed estrinsechi.La correzione degli errori indotti dalle lenti possono essere eseguite mediante :

UnDistortOnce

Corrects camera lens distortion

void cvUnDistortOnce( const CvArr* srcImage, CvArr* dstImage, const float* intrMatrix, const float* distCoeffs,

Page 175: Bioidentià - Il Progetto Ottico

int interpolate=1 );

srcImageSource (distorted) image.

dstImageDestination (corrected) image.

intrMatrixMatrix of the camera intrinsic parameters (3x3).

distCoeffsVector of the four distortion coefficients k1, k2, p1 and p2.

interpolateBilinear interpolation flag.

Esistono alcune funzioni di OPENCV che sono utilizzate per identificare questi tipi di parametri.

FindExtrinsicCameraParams

Finds extrinsic camera parameters for pattern

void cvFindExtrinsicCameraParams( int numPoints, CvSize imageSize, CvPoint2D32f* imagePoints32f, CvPoint3D32f* objectPoints32f, CvVect32f focalLength32f, CvPoint2D32f principalPoint32f, CvVect32f distortion32f, CvVect32f rotVect32f, CvVect32f transVect32f );

numPointsNumber of the points.

ImageSizeSize of the image.

imagePoints32fPointer to the image.

objectPoints32fPointer to the pattern.

focalLength32fFocal length.

principalPoint32fPrincipal point.

distortion32fDistortion.

rotVect32fRotation vector.

transVect32fTranslate vector.

Page 176: Bioidentià - Il Progetto Ottico

I concetti algoritmici utilizzati.

Nelle pagine precedenti si sono utilizzati dei termini particolari come ad esempio OBJECT RECOGNITION, PATTERN RECOGNITION, SEGMENTAZIONE, HIDDEN MARKOV MODELLS ecc.Tutte queste voci sono comuni nell’ambito delle metodologie utilizzate all’interno della computer vision.Nel sistema software di gestione dell’identificazione retinale sono utilizzate molte procedure che si attengono a questi termini e quindi prima di trattare dal punto di vista algoritmico la problematica è necessario avere ben chiari questi principi.Alcuni termini si riferiscono a concetti in senso generale mentre altri sono relativi ad algoritmi specifici utilizzati all’interno dei procedimenti informatici.Un concetto fondamentale è comunque quello legato al fatto che reale od astratto che sia il nostro lavoro sarà indirizzato verso la gestione di un oggetto che poi di fatto è costituito dalla nostra retina.Nei sistemi indirizzati al riconoscimento d’oggetti in genere questi sono presenti dentro ad immagini composte da altri oggetti perciò in alcuni casi prima di poter intervenire a livello algoritmico, ad esempio per eseguire un riconoscimento, è necessario eseguire determinati metodi per semplificare il contenuto dell’immagine.

SEGMENTAZIONE

Uno degli algoritmi utilizzati è quello legato alla segmentazione.La segmentazione di una immagine è un processo che consente di suddividere la stessa in alcune regioni significative.In altre parole per segmentazione dell'immagine si intendono tutti quei passaggi che consentono una descrizione dettagliata degli oggetti stessi come il numero di pixels costituenti l'oggetto e le loro coordinate, tutte le informazioni necessarie a tracciare i loro contorni ecc.. Ogni oggetto viene quindi identificato per mezzo di un set descrittivo di dati che vengono memorizzati e successivamente impiegati per le operazioni di misura sugli oggetti stessi.Il caso più semplice consiste nel suddividere l’immagine in due sole regioni di cui una costituisce lo sfondo e l’altra l’oggetto.Nei casi più complessi ciascuna regione è definita con il termine di “classe”.Su questo metodo avevamo accennato il concetto nelle pagini precedenti ma ripentendolo possiamo dire che esistono sostanzialmente tre tipologie di segmentazione:

1 Thresholding2 Edge based method3 Relaxation

Page 177: Bioidentià - Il Progetto Ottico

L’utilizzo della segmentazione ha numerosi vantaggi:

1. Trasformazione di un’immagine in regioni che possono essere trattate separatamente. Ad esempio immagini binarie.

2. Identificazione delle caratteristiche dominanti di unaimmagine.

3. Trasformazione di immagini complesse in immagini più semplici per le operazioni di riconoscimento (pattern recognition) nel campo delle Reti Neurali o della IA

Metodo del livello di soglia (Threshold).

Questo metodo è il più semplice e consiste nel considerare come sfondo tutti i pixels che hanno un valore di densità uguale o maggiore di un determinato valore di soglia; essi verranno quindi settati al valore del bianco (255). Invece sono considerati come appartenenti ad oggetti tutti quei pixels che hanno un valore inferiore al valore di soglia e verranno settati al nero (0).In questo caso si parla di valore di soglia superiore. A volte è necessario scegliere l'inverso, cioè settare al nero i pixel aventi un valore maggiore del valore di soglia e si parla allora di valore di soglia inferiore. Il settaggio dei pixel oggetto al nero e di quelli dello sfondo al bianco è detto binarizzazione dell'immagine. Da notare che non sempre è necessario ottenere l'immagine binaria per poter eseguire i calcoli richiesti; infatti spesso ciò non è necessario e anzi non si deve fare quando si devono eseguire analisi densitometriche in quanto nell'immagine binaria vengono perse tutte le informazioni relative al valore dei pixel dell'immagine nella scala dei grigi.

Tuttavia i calcoli delle grandezze morfometriche sull'immagine binaria sono più veloci e precisi rispetto agli stessi eseguiti su un'immagine in scala di grigi o in falsi colori. Ciò a causa degli algoritmi usati per l'identificazione degli oggetti e i calcoli relativi.

Page 178: Bioidentià - Il Progetto Ottico

La scelta della soglia dipende dall’istogramma dell’immagine.Non per tutte le immagini è possibile con una sola soglia ricavare le informazioni desiderate.

Volendo ricorrere a più soglie è possibile utilizzare ler regole :

Nel caso bimodale una sola soglia separa le due regioni dell’immagine. In questo caso vale :

In questo caso si possono scegliere due valori di soglia e dunque si hanno 4 possibilità.In questo caso una sola soglia non è sufficiente a caratterizzarel’immagine.Un sottogruppo di questo metodo è quello definito con il termine di “Metodo delle densità parziali (Density slice)”.Esso consiste nello stabilire un livello di soglia inferiore e un livello di soglia superiore nel quale tutti i pixels che hanno valori compresi in tale intervallo sono considerati appartenenti

Page 179: Bioidentià - Il Progetto Ottico

ad oggetti di interesse; mentre quelli al di sotto del valore minimo e al di sopra del valore massimo di tale intervallo sono considerati appartenenti allo sfondo.Detto in altre parole la segmentazione è una elaborazione finalizzata al partizionamento delle immagini in regioni disgiunte e singolarmente omogenee rispetto a determinati parametri (luminanza, texture, forma, ecc.). Per esempio, data un'immagine con il primo piano di una persona, un problema di segmentazione potrebbe essere quello di individuare e separare alcune parti dell'immagine come i capelli, gli occhi, la bocca e via dicendo. Nel caso dei capelli sarebbe opportuno, ad esempio, far riferimento alle caratteristiche di texture dei dati al fine di isolare l'intera regione dei capelli, senza incorrere nell'errore di segmentarla ulteriormente a causa di variazioni nella luminanza.Un applicazione tipica è quella della classificazione, soprattutto per le immagini da telerilevamento in cui si cerca di identificare i diversi tipi di superfice terrestre (fiumi, boschi, campi, insediamenti urbani, ecc.) in base ai dati osservati, generalmente per fini di monitoraggio ambientale.

Edge based method

Se i contorni di un’immagine possono essere considerati come frontiere di ciascuna regione di separazione, l’applicazione di un metodo “edge detector” consente la segmentazione della stessa.Il metodo è anche detto Metodo dei Seguitori di Contorno ed i passi per la realizzazione sono i seguenti:

1. Calcolo del Gradiente: vengono create due nuove immagini che indicano il modulo e la direzione dei contorni attraverso l’utilizzo di filtri derivativi.

2. Assottigliamento degli spigoli: il gradiente produce spigoli di dimensioni molto grandi. Maggiore è la finestra della maschera è maggiori sono le dimensioni degli spigoli.Pertanto devono essere selezionati i soli spigoli in cui il massimo valore è il massimo locale nella direzione del gradiente stesso.Rimane così un solo pixel.

3. Costruzione delle catene tra pixel: vengono costruite le “catene” tra tutti i pixel selezionati in precedenza. Si creano sì delle curve che costituiscono il contorno delle regioni.

Page 180: Bioidentià - Il Progetto Ottico

Relaxation

Effetto Rilievo: si basa su operatori di gradiente, opportunamente modificati. Ai diversi livelli di luminosità si applica un algoritmo che restituisce delle curve di livello.

Solarizzazione: E’ una modifica (taglio) dell’istogramma dell’immagine:

L’utilizzo della segmentazione di fatto semplifica la gestione

Page 181: Bioidentià - Il Progetto Ottico

degli oggetti presenti in quanto delimita il contenuto di questi in modo netto.Generalmente la rappresentazione degli oggetti all’inyterno di un immagine è costituita da gruppi di pixels di colorazioni differenti.In questo modo diventa complicato concettualizzare queli possono essere i limiti degli oggetti da passare alle varie funzioni di elaborazione.La segmentazione semplifica notevolmente i processi successivi che vengono eseguiti nell’ambito dell’identificazione degli oggetti.Nell’ambito di OPENCV le funzionalità di gestione del threshold possono essere eseguite molto semplicemente mediante l’suo dell’apposita funzione.

Threshold

Applies fixed-level threshold to array elements

void cvThreshold( const CvArr* src, CvArr* dst, double threshold, double maxValue, int thresholdType );

srcSource array (single-channel, 8-bit of 32-bit floating point). dstDestination array; must be either the same type as src or 8-bit. thresholdThreshold value. maxValueMaximum value to use with CV_THRESH_BINARY, CV_THRESH_BINARY_INV, and CV_THRESH_TRUNC thresholding types. thresholdTypeThresholding type (see the discussion)

The function cvThreshold applies fixed-level thresholding to single-channel array. The function is typically used to get bi-level (binary) image out of grayscale image or for removing a noise, i.e. filtering out pixels with too small or too large values. There are several types of thresholding the function supports that are determined by thresholdType:

thresholdType=CV_THRESH_BINARY:dst(x,y) = maxValue, if src(x,y)>threshold 0, otherwise

thresholdType=CV_THRESH_BINARY_INV:dst(x,y) = 0, if src(x,y)>threshold maxValue, otherwise

thresholdType=CV_THRESH_TRUNC:dst(x,y) = threshold, if src(x,y)>threshold src(x,y), otherwise

Page 182: Bioidentià - Il Progetto Ottico

thresholdType=CV_THRESH_TOZERO:dst(x,y) = src(x,y), if (x,y)>threshold 0, otherwise

thresholdType=CV_THRESH_TOZERO_INV:dst(x,y) = 0, if src(x,y)>threshold src(x,y), otherwise

Come avevamo detto inizialmente il problema dopo averlo analizzato dal punto di vista del geometric matching è stato subito inquadrato nella tipologia di problemi affrontabili mediante le metodologie di riconoscimento e classificazione di pattern, template o shapes.

Page 183: Bioidentià - Il Progetto Ottico

Il pattern viene definito, con un termine molto rasente alla filosofia, come l’opposto del chaos, o, in altre parole, forma vagamente definita a cui può essere attribuito un nome.Un esempio di pattern può essere una retina, un impronta, un volto , eccNel contesto del pattern recognition il riconoscimento è inteso come classificazione o categorizzazione ovvero l’assegnamento del pattern a una classe.Per classe intendiamo un insieme di entità aventi proprietà comuni (ad. esempio i diversi modi in cui le persone scrivono il carattere “A”). Il concetto di classe è semantico e dipende strettamente dall’applicazione.Le classi possono essere definite dal progettista (classificazione supervisionata) o “imparate” autonomamente dal sistema (classificazione non supervisionata).Come abbiamo visto prima il metodo classico di confronto diretto delle immagini non funziona per i seguenti motivi :

Traslazione, rotazione, scala e prospettiva. Deformazione e variabilità dei pattern. Cambiamenti di illuminazione. Rumore e diverse tecniche di acquisizione.

Ad esempio perche’ l’immagine I1 – I2 non funziona ?

Page 184: Bioidentià - Il Progetto Ottico

I principali approcci della pattern recognition sono quelli che seguono.

Template matching

La distanza diretta tra immagini non fornisce buoni risultati spesso a causa di traslazioni, rotazioni, variabilità dei pattern.

Approccio Statistico

Ogni pattern è rappresentato da un punto nello spazio multidimensionale.

Prevede una fase di estrazione delle caratteristiche estrazione delle caratteristiche che mappa il pattern nel punto e una fase di classificazione classificazione che associa il punto a una classe.

I classificatori utilizzati sono fondati su solide basi statistiche.

Page 185: Bioidentià - Il Progetto Ottico

Di ogni oggetto viene misurata l’estensione dei pixels rispetto al barricentro.Nel caso di classificazione :

Se E è l’estensione dell’oggetto da classificare in una delle 2 classi T (oggetti allungati a forma di T) e C (oggetti più circolari).

Dove Avgt e AvgC sono le estensioni medie degli oggetti delle 2 classi T e C misurate su un set di addestramento.

Approccio Strutturale (sintattico)

I pattern sono codificati in termini di componenti primitive componenti primitive e di relazioni relazioni che intercorrono tra esse.

Il confronto avviene confrontando primitive e relazioni.

Page 186: Bioidentià - Il Progetto Ottico

Reti Neurali

Sono costituite da grafi orientati i cui nodi (neuroni) processano le informazioni trasmesse da altri neuroni ad essi collegati.

Consentono di “codificare” complessi complessi mapping mapping non non-lineari lineari, che vengono solitamente “appresi” da esempi.

Il termine template matching template matching è molto generico nell’ambito del PR, ma normalmente fa riferimento allo “ricerca” di un template T all’interno di un’immagine I con l’obiettivo di determinare se I contiene l’oggetto (match) e in quale posizione T appare nell’immagine.

Page 187: Bioidentià - Il Progetto Ottico

Un concetto matematico utilizzato nel Template Matching è quello di Correlazione nello spazio di Fourier Fourier Il teorema di Correlazione afferma che un’operazione di correlazione eseguita nel dominio spaziale corrisponde a una moltiplicazione eseguita nel dominio delle frequenze (Fourier):

La correlazione tra due funzioni f e g in ciascun punto (x,y) è definita (nel continuo) come:

Il teorema di correlazione afferma che:

dove F è la trasformata di Fourier di f, G* è la complessa coniugata della trasformata di Fourier di g e F-1 è l’operazione di l’antitrasformata.Per eseguire la correlazione nello spazio delle frequenze è pertanto necessario:

1. Calcolare la trasformata dell’immagine I (con algoritmo FFT su immagine di dimensione pari a una potenza di 2).

2. Calcolare la trasformata del template T (che deve essere esteso a una dimensione pari a quella dell’immagine) e la

Page 188: Bioidentià - Il Progetto Ottico

complessa coniugata.3. Eseguire la moltiplicazione pixel a pixel (tra numeri

complessi) 4. Antitrasformare (con algoritmo InvFFT).

Per un’immagine di N*N pixel e un template di M*M pixel la complessità nel dominio dello spazio è: N2×M2 mentre nel dominio delle frequenze 3 × N2 ln (N2) + N2

Considerando che nello spazio delle freq. sono richieste operazioni floating-point e allargamento di immagini (per compensare effetti di bordo e adeguamento a potenza del 2) si ha maggiore efficienza solo quando: M2 >> ln (N2)

Nel caso di TEMPLATE DEFORMABILI i metodi sono quelli che seguono :

Free-Form deformable:

il template non è vincolato a forme precise (anche se generalmente si impongono criteri di regolarità). Si fa uso di un potential field, cioè di una funzione di energia prodotta dalle feature salienti dell’immagine, per guidare il processo verso le deformazioni maggiormente significative.

Eint è l’energia interna che controlla la regolarità e l’elasticità dello snake.

Eimage è l’energia dell’immagine che indica quanto la forma dell’oggetto si adatta all’immagine sottostante (bordi, gradiente, ...).

Eext è l’energia esterna determinata da altri eventuali componenti esterne.

Page 189: Bioidentià - Il Progetto Ottico

Analytic-Form based (Parametric deformable Parametric deformable):

si tratta di template parametrici (polilinee, archi, curve spline, o combinazione dei precedenti) regolate da un numero limitato di parametri agendo sui quali si ottengono deformazioni controllate.

Prototype based(Parametric deformable Parametric deformable):

viene definito un template master e una serie di trasformazioni parametriche che ne producono versioni deformate.

Shape learning (Apprendimeto della forma da esempi): Questo è il caso nostro o perlomeno quello che si adatta alle nostre esigenze.Spesso risulta complicato fornire espressioni analitiche di un template e altrettanto difficile definire precisamente le trasformazioni che mappano un oggetto nelle sue possibili deformazioni.I metodi di Shape learning hanno come obiettivo l’apprendimentodella forma di un oggetto e delle sue possibili variazioni a prtire da un insieme di esempi.

Page 190: Bioidentià - Il Progetto Ottico

Nel metodo di Cootes il template viene modellato da poligonali; durante l’addestramento gli esempi nel training set sono allineati (manualmente) sulla base di punti notevoli. I molteplici gradi di libertà dati dalla mobilità spaziale di punti corrispondenti nei diversi pattern di esempio vengono fortemente ridotti (trasformata KL) per ottenere un modello parametrico con pochi gradi di libertà.Una parte operativa legata al riconoscimento è quello dell’estrazione dei particolari.

Feature Extraction (estrazione delle caratteristiche)

L’approccio statistico richiede il mapping di un pattern in uno spazio multidimensionale. Come già detto, un’immagine può essere considerata come un punto multidimensionale, ma tale rappresentazione mal si presta alla maggior parte dei problemi di riconoscimento (scarsa invarianza a piccoli cambiamenti locali, deformazioni, prospettiva, illuminazione, ...).Con il termine feature extraction si intende in generale il processo di estrazione di caratteristiche da un’immagine.

Page 191: Bioidentià - Il Progetto Ottico

Il pre-processing dell’immagine è un’elaborazione iniziale dell’immagine eseguita allo scopo di semplificare e rendere più efficace la successiva estrazione delle caratteristiche. Si utilizzano tecniche di filtraggio per:

Migliorare il contrasto dell’immagine. Ridurre il rumore. Separare meglio gli oggetti dallo sfondo.

Istogramma

L’istogramma di un’immagine digitale a livelli di grigio indica il numero di pixel dell’immagine per ciascun livello di grigio:

Dall’istogramma possono essere estratte informazioni interessanti sull’immagine:

se la maggior parte dei pixel assume valori di grigio “condensati”

ciò significa che l’immagine ha uno scarso contrasto (range dinamico).

se nell’istogramma sono predominanti le basse intensità, l’immagine è molto scura e viceversa ...

un istogramma bimodale denota spesso la presenza di un oggetto abbastanza omogeneo su uno sfondo di luminosità pressoché costante.

Una delle parti del software da noi scritto ipotizza l’suo dei classificatori la cui teoria, in linea di massima, è quella che segue.

Classificazione (approccio statistico) Una volta estratte le feature dai pattern, la classificazione cnsiste nell’associare ogni pattern a una o più classi.

Se un pattern viene associato a una sola classe si parla di classificazione esclusiva classificazione esclusiva; se invece il pattern può appartenere, con un certo grado di probabilità, a più classi si parla di classificazione classificazione continua o continua o fuzzy fuzzy.

Page 192: Bioidentià - Il Progetto Ottico

La classificazione si dice supervisionata supervisionata nel caso in cui le classi sono note a priori e i pattern del training set sono etichettati; non supervisionata supervisionata nel tal caso in cui le classi sono sconosciute e devono essere derivate dai dati stessi.

Approccio Bayesiano

Il problema è posto in termini probabilistici. Se tutte le le distribuzioni in gioco sono note l’approccio byesiano costituisce la migliore regola di classificazione possibile.Notazione e definizioni di base

Sia V uno spazio di pattern d-dimensionali e

W = {w1, w2, ..., ws}

un insieme di classi disgiunte costituite da elementi di V

Per ogni e per ogni ndichiamo con p(x|wi) la densità di probabilità condizionale di x data wi, ovvero la densità di probabilità che il prossimo pattern sia x sotto l’ipotesi che la sua classe di appartenenza sia wi

Per ogni indichiamo con P(wi) la probabilità a priori di wi ovvero la probabilità, indipendentemente dall’osservazione, che il prossimo pattern da classificare sia di classe wi

Per ogni indichiamo con p(x) la densità di probabilitàassoluta di x, ovvero la densità di probabilità che il prossimo

Page 193: Bioidentià - Il Progetto Ottico

pattern da classificare sia x.

Per ogni e per ogni indichiamo con P(wi|x) la probabilit probabilità a posteriori a posteriori di wi dato x, ovvero la probabilità che avendo osservato il pattern x, la classe di appartenenza sia wi. Per il teorema di Bayes:

Page 194: Bioidentià - Il Progetto Ottico

Il controllo d’inquadratura della retina.

In questa fase l’identificazione dell’OGGETTO retina all’interno di un immagine viene eseguita in senso generale.

La funzionalità è indirizzata a individuare una retina dentro ad un immagine con il fine di ritagliare la porzione di questa e con questo parte creare una nuova immagine la quale verrà utilizzata per la fase dell’identificazione.Il sistema utilizza il metodo haar-like per l’individuazione della forma ottimale della retina inquadrata.Questa fase della programmazione può essere suddivisa in due fasi ben precise e precisamente quella in cui si esegue il training per fare in modo che il sistema riesca ad individuare automaticamente quando all’interno dell’immagine giunta dalla camera è presente una retina analizzabile.Per fare questo è necessario spiegare al sistema quali possono essere immagini accettabili (positive) e quelle che no (negative).La struttura letta da disco relativa alla cascata di classificatori indirizzati alla retina viene creata mediante una serie di operazioni che devono essere eseguite.Il sistema necessita di una serie di immagini positive e negative relative al concetto di retina.In altre parole prima di creare il training si devono creare immagini che NON contengono rappresentazioni dell’immagine ed altre invece che la contengono.La struttura della directory è quella che segue:

/img img1.jpg img2.jpgbg.txt

Dove il file bg.txt:

img/img1.jpgimg/img2.jpg

La creazione dei campioni positivi invece deve essere eseguita mediante una determinata sequenza di funzioni facenti parte del programma chiamato CREATESAMPLES.

Page 195: Bioidentià - Il Progetto Ottico

Questo ha tra le funzioni quella di analizzare i parametri passati.Le altre funzioni utilizzate possiedono come prototipo quello definito nel file .h

/* * cvhaartraining.h * * haar training functions */

#ifndef _CVHAARTRAINING_H_#define _CVHAARTRAINING_H_

#ifdef __cplusplusextern "C" {#endif

/* * cvCreateTrainingSamples * * Create training samples applying random distortions to sample image and * store them in .vec file * * filename - .vec file name * imgfilename - sample image file name * bgcolor - background color for sample image * bgthreshold - background color threshold. Pixels those colors are in range * [bgcolor-bgthreshold, bgcolor+bgthreshold] are considered as transparent * bgfilename - background description file name. If not NULL samples * will be put on arbitrary background * count - desired number of samples * invert - if not 0 sample foreground pixels will be inverted * if invert == CV_RANDOM_INVERT then samples will be inverted randomly * maxintensitydev - desired max intensity deviation of foreground samples pixels * maxxangle - max rotation angles * maxyangle * maxzangle * showsamples - if not 0 samples will be shown * winwidth - desired samples width * winheight - desired samples height */#define CV_RANDOM_INVERT 0x7FFFFFFF

void cvCreateTrainingSamples( const char* filename, const char* imgfilename, int bgcolor, int bgthreshold, const char* bgfilename, int count, int invert = 0, int maxintensitydev = 40, double maxxangle = 1.1, double maxyangle = 1.1, double maxzangle = 0.5, int showsamples = 0, int winwidth = 24, int winheight = 24 );

void cvCreateTestSamples( const char* infoname, const char* imgfilename, int bgcolor, int bgthreshold, const char* bgfilename, int count,

Page 196: Bioidentià - Il Progetto Ottico

int invert, int maxintensitydev, double maxxangle, double maxyangle, double maxzangle, int showsamples, int winwidth, int winheight );

/* * cvCreateTrainingSamplesFromInfo * * Create training samples from a set of marked up images and store them into .vec file * infoname - file in which marked up image descriptions are stored * num - desired number of samples * showsamples - if not 0 samples will be shown * winwidth - sample width * winheight - sample height * * Return number of successfully created samples */int cvCreateTrainingSamplesFromInfo( const char* infoname, const char* vecfilename, int num, int showsamples, int winwidth, int winheight );

/* * cvShowVecSamples * * Show samples stored in .vec file * filename - .vec file name * winwidth - sample width * winheight - sample height */void cvShowVecSamples( const char* filename, int winwidth, int winheight );

/* * cvCreateCascadeClassifier * * Create cascade classifier * dirname - directory name in which cascade classifier will be created. * It must exist and contain subdirectories 0, 1, 2, ... (nstages-1). * vecfilename - name of .vec file with object's images * bgfilename - name of background description file * npos - number of positive samples used in training of each stage * nneg - number of negative samples used in training of each stage * nstages - number of stages * numprecalculated - number of features being precalculated. Each precalculated feature * requires (number_of_samples*(sizeof( float ) + sizeof( short ))) bytes of memory * numsplits - number of binary splits in each weak classifier * 1 - stumps, 2 and more - trees. * minhitrate - desired min hit rate of each stage * maxfalsealarm - desired max false alarm of each stage * weightfraction - weight trimming parameter * mode - 0 - BASIC = Viola * 1 - CORE = All upright * 2 - ALL = All features * symmetric - if not 0 vertical symmetry is assumed * equalweights - if not 0 initial weights of all samples will be equal * winwidth - sample width * winheight - sample height

Page 197: Bioidentià - Il Progetto Ottico

* boosttype - type of applied boosting algorithm * 0 - Discrete AdaBoost * 1 - Real AdaBoost * 2 - LogitBoost * 3 - Gentle AdaBoost * stumperror - type of used error if Discrete AdaBoost algorithm is applied * 0 - misclassification error * 1 - gini error * 2 - entropy error */void cvCreateCascadeClassifier( const char* dirname, const char* vecfilename, const char* bgfilename, int npos, int nneg, int nstages, int numprecalculated, int numsplits, float minhitrate = 0.995F, float maxfalsealarm = 0.5F, float weightfraction = 0.95F, int mode = 0, int symmetric = 1, int equalweights = 1, int winwidth = 24, int winheight = 24, int boosttype = 3, int stumperror = 0 );

#ifdef __cplusplus}#endif /* extern "C" */

#endif /* _CVHAARTRAINING_H_ */

Una volta creata la struttura mediante le funzioni di training il software la utilizzerà per identificare in quale momento in una certa sequenza di immagini provenienti dalla telecamera è presente un immagine retinale.Il programma deve identificare tale immagine e dopo averla inserita in un rettangolo di cut tagliarla per creare l’immagine finale che verrà utilizzata per la fase di identificazione.Nella funzione main viene richiamata la funzione

InitRetinaDetect(classifierbase)

la quale ha lo scopo di inizializzare la cascata di CLASSIFICATORI HAAR.

const int root_w = 400, root_h = 400;

int main( int argc, char **argv ){ const char* facebaseopt="--facebase="; char* classifierbase = 0; char* aviname = 0; int auto_run = 0; if( argc > 1 && argv[argc-1][0] != '-' ) { aviname = argv[argc-1]; auto_run = 1; argc--; } if( argc > 1 && strncmp(argv[argc-1],facebaseopt,strlen(facebaseopt))==0 ) { classifierbase=argv[argc-1] + strlen(facebaseopt);

Page 198: Bioidentià - Il Progetto Ottico

argc--; } if( !InitRetinaDetect(classifierbase)) { fprintf( stderr, "Could not locate face classifier base at %s\n" "Use --facebase=<classifier base path> option to specify the base\n", classifierbase ); return -1; }

cpu_freq = cvGetTickFrequency(); printf("Tick frequency (*10^-6): %g\n", cpu_freq ); Fl_Window* w; { Fl_Window* o = root_window = new Fl_Window( root_w, root_h ); w = o; { Fl_Tabs* o = new Fl_Tabs( 10, 10, root_w - 20, root_h - 100 ); // camera tab { Fl_Group* o = new Fl_Group( 10, 30, root_w - 20, root_h - 110, "Face Detection" ); { VideoWindow* o = new VideoWindow( 15, 35, root_w - 30, root_h - 120 ); video_window = o; o->box( FL_BORDER_BOX ); o->color(0); } o->end(); } o->end(); Fl_Group::current()->resizable(o); } { const int bwidth = 30, bheight = 30; play_button = new Fl_Button( 10, root_h - 35, bwidth, bheight, "@>" ); play_button->callback((Fl_Callback*)cb_PauseResume); play_button->deactivate(); stop_button = new Fl_Button( 10 + bwidth, root_h - 35, bwidth, bheight, "@square" ); stop_button->callback((Fl_Callback*)cb_Stop); stop_button->deactivate(); video_button = new Fl_Button( 10 + bwidth*2, root_h - 35, bwidth, bheight, "..." ); video_button->callback((Fl_Callback*)cb_Open); cam_button = new Fl_Button( 10 + bwidth*3, root_h - 35, bwidth, bheight, "[o]" ); cam_button->callback((Fl_Callback*)cb_StartCam); video_pos = new Fl_Value_Slider( 10 + bwidth*4 + 10, root_h - 35, 200, 20, "Position" ); video_pos->type( FL_HOR_NICE_SLIDER ); record_button = new Fl_Button( 10 + bwidth*4 + 230, root_h - 35, bwidth, bheight, "@circle" ); record_button->labelcolor(FL_RED); record_button->callback((Fl_Callback*)cb_StartStopRecord ); record_button->deactivate(); fps_box = new Fl_Box( 10, root_h - 75, bwidth*4, bheight, "<No

Page 199: Bioidentià - Il Progetto Ottico

data>" ); fps_box->box( FL_DOWN_BOX ); } o->end(); } Fl::visual(FL_RGB); w->show(argc, argv); if( auto_run ) Fl::add_timeout( 0.1, cb_AutoRun, aviname ); Fl::run(); cb_Exit(0,0); return 0;}

Come dicevamo precedentemente il sistema utilizza la trasformata di GABOR e la trasformata WAVELET per l’analisi delle informazioni relative ad una generica retina.OpenCV utilizza le HAAR WAVELET.La precednte figura mostra la funzione Harr Wavelet.L’immagine successiva invece mostra il procedimento

concettuale per ottenere il vettore delle di dimansioni ottimizzate.In questo H ed L indicano il filtre passa alto e quello passa basso mentre HH indica il filtro passa alto utilizzato su ambedue gli assi X e Y.L’immagine a fianco si riferisce ad un immagine di esempio di

450x60.Ciascuna delle 87 dimensioni possiedono un valore reale compreso tra -1 e 1.Per ridurre lo spazio e il tempo computazionale necessario per la manipolazione il valore viene quantizzato in m,odo molto semplice convertendo il valore positivo in 1 e quello negativo in 0.In questo modo un immagine di 450x60 può essere rappresentata in 87 bits.I valori relativi alle dimensioni dell’immagine sono soltanto teoricizzati

in modalità puramente casuale in quanto la loro determinazione

Page 200: Bioidentià - Il Progetto Ottico

precisa dovrà essere eseguita mediante prove eseguite realmente.Matematicamente la funzione di HAAR SCALING è definita come segue:

Supponiamo che sia definita da

Definiamo come

Definiamo lo spazio del vettore Vj come

dove denota l’attraveramento lineare.

L’indice j si riferisce alla dilatazione mentre i si riferisce alla translazione.

La costante viene scelta tale a .

Se uno considera la funzione di scala su un altro intervallo oltre a [0,1], il fattore di normalizzazione potrebbe cambiare.

Volendo descrivere algoritmicamente la funzione di haarscaling abbiamo :

function y=haarscale(i,j)

y=zeros(3000,1); % 3000 is chosen to give a suitable resolution.

support_start = ceil(1000*i/2^j)+1; % Gives vector indices for where thesupport_end = floor(1000*(1+i)/2^j); % support of the function starts/end.

for k=1000+support_start:1000+support_end y(k) = 1;end

norm_factor = sqrt(2^j); % Normalizing factor w.r.t. the L^2-norm.

Page 201: Bioidentià - Il Progetto Ottico

y = norm_factor*y;

Per quanto riguarda la funzione di HAAR WAVELET :

Supponiamo sia definita da

Definiamo come

Definiamo il vettore dello spazio Wj

dove denota l’attraversamento lineare.

La costante è scelta .

Se uno considera la funzione di scala su un altro intervallo oltre a [0,1], il fattore di normalizzazione potrebbe cambiare.

Algoritmicamente la HAARWAVELET

function y=haarwavelet(i,j)

y=zeros(3000,1); % 3000 is chosen to give a suitable resolution.

support_start = ceil(1000*i/2^j)+1; % Gives vector indices representingsupport_middle = floor(1000*(0.5+i)/2^j); % the start/middle/end ofsupport_end = floor(1000*(1+i)/2^j); % the support of the wavelet.

for k=1000+support_start:1000+support_middle y(k) = 1;end

for k=1001+support_middle:1001+support_end

Page 202: Bioidentià - Il Progetto Ottico

y(k) = -1;end

norm_factor = sqrt(2^j); % Normalizing factor w.r.t. the L^2-norm.y = norm_factor*y;

La struttura di base di HAAR è :

La libreria OPENCV utilizza le seguenti strutture per la gestione delle funzioni cvHaar.

#define CV_HAAR_FEATURE_MAX 3

/* a haar feature consists of 2-3 rectangles with appropriate weights */typedef struct CvHaarFeature{ int tilted; /* 0 means up-right feature, 1 means 45--rotated feature */

/* 2-3 rectangles with weights of opposite signs and with absolute values inversely proportional to the areas of the rectangles. if rect[2].weight !=0, then the feature consists of 3 rectangles, otherwise it consists of 2 */ struct { CvRect r; float weight; } rect[CV_HAAR_FEATURE_MAX];} CvHaarFeature;

/* a single tree classifier (stump in the simplest case) that returns the response for the feature at the particular image location (i.e. pixel sum over subrectangles of the window) and gives out a value depending on the responce */typedef struct CvHaarClassifier{ int count; /* number of nodes in the decision tree */ CvHaarFeature* haarFeature; /* these are "parallel" arrays. Every index i corresponds to a node of the decision tree (root has 0-th index).

left[i] - index of the left child (or negated index if the left child is a leaf) right[i] - index of the right child (or negated index if the right child is a leaf) threshold[i] - branch threshold. if feature responce is <= threshold, left branch is chosen, otherwise right branch is chosed. alpha[i] - output value correponding to the leaf. */ float* threshold; /* array of decision thresholds */ int* left; /* array of left-branch indices */ int* right; /* array of right-branch indices */ float* alpha; /* array of output values */}CvHaarClassifier;

Page 203: Bioidentià - Il Progetto Ottico

/* a boosted battery of classifiers(=stage classifier): the stage classifier returns 1 if the sum of the classifiers' responces is greater than threshold and 0 otherwise */typedef struct CvHaarStageClassifier{ int count; /* number of classifiers in the battery */ float threshold; /* threshold for the boosted classifier */ CvHaarClassifier* classifier; /* array of classifiers */}CvHaarStageClassifier;

/* cascade of stage classifiers */typedef struct CvHaarClassifierCascade{ int count; /* number of stages */ CvSize origWindowSize; /* original object size (the cascade is trained for) */ CvHaarStageClassifier* stageClassifier; /* array of stage classifiers */}CvHaarClassifierCascade;

Come dicevamo nella funzione main viene richiamato l’inizializzatore InitRetinaDetect :

int InitRetinaDetect( const char* classifier_cascade_path ){ CvHaarClassifierCascade* cascade = cvLoadHaarClassifierCascade( classifier_cascade_path && strlen(classifier_cascade_path) > 0 ? classifier_cascade_path : "<default_face_cascade>", cvSize( ORIG_WIN_SIZE, ORIG_WIN_SIZE )); if( !cascade ) return 0; hid_cascade = cvCreateHidHaarClassifierCascade( cascade ); cvReleaseHaarClassifierCascade( &cascade ); return 1;}

Nella prima riga della funzione viene letta da disco la scascata di classificatori HAAR.I files letti hanno il seguente formato:

9126 4 12 9 0 -16 7 12 3 0 3haar_y3-0.031512 0 -12.087538 -2.217210 126 4 12 7 0 -110 4 4 7 0 3haar_x30.012396 0 -1-1.863394 1.327205 123 9 18 9 0 -13 12 18 3 0 3

Page 204: Bioidentià - Il Progetto Ottico

haar_y30.021928 0 -1-1.510525 1.062573 128 18 9 6 0 -18 20 9 2 0 3haar_y30.005753 0 -1-0.874639 1.176034 123 5 4 19 0 -15 5 2 19 0 2haar_x20.015014 0 -1-0.779457 1.260842 126 5 12 16 0 -16 13 12 8 0 2haar_y20.099371 0 -10.557513 -1.874300 125 8 12 6 0 -15 11 12 3 0 2haar_y20.002734 0 -1-1.691193 0.440097 1211 14 4 10 0 -111 19 4 5 0 2haar_y2-0.018859 0 -1-1.476954 0.443501 124 0 7 6 0 -14 3 7 3 0 2haar_y20.005974 0 -1-0.859092 0.852556 -5.042550

La sintassi della funzione che esegue la lettura è :

CvHaarClassifierCascade*cvLoadHaarClassifierCascade( const char* directory="<default_face_cascade>", CvSize origWindowSize=cvSize(24,24));

directoryNome del file che contiene la dscrizione dei classificatori creati mediante la fase di training.

origWindowSizeLa dimsnione originale dell’oggetto sulla quel è stato eseguito il training.

Page 205: Bioidentià - Il Progetto Ottico

La seconda funzionalità eseguita è quella relativa alla creazione della cascata di classificatori mediante l’utilizzo dei parametri letti.

/* hidden (optimized) representation of Haar classifier cascade */typedef struct CvHidHaarClassifierCascade CvHidHaarClassifierCascade;

CvHidHaarClassifierCascade*cvCreateHidHaarClassifierCascade( CvHaarClassifierCascade* cascade, const CvArr* sumImage=0, const CvArr* sqSumImage=0, const CvArr* tiltedSumImage=0, double scale=1 );

cascadeoriginal cascade that may be loaded from file using cvLoadHaarClassifierCascade.

sumImageIntegral (sum) single-channel image of 32-bit integer format. This image as well as the two subsequent images are used for fast feature evaluation and brightness/contrast normalization. They all can be retrieved from the input 8-bit single-channel image using function cvIntegral. Note that all the images are 1 pixel wider and 1 pixel taller than the source 8-bit image.

sqSumImageSquare sum single-channel image of 64-bit floating-point

format. tiltedSumImage

Tilted sum single-channel image of 32-bit integer format. scale

Initial scale (see cvSetImagesForHaarClassifierCascade).

In altre parole la funzione converte i parametri letti mediante la funzione precedente in un formato interno più veloce.Una volta creata questa catena e assegnato l’handle alla variabile di rappresentazione nel programma la cascata viene rilasciata.

cvReleaseHaarClassifierCascade( &cascade );

Sempre all’interno del MAIN il programma continua a richiamare la funzione GetNextFrame dentro alla quale esiste il richiamo della funzione alla quale è demandata la funzionalità di individuare se dentro all’immagine corrente giunta dalla telecamera esiste una retina.Questa funzione ha il compito di tracciare un rettangolo intorno a questa.

void DetectAndDrawRetina( IplImage* img )

Page 206: Bioidentià - Il Progetto Ottico

{ if( hid_cascade && img ) { int scale = 2; CvSize img_size = cvGetSize( img ); IplImage* temp = cvCreateImage( cvSize(img_size.width/2,img_size.height/2), 8, 3 ); int i;

cvPyrDown( img, temp ); cvClearMemStorage( storage );

if( hid_cascade ) { CvSeq* retinas = cvHaarDetectObjects( temp, hid_cascade, storage, 1.2, 2, 1 ); for( i = 0; i < (retinas ? retinas->total : 0); i++ ) { CvRect r = *(CvRect*)cvGetSeqElem( retinas, i ); cvRectangle( img, cvPoint(r.x*scale,/*img->height - */r.y*scale), cvPoint((r.x+r.width)*scale,/*img->height - */(r.y+r.height)*scale), CV_RGB(255,0,0), 3 ); } }

cvReleaseImage( &temp ); }}

L’analisi iniziale, quella relativa al training, è stata eseguita con il seguente campionamento d’immagini :

POSITIVE

Page 207: Bioidentià - Il Progetto Ottico

NEGATIVE

Questi campioni sono stati scelti per lo scopo funzionale in ufficio.In altre parole non avendo una mucca in ufficio la sperimentazione l’ho eseguita mostrando al programma come riconoscere un immagine di una retina rappresentata da un immagine mescolata ad altri oggetti.Passando con la telecamera su un gruppo di oggetti il programma doveva delimitare l’immagine retinale.

Page 208: Bioidentià - Il Progetto Ottico

Nell’istante in cui l’identificazione dovrà essere eseguita in ambiente operativo reale, il training dovrà essere rieseguito catalogando una latra serie di immagini classificate come positive e altre negative.

Page 209: Bioidentià - Il Progetto Ottico

Il SISTEMA DI IDENTIFICAZIONE.

Tutto il sistema di identificazione è basato sui modelli di Markov nascosti implementati all’inetrno della libreria OpenCV.Le funzioni utilizzate per la gestione pretendono una serie di parametri i quali sono i valori classici utilizzati nei sistemi HIDDEN MARKOV MODELL.

Gli HMM sono una classe di strumenti matematici sempre più largamente utilizzata nel settore della elaborazione dei segnali e della identificazione parametrica; questa locuzione inglese ha certamente il vantaggio della compattezza rispetto alla più esplicativa perifrasi modelli di sistemi dinamici stocastici parzialmente osservati, la quale tuttavia ne riunisce efficacemente tutte le caratteristiche principali.Essi descrivono infatti sistemi dinamici regolati da equazioni, in generale non lineari, in cui stati ed osservazioni consistono in processi aleatori piuttosto che in quantità deterministiche, ed in cui non è possibile una osservazione diretta del valore dello stato corrente ma si ha accesso soltanto a versioni "corrotte" da rumore stocastico dello stato stesso, regolate da una equazione di misura.Talvolta con questa terminologia si intende il più ristretto caso in cui sia gli stati del sistema che le osservazioni assumono valori solamente in un insieme discreto, e le equazioni che determinano l’evoluzione del sistema sono lineari.MM può essere trattata in maniera unitaria ricorrendo ai reference probability methods o metodi del cambio di misura di probabilità.

Page 210: Bioidentià - Il Progetto Ottico

Un biettivo, una volta a disposizione i parametri definitivi del modello, e quello di ottenere una stima della sequenza degli stati attraversati dall’HMM sollecitato dalla corrispondente sequenza delle osservazioni. Parlando concettualmente di HMM sono da prendere in considerazione le stime in linea (forward estimates), quelle ottenute in base alle osservazioni passate (rispetto ovviamente all’istante corrente di stima), che, soprattutto, le più significative stime a posteriori (smoothed estimates) che tengono conto di tutte le osservazioni passate, presenti e future.Una difficoltà importante che incorre nell’utilizzo dei modelli matematici per rappresentare un qualsiasi fenomeno fisico o sistema dinamico consiste nel fatto che, solitamente, si hanno a priori pochissime informazioni da poter sfruttare per stabilire i valori dei parametri fondamentali dei modelli stessi, una volta scelta la classe di formalismi da adottare. Gli HMM hanno una straordinaria capacità di autoapprendimento di questi parametri che si fonda su una tecnica detta di massimizzazione dell’aspettazione (in inglese EM-expectation maximization); essenziale a questo scopo è lo stimare una serie di altre quantità ausiliarie, oltre agli stati del modello, quali il numero di transizioni tra i diversi stati nel corso della sequenza, il numero di occupazioni degli stati stessi, ed altre che vedremo in seguito.É interessante accennare al fatto che rientrano nella categoria degli HMM anche formalismi ben noti come il filtro di Kalman, che si riottiene dal modello generale nel caso di stati e osservazioni continue ed equazioni lineari, insieme alla sua versione estesa in cui si considerano equazioni generali di tipo non lineare;

sfruttando i reference probability methods si ottengono anche in questi ambiti soluzioni molto eleganti. Nel nostro caso utilizzeremo le Embedded Hidden Markov Model chiamate brevemente EHMM.Le immagini che seguono rappresentano il principio di base degli HMM e le varie diversità che esitono nell’ambito degli stessi.L’immagine rappresenta graficamente l’utilizzo degli HMM nell’ambito di un riconoscimento facciale.Gli HMM vengono utilizzati in diversi tipi di riconoscimento come ad esempio in quello vocale.

A seconda dell’applicazione il metodo di gestione diventa sempre più complesso.La diversità è riferita alla modalità di trattatamento degli

Page 211: Bioidentià - Il Progetto Ottico

alberi su cui sono strutturati gli HMM.

I modelli marcoviani si basano anche su fattori statistici per la valutazione dei percosri ottimali.Matematicamente abbiamo :S è un set di stati. Il processo random {Xt|t=1,2….} è una catena di Markov se "t, la variabile random Xt soddisfa la proprietà di MARKOV.

pij=P{Xt+1=j | Xt=i, Xt-1=it-1, Xt-2=it-2,…….X1=i1} = P{Xt+1=j | Xt=i }

Quindi, abbiamo :

P(X1X2…….Xk-1Xk)=P(Xk | X1X2……. Xk-1).P(X1X2…….Xk-1) =P(Xk | Xk-1).P(X1X2…….Xk-1)

=P(X1). P P(Xi+1 | Xi) for i=1,k-1

pij è chiamata matrice di transizione.

Markov Model=Markov Chain + Transition matrix.

HMM è una catena di Markov con un numero finito di stati osswervabili.Questi stati hanno una probabilità di distribuzione associata con il set di vettori di osservazione.

Page 212: Bioidentià - Il Progetto Ottico

Cose necessarie per caratterizzare un HMM sono:

1. La matrice probabilistica di transazione di stato.2. Uno stato iniziale relativo alla probabililità di

distribuzione dello stato.3. Una funzione relativa alla probabile densità associata con

ogni stato di osservazione.

La seguente immagine mostra il flusso relativo al training di un immagine.

Trattando gli HMM a livello di programmazione ci troviamo davanti a concetti particolari come ad esempio gli stati, i superstati ecc.Questi vengono proiettati nella serie di valori che corrispondono alla serie di parametri che le funzioni di OPENCV legate agli HMM necessitano.Gli HMM implementati nel nostro programma utilizzano le seguenti strutture per la memorizzazione su disco.

CvHMMEmbedded HMM Structure

typedef struct _CvEHMM { int level; int num_states; float* transP; float** obsProb; union { CvEHMMState* state;

Page 213: Bioidentià - Il Progetto Ottico

struct _CvEHMM* ehmm; } u; } CvEHMM;

levelLevel of embedded HMM. If level ==0, HMM is most external. In 2D HMM there are two types of HMM: 1 external and several embedded. External HMM has level ==1, embedded HMMs have level ==0 .

num_statesNumber of states in 1D HMM.

transPState-to-state transition probability, square matrix (num_state×num_state).

obsProbObservation probability matrix.

stateArray of HMM states. For the last-level HMM, that is, an HMM without embedded HMMs, HMM states are real.

ehmmArray of embedded HMMs. If HMM is not last-level, then HMM states are not real and they are HMMs.

E anche la seguente struttura

CvImgObsInfoImage Observation Structure

typedef struct CvImgObsInfo { int obs_x; int obs_y; int obs_size; float** obs; int* state; int* mix; } CvImgObsInfo;

obs_xNumber of observations in the horizontal direction.

obs_yNumber of observations in the vertical direction.

obs_sizeLength of every observation vector.

obsPointer to observation vectors stored consequently. Number of vectors is obs_x*obs_y .

stateArray of indices of states, assigned to every observation vector. mix

Mediante le funzioni di scrittura e di lettura che seguono vengono eseguite le gestioni su disco di queste strutture di dati.

bool CContEHMM::Save( const char* filename ){ FILE* file;

if (!m_hmm) return false;

file = fopen( filename, "wt" );

Page 214: Bioidentià - Il Progetto Ottico

if (!file) return false;

// write topology fprintf(file, "%s %d\n", "<NumSuperStates>", m_hmm->num_states ); fprintf(file, "%s ", "<NumStates>"); for( int i = 0; i < m_hmm->num_states; i++ ) { fprintf(file, "%d ", m_hmm->u.ehmm[i].num_states ); } fprintf(file, "\n");

fprintf(file, "%s ", "<NumMixtures>"); for( i = 0; i < m_hmm->num_states; i++ ) { CvEHMM* ehmm = &(m_hmm->u.ehmm[i]);

for( int j = 0; j < ehmm->num_states; j++ ) { fprintf(file, "%d ", ehmm->u.state[j].num_mix ); } } fprintf(file, "\n");

fprintf(file, "%s %d\n", "<VecSize>", m_vectSize);

//consequently write all hmms CvEHMM* hmm = m_hmm; for( i = 0; i < m_hmm->num_states + 1; i++ ) { if (hmm->level == 0 ) fprintf(file, "%s\n", "<BeginEmbeddedHMM>"); else fprintf(file, "%s\n", "<BeginExternalHMM>");

fprintf(file, "%s %d\n", "<NumStates>", hmm->num_states);

if (hmm->level == 0 ) { for ( int j = 0; j < hmm->num_states; j++) { CvEHMMState* state = &(hmm->u.state[j]);

fprintf(file, "%s %d\n", "<State>", j); fprintf(file, "%s %d\n", "<NumMixes>", state->num_mix);

float* mu = state->mu; float* inv_var = state->inv_var;

for( int m = 0; m < state->num_mix; m++) { fprintf(file, "%s %d %s %f\n", "<Mixture>", m, "<Weight>", state->weight[m] ); fprintf(file, "%s\n", "<Mean>");

for (int k = 0; k < m_vectSize; k++) { fprintf(file, "%f ", mu[0]); mu++; }

Page 215: Bioidentià - Il Progetto Ottico

fprintf(file, "\n"); fprintf(file, "%s\n", "<Inverted_Deviation>"); for (k = 0; k < m_vectSize; k++) { fprintf(file, "%f ", inv_var[0]); inv_var++; } fprintf(file, "\n");

fprintf(file, "%s %f\n", "<LogVarVal>", state->log_var_val[m] );

} } }

//write the transition probability matrix fprintf(file, "%s\n", "<TransP>" ); float* prob = hmm->transP;

for (int j = 0; j < hmm->num_states; j++) { for (int k = 0; k < hmm->num_states; k++) { fprintf(file, "%f ", *prob); prob++; } fprintf(file, "\n"); }

if( hmm->level == 0 ) fprintf(file, "%s\n", "<EndEmbeddedHMM>"); else fprintf(file, "%s\n", "<EndExternalHMM>");

hmm = &(m_hmm->u.ehmm[i]); } fclose(file); return true;}

bool CContEHMM::Load( const char* filename ){ FILE* file; int num_states[128]; int num_mix[128]; char temp_char[128];

if (m_hmm) cvRelease2DHMM( &m_hmm);

file = fopen( filename, "rt" );

if (!file) return false;

// read topology fscanf(file, "%s %d\n", temp_char, num_states); fscanf(file, "%s ", temp_char); for( int i = 0; i < num_states[0]; i++ ) { fscanf(file, "%d ", num_states + i + 1 );

Page 216: Bioidentià - Il Progetto Ottico

} fscanf(file, "\n"); //compute total number of internal states int total_states = 0; for( i = 0; i < num_states[0]; i++ ) { total_states += num_states[i+1]; } //read number of mixtures fscanf(file, "%s ", temp_char); for( i = 0; i < total_states; i++ ) { fscanf(file, "%d ", &num_mix[i] ); } fscanf(file, "\n");

fscanf(file, "%s %d\n", temp_char, &m_vectSize);

m_hmm = cvCreate2DHMM( num_states, num_mix, m_vectSize);

//create HMM with known parameters//!!! cvCreate2DHMM( &m_hmm, num_states, num_mix, m_vectSize); if (!m_hmm ) return false;

//consequently read all hmms CvEHMM* hmm = m_hmm; for( i = 0; i < num_states[0]+1; i++ ) { fscanf(file, "%s\n", temp_char); int temp_int; fscanf(file, "%s %d\n", temp_char , &temp_int); assert(temp_int==num_states[i]);

if ( i!= 0 ) { for (int j = 0; j < num_states[i]; j++) { CvEHMMState* state = &(hmm->u.state[j]);

fscanf(file, "%s %d\n", temp_char, &temp_int); assert(temp_int == j);

fscanf(file, "%s %d\n", temp_char, &temp_int); assert(temp_int == state->num_mix);

float* mu = state->mu; float* inv_var = state->inv_var;

for( int m = 0; m < state->num_mix; m++) { int temp_int; fscanf(file, "%s %d %s %f\n", temp_char, &temp_int, temp_char, &(state->weight[m]) ); assert( temp_int == m ); fscanf(file, "%s\n", temp_char );

for (int k = 0; k < m_vectSize; k++) { fscanf(file, "%f ", mu);

Page 217: Bioidentià - Il Progetto Ottico

mu++; } fscanf(file, "\n"); fscanf(file, "%s\n", temp_char); for (k = 0; k < m_vectSize; k++) { fscanf(file, "%f ", inv_var); inv_var++; } fscanf(file, "\n");

fscanf(file, "%s %f\n", temp_char, &(state->log_var_val[m]) ); } } }

//read the transition probability matrix fscanf(file, "%s\n", temp_char ); float* prob = hmm->transP;

for (int j = 0; j < hmm->num_states; j++) { for (int k = 0; k < hmm->num_states; k++) { fscanf(file, "%f ", prob); prob++; } fscanf(file, "\n"); }

fscanf( file, "%s\n", temp_char );

hmm = &(m_hmm->u.ehmm[i]); } fclose(file); return true;}

Su disco le informazioni salvate possiedono la seguente forma.

<NumSuperStates> 5<NumStates> 3 6 6 6 3 <NumMixtures> 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 <VecSize> 8<BeginExternalHMM><NumStates> 5<TransP>-0.083382 -2.525729 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.133531 -2.079442 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.133531 -2.079442 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.051293 -2.995732 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 0.000000 <EndExternalHMM><BeginEmbeddedHMM><NumStates> 3<State> 0<NumMixes> 3

Page 218: Bioidentià - Il Progetto Ottico

<Mixture> 0 <Weight> 0.769076<Mean>-20.972395 -1.199845 -9.647115 0.250141 -3.410903 0.394978 -3.123760 0.038134 <Inverted_Deviation>0.014614 0.026245 0.022608 0.027866 0.058584 0.056817 0.068044 0.070711 <LogVarVal> 30.856710<Mixture> 1 <Weight> 0.052209<Mean>473.255920 11.369661 18.953630 1.685655 -10.397700 1.066247 -1.562027 0.323794 <Inverted_Deviation>0.007808 0.003862 0.070711 0.038979 0.070711 0.070711 0.070711 0.070711 <LogVarVal> 31.478554<Mixture> 2 <Weight> 0.178715<Mean>-212.370987 0.200874 -183.015442 4.668548 16.942772 -3.695751 15.826168 0.028298 <Inverted_Deviation>0.011709 0.016380 0.012051 0.007986 0.017965 0.019467 0.020320 0.025447 <LogVarVal> 37.912323<State> 1<NumMixes> 3<Mixture> 0 <Weight> 0.073511<Mean>-172.158371 -1.767324 -38.203041 4.343173 5.701460 0.570762 3.160259 0.587821 <Inverted_Deviation>0.011865 0.014904 0.028598 0.030125 0.039158 0.070711 0.070711 0.070711 <LogVarVal> 31.463648<Mixture> 1 <Weight> 0.122940<Mean>141.690094 -2.228673 9.012510 -2.404523 -2.345371 -0.013314 -3.915411 1.399009 <Inverted_Deviation>0.013544 0.017109 0.021005 0.024648 0.035656 0.069890 0.070711 0.070711 <LogVarVal> 31.807859<Mixture> 2 <Weight> 0.803549<Mean>-1.835994 -0.325710 -26.794296 0.163191 -0.147022 -2.228513 0.316842 -0.291369 <Inverted_Deviation>0.023006 0.030401 0.026106 0.038078 0.063985 0.050297 0.070711 0.070711 <LogVarVal> 29.795156<State> 2<NumMixes> 3<Mixture> 0 <Weight> 0.114630<Mean>187.055984 0.339832 -151.698074 -5.774115 12.813437 -3.688910 -12.469172 -1.845637 <Inverted_Deviation>0.009355 0.015851 0.012498 0.008687 0.016760 0.025930 0.020683 0.024815 <LogVarVal> 37.839188<Mixture> 1 <Weight> 0.864253<Mean>9.724429 1.652164 -2.467111 -0.952352 -1.476223 0.860395 1.329256 0.235927 <Inverted_Deviation>0.020711 0.049239 0.022015 0.034982 0.067921 0.042441 0.053227 0.070711 <LogVarVal> 30.067411<Mixture> 2 <Weight> 0.021116<Mean>-482.082367 181.330582 31.898191 -20.684919 -6.698741 0.991098 0.861548 -1.186828 <Inverted_Deviation>0.006135 0.012554 0.070711 0.051096 0.031708 0.070711 0.070711 0.070711 <LogVarVal> 31.072191<TransP>-0.051505 -2.991724 -10000000000.000000

Page 219: Bioidentià - Il Progetto Ottico

-10000000000.000000 -0.032199 -3.451890 -10000000000.000000 -10000000000.000000 0.000000 <EndEmbeddedHMM><BeginEmbeddedHMM><NumStates> 6<State> 0<NumMixes> 3<Mixture> 0 <Weight> 0.061688<Mean>332.239349 -5.602865 -14.591848 25.645439 -13.951871 2.334095 -1.746691 0.068255 <Inverted_Deviation>0.006121 0.004254 0.028941 0.021972 0.036400 0.070711 0.070711 0.070711 <LogVarVal> 33.755962<Mixture> 1 <Weight> 0.847403<Mean>-22.062757 1.276612 -15.454859 -1.293295 -1.640206 -0.550484 -0.921772 -0.228833 <Inverted_Deviation>0.016921 0.019725 0.031083 0.031985 0.051025 0.070711 0.070711 0.070711 <LogVarVal> 30.420504<Mixture> 2 <Weight> 0.090909<Mean>-307.269745 -6.480935 -103.124588 -1.383479 24.288076 -4.534930 9.166031 2.136502 <Inverted_Deviation>0.008850 0.007742 0.023042 0.011087 0.018224 0.070711 0.063117 0.042436 <LogVarVal> 35.016418<State> 1<NumMixes> 3<Mixture> 0 <Weight> 0.200000<Mean>29.304270 -6.858905 -140.366104 4.895126 5.822843 -4.513440 -6.845486 1.737466 <Inverted_Deviation>0.019348 0.034450 0.017851 0.027495 0.067659 0.018135 0.048407 0.070711 <LogVarVal> 31.892227<Mixture> 1 <Weight> 0.757143<Mean>-8.627180 -3.913884 0.767934 1.317592 -1.155759 -5.062126 1.812659 -0.273500 <Inverted_Deviation>0.024372 0.058368 0.027968 0.043595 0.070711 0.038213 0.070711 0.070711 <LogVarVal> 29.055836<Mixture> 2 <Weight> 0.042857<Mean>224.008102 -40.747932 -22.446465 -15.536781 1.613000 -15.609318 -5.861628 1.234214 <Inverted_Deviation>0.011552 0.029264 0.013270 0.021500 0.070711 0.055860 0.063269 0.070711 <LogVarVal> 31.676809<State> 2<NumMixes> 3<Mixture> 0 <Weight> 0.657778<Mean>-16.048042 3.164254 -3.990868 -0.207382 0.337395 6.381185 -1.768695 -0.399991 <Inverted_Deviation>0.024945 0.041299 0.011888 0.038374 0.067946 0.018147 0.070417 0.070711 <LogVarVal> 31.150278<Mixture> 1 <Weight> 0.213333<Mean>-129.183838 -2.374153 58.049500 -3.579679 -2.807038 -12.895558 4.481920 0.560053 <Inverted_Deviation>0.010968 0.021525 0.012028 0.029317 0.065543 0.026986 0.052524 0.070711 <LogVarVal> 32.813408<Mixture> 2 <Weight> 0.128889

Page 220: Bioidentià - Il Progetto Ottico

<Mean>136.449188 15.072393 21.410343 0.304627 1.185207 1.440380 -1.137706 -0.825282 <Inverted_Deviation>0.013488 0.012942 0.013954 0.020873 0.033767 0.026371 0.035187 0.069733 <LogVarVal> 34.407440<State> 3<NumMixes> 3<Mixture> 0 <Weight> 0.348624<Mean>19.712467 3.993253 30.475801 13.512649 -4.126996 22.256044 -4.251338 -3.650669 <Inverted_Deviation>0.023656 0.022237 0.016146 0.014870 0.050358 0.015594 0.036664 0.064872 <LogVarVal> 33.654343<Mixture> 1 <Weight> 0.165138<Mean>128.506607 -7.856478 77.194824 -8.695423 -13.027184 -15.868305 -14.322035 4.716886 <Inverted_Deviation>0.009385 0.022030 0.017512 0.022014 0.039319 0.040382 0.041146 0.070711 <LogVarVal> 33.208969<Mixture> 2 <Weight> 0.486239<Mean>-41.485161 -2.108405 -60.229691 -0.742463 8.568585 2.393284 12.158751 1.010459 <Inverted_Deviation>0.017285 0.032958 0.016136 0.020023 0.040785 0.023420 0.035068 0.060603 <LogVarVal> 33.194424<State> 4<NumMixes> 3<Mixture> 0 <Weight> 0.901587<Mean>20.881762 -1.768637 -6.697111 -1.355091 -0.253182 -4.685781 -0.407999 -0.137556 <Inverted_Deviation>0.027539 0.044917 0.022056 0.041149 0.070711 0.047551 0.070711 0.070711 <LogVarVal> 29.272205<Mixture> 1 <Weight> 0.041270<Mean>200.368622 11.540556 45.782974 3.420283 -18.899872 4.935305 -8.701583 0.798857 <Inverted_Deviation>0.012718 0.011904 0.028538 0.014262 0.033927 0.065217 0.070711 0.070711 <LogVarVal> 32.593105<Mixture> 2 <Weight> 0.057143<Mean>-102.914154 2.887007 -68.612213 6.443975 14.543627 1.761935 9.705220 0.981170 <Inverted_Deviation>0.015346 0.015776 0.024968 0.020148 0.044144 0.039683 0.060597 0.070711 <LogVarVal> 32.299801<State> 5<NumMixes> 3<Mixture> 0 <Weight> 0.238411<Mean>215.408157 -2.994002 -67.357452 10.044118 17.727612 -3.746516 -5.952805 1.734724 <Inverted_Deviation>0.011668 0.011538 0.018723 0.013939 0.020979 0.049652 0.048738 0.044163 <LogVarVal> 34.751118<Mixture> 1 <Weight> 0.509934<Mean>-24.402103 17.768127 2.630338 -5.581841 0.374965 0.299918 0.793470 0.396344 <Inverted_Deviation>0.009372 0.015522 0.061483 0.069743 0.070711 0.070711 0.070711 0.070711 <LogVarVal> 29.463020<Mixture> 2 <Weight> 0.251656<Mean>

Page 221: Bioidentià - Il Progetto Ottico

79.709373 9.802913 -22.161613 -8.858971 -14.081789 2.421615 2.427852 -1.545525 <Inverted_Deviation>0.027740 0.017422 0.020816 0.020394 0.041865 0.043405 0.048802 0.070711 <LogVarVal> 31.958019<TransP>-0.053346 -2.957511 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.121361 -2.169054 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.073766 -2.643512 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.158748 -1.918759 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.052129 -2.979984 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 0.000000 <EndEmbeddedHMM><BeginEmbeddedHMM><NumStates> 6<State> 0<NumMixes> 3<Mixture> 0 <Weight> 0.024561<Mean>190.812363 -2.622171 13.340729 -1.307912 3.414199 0.007860 1.341246 -0.745841 <Inverted_Deviation>0.010704 0.009503 0.032570 0.070711 0.065904 0.070711 0.070711 0.070711 <LogVarVal> 30.512737<Mixture> 1 <Weight> 0.838597<Mean>-28.437531 2.835221 4.740308 -0.554232 -0.054382 -0.092343 -0.135304 0.087556 <Inverted_Deviation>0.016608 0.028242 0.042271 0.063736 0.070711 0.070711 0.070711 0.070711 <LogVarVal> 28.757013<Mixture> 2 <Weight> 0.136842<Mean>-289.311829 -8.882969 33.374794 -11.372365 -1.015401 3.743531 -1.616095 0.227328 <Inverted_Deviation>0.006962 0.007311 0.010206 0.022349 0.034598 0.032280 0.063989 0.070711 <LogVarVal> 35.045723<State> 1<NumMixes> 3<Mixture> 0 <Weight> 0.033019<Mean>96.899635 -14.256236 42.901783 -11.595068 9.928827 -4.615505 -12.232879 3.404555 <Inverted_Deviation>0.024551 0.014728 0.012893 0.038507 0.043853 0.034159 0.070711 0.070711 <LogVarVal> 31.913870<Mixture> 1 <Weight> 0.759434<Mean>-22.718081 -2.177552 22.436535 0.733987 0.292511 -0.798927 -0.138575 -0.455182 <Inverted_Deviation>0.023305 0.049659 0.020533 0.039577 0.070711 0.038835 0.070711 0.070711 <LogVarVal> 29.651739<Mixture> 2 <Weight> 0.207547<Mean>-51.747776 -1.974753 183.901276 4.065125 -1.189533 -33.964375 6.775185 0.415048 <Inverted_Deviation>0.016178 0.031040 0.015782 0.031070 0.066429 0.017635 0.057697 0.070711 <LogVarVal> 32.047115<State> 2<NumMixes> 3

Page 222: Bioidentià - Il Progetto Ottico

<Mixture> 0 <Weight> 0.368984<Mean>-10.272039 11.030415 17.832426 2.757569 0.699663 -5.451602 0.950643 -1.928197 <Inverted_Deviation>0.024173 0.016458 0.025588 0.032414 0.064883 0.068372 0.070711 0.070711 <LogVarVal> 30.219448<Mixture> 1 <Weight> 0.139037<Mean>-119.390373 -16.832819 19.765537 -2.150642 6.756366 -5.849945 4.416418 2.809105 <Inverted_Deviation>0.027897 0.013168 0.015439 0.037351 0.035009 0.049909 0.070711 0.070711 <LogVarVal> 31.594343<Mixture> 2 <Weight> 0.491979<Mean>67.445679 -8.697609 40.084557 -11.676978 0.023525 -7.867779 0.510914 1.323853 <Inverted_Deviation>0.014756 0.018779 0.019235 0.029185 0.042744 0.049894 0.066536 0.070711 <LogVarVal> 31.764666<State> 3<NumMixes> 3<Mixture> 0 <Weight> 0.329412<Mean>-131.007034 1.681211 -57.504356 4.121988 28.122553 -0.132149 12.960434 4.076024 <Inverted_Deviation>0.012016 0.012977 0.021044 0.014756 0.031071 0.049917 0.046628 0.063894 <LogVarVal> 33.707184<Mixture> 1 <Weight> 0.358824<Mean>16.625938 16.799940 4.682932 23.613672 -2.290540 7.557913 -3.112319 -8.199980 <Inverted_Deviation>0.020510 0.011215 0.021219 0.012174 0.031079 0.028879 0.033276 0.056163 <LogVarVal> 34.515877<Mixture> 2 <Weight> 0.311765<Mean>166.596619 0.482895 61.800034 4.413245 -28.290314 0.981202 -13.898478 4.249887 <Inverted_Deviation>0.011246 0.011284 0.015878 0.013644 0.030735 0.034372 0.040312 0.051504 <LogVarVal> 35.018291<State> 4<NumMixes> 3<Mixture> 0 <Weight> 0.941634<Mean>34.391529 -1.193665 0.464204 -0.863615 -0.116536 -0.789280 -0.261378 -0.272957 <Inverted_Deviation>0.050785 0.070711 0.050196 0.070711 0.070711 0.070711 0.070711 0.070711 <LogVarVal> 26.445854<Mixture> 1 <Weight> 0.031128<Mean>-91.545151 -49.904755 -40.684425 -39.325836 -10.901596 -9.738219 -4.026871 4.591399 <Inverted_Deviation>0.019245 0.070711 0.042390 0.064079 0.070711 0.070711 0.070711 0.070711 <LogVarVal> 27.683689<Mixture> 2 <Weight> 0.027237<Mean>-4.087406 -16.898485 7.170161 -8.011189 -9.495887 -4.003296 0.647717 -0.724366 <Inverted_Deviation>0.037639 0.058116 0.063505 0.070711 0.070711 0.065537 0.070711 0.070711 <LogVarVal> 26.782356<State> 5<NumMixes> 3<Mixture> 0 <Weight> 0.248175

Page 223: Bioidentià - Il Progetto Ottico

<Mean>193.838730 -0.841311 -19.025002 -1.742880 2.352849 -0.728297 -8.807205 1.636138 <Inverted_Deviation>0.016424 0.012148 0.010296 0.017934 0.026932 0.027708 0.038896 0.040834 <LogVarVal> 35.341076<Mixture> 1 <Weight> 0.613139<Mean>12.877467 3.272102 2.626410 -0.844084 -1.496272 1.243824 2.790946 0.615524 <Inverted_Deviation>0.034123 0.047279 0.047078 0.044948 0.070711 0.070711 0.070711 0.070711 <LogVarVal> 27.763226<Mixture> 2 <Weight> 0.138686<Mean>105.450005 6.511856 55.032810 4.647384 2.288129 -3.770526 1.748496 -4.205755 <Inverted_Deviation>0.024094 0.016110 0.013488 0.014875 0.029750 0.029896 0.032855 0.048521 <LogVarVal> 34.413460<TransP>-0.057778 -2.879900 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.078472 -2.583997 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.089445 -2.458520 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.098846 -2.363210 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.064279 -2.776487 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 0.000000 <EndEmbeddedHMM><BeginEmbeddedHMM><NumStates> 6<State> 0<NumMixes> 3<Mixture> 0 <Weight> 0.079399<Mean>281.515320 5.062520 23.383995 -6.769423 -1.797396 -2.218050 -1.719421 0.938018 <Inverted_Deviation>0.007033 0.005905 0.028191 0.037544 0.044815 0.068372 0.070711 0.070711 <LogVarVal> 32.605255<Mixture> 1 <Weight> 0.831545<Mean>-9.736834 -1.911342 9.898236 0.245111 1.282359 -2.437490 -0.494635 -0.159903 <Inverted_Deviation>0.016225 0.026268 0.026959 0.042149 0.070711 0.058875 0.070711 0.070711 <LogVarVal> 29.899328<Mixture> 2 <Weight> 0.089056<Mean>-234.735886 2.390812 75.920830 5.356786 -11.480034 -6.676812 9.000673 0.603900 <Inverted_Deviation>0.010240 0.011519 0.007933 0.010402 0.017930 0.036167 0.031687 0.033247 <LogVarVal> 37.223103<State> 1<NumMixes> 3<Mixture> 0 <Weight> 0.068063<Mean>73.068626 4.208974 -108.522934 34.903324 7.557928 -18.668013 -4.114515 0.012024 <Inverted_Deviation>0.006929 0.016683 0.015159 0.028884 0.037623 0.026465 0.039746 0.070711 <LogVarVal> 34.164383<Mixture> 1 <Weight> 0.518325

Page 224: Bioidentià - Il Progetto Ottico

<Mean>-38.629051 5.369726 29.472923 7.114058 -0.945012 -12.123492 3.357934 -0.145340 <Inverted_Deviation>0.009075 0.030282 0.013002 0.029454 0.065644 0.030550 0.070711 0.070711 <LogVarVal> 32.156143<Mixture> 2 <Weight> 0.413613<Mean>134.908218 0.393828 113.515602 2.343509 -4.886399 -12.961477 -4.844072 -0.264280 <Inverted_Deviation>0.007246 0.014630 0.011153 0.015511 0.031214 0.021559 0.046464 0.070711 <LogVarVal> 35.415352<State> 2<NumMixes> 3<Mixture> 0 <Weight> 0.415414<Mean>-46.442204 2.625515 -39.037647 0.741800 0.109419 20.635923 1.452390 -0.398463 <Inverted_Deviation>0.007425 0.019306 0.015365 0.019814 0.060124 0.012820 0.064612 0.070711 <LogVarVal> 34.082813<Mixture> 1 <Weight> 0.204887<Mean>-25.423428 -1.808578 216.439011 -3.891537 -3.458281 27.054890 7.209569 -0.137808 <Inverted_Deviation>0.015531 0.043220 0.010858 0.020908 0.060988 0.012498 0.039046 0.070711 <LogVarVal> 33.347191<Mixture> 2 <Weight> 0.379699<Mean>28.790150 -4.355493 -174.831299 0.902964 3.188112 -11.479298 -6.226968 0.909172 <Inverted_Deviation>0.010894 0.025712 0.012667 0.025213 0.062370 0.014423 0.047051 0.070711 <LogVarVal> 33.527699<State> 3<NumMixes> 3<Mixture> 0 <Weight> 0.304348<Mean>86.820747 5.144733 -100.133652 -20.788786 13.970844 -1.287977 -22.528519 -0.661565 <Inverted_Deviation>0.014922 0.025611 0.009903 0.013569 0.032377 0.014940 0.024406 0.039824 <LogVarVal> 35.933765<Mixture> 1 <Weight> 0.462451<Mean>-37.885178 5.131439 33.009090 -11.834466 -1.668376 11.706657 8.278119 -1.887173 <Inverted_Deviation>0.009802 0.020549 0.017517 0.012941 0.033183 0.015504 0.029852 0.047472 <LogVarVal> 35.612408<Mixture> 2 <Weight> 0.233202<Mean>-55.076748 -2.452983 151.571808 3.877711 -13.306914 -3.478388 14.378208 2.829310 <Inverted_Deviation>0.008172 0.019092 0.015081 0.013413 0.026307 0.017964 0.027104 0.051203 <LogVarVal> 36.087620<State> 4<NumMixes> 3<Mixture> 0 <Weight> 0.529158<Mean>1.878654 -0.733471 33.537338 1.262277 -0.333027 7.590052 -0.060252 -1.090263 <Inverted_Deviation>0.023968 0.055641 0.018797 0.023763 0.070711 0.017156 0.051693 0.070711 <LogVarVal> 31.238581<Mixture> 1 <Weight> 0.276458<Mean>

Page 225: Bioidentià - Il Progetto Ottico

-21.736927 -2.542204 178.507385 4.930440 -3.906276 -7.275815 7.139390 1.955986 <Inverted_Deviation>0.019527 0.070711 0.015019 0.023224 0.070711 0.014298 0.033285 0.070711 <LogVarVal> 32.073654<Mixture> 2 <Weight> 0.194384<Mean>41.534611 0.298131 -100.676323 -7.546008 7.317516 13.963810 -7.074047 1.352842 <Inverted_Deviation>0.020142 0.061396 0.014286 0.019261 0.051039 0.015684 0.029240 0.070711 <LogVarVal> 32.784084<State> 5<NumMixes> 3<Mixture> 0 <Weight> 0.293725<Mean>65.476868 -4.344866 16.173809 1.581775 2.378810 -2.788371 -1.462082 1.073274 <Inverted_Deviation>0.024989 0.019618 0.022597 0.028031 0.039386 0.055366 0.065933 0.070711 <LogVarVal> 31.060362<Mixture> 1 <Weight> 0.626168<Mean>2.023335 1.580380 11.692266 0.814330 0.784113 -1.665624 1.021921 -0.508516 <Inverted_Deviation>0.029082 0.035495 0.031096 0.042873 0.062136 0.070711 0.070711 0.070711 <LogVarVal> 28.801016<Mixture> 2 <Weight> 0.080107<Mean>194.629745 3.963917 49.733593 7.044076 -14.174562 -5.307319 -8.042933 -0.596228 <Inverted_Deviation>0.019450 0.010448 0.012431 0.018382 0.026960 0.053558 0.061205 0.059666 <LogVarVal> 33.617088<TransP>-0.043867 -3.148453 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.234994 -1.563394 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.078165 -2.587764 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.172097 -1.844510 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -0.090355 -2.448848 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 -10000000000.000000 0.000000 <EndEmbeddedHMM><BeginEmbeddedHMM><NumStates> 3<State> 0<NumMixes> 3<Mixture> 0 <Weight> 0.764505<Mean>4.214235 -0.590245 -18.314932 -2.061201 1.134269 20.565706 -0.863436 0.251514 <Inverted_Deviation>0.014439 0.022890 0.006650 0.021375 0.039824 0.013106 0.052829 0.070711 <LogVarVal> 34.600323<Mixture> 1 <Weight> 0.075085<Mean>492.951630 -30.950453 -10.584294 2.464219 5.519246 -0.124828 -0.360903 -0.114343 <Inverted_Deviation>0.015467 0.003779 0.070711 0.070711 0.070711 0.070711 0.070711 0.070711 <LogVarVal> 30.221079<Mixture> 2 <Weight> 0.160410<Mean>

Page 226: Bioidentià - Il Progetto Ottico

-135.749176 -2.787473 154.343948 -4.639666 -8.062235 3.051846 10.178977 -0.126230 <Inverted_Deviation>0.012060 0.022278 0.008706 0.009491 0.022054 0.014707 0.019911 0.030878 <LogVarVal> 37.630077<State> 1<NumMixes> 3<Mixture> 0 <Weight> 0.141401<Mean>-145.575256 -0.853109 43.739334 -3.194839 0.044414 -2.246252 4.633504 0.160951 <Inverted_Deviation>0.012365 0.014624 0.008737 0.018236 0.038915 0.030116 0.035987 0.058581 <LogVarVal> 34.852570<Mixture> 1 <Weight> 0.793631<Mean>4.161003 0.191693 24.924175 0.116371 0.253912 -0.735707 -0.397659 -0.206465 <Inverted_Deviation>0.027827 0.031615 0.034241 0.052863 0.070711 0.070711 0.070711 0.070711 <LogVarVal> 28.525803<Mixture> 2 <Weight> 0.064968<Mean>156.611725 10.981389 26.052437 4.576946 -3.795823 -1.734974 -1.815239 -0.578430 <Inverted_Deviation>0.017771 0.011419 0.028703 0.050400 0.060905 0.070711 0.070711 0.070711 <LogVarVal> 30.366079<State> 2<NumMixes> 3<Mixture> 0 <Weight> 0.084158<Mean>-18.079115 -3.193123 151.020554 -13.808769 -1.519674 5.422098 17.030935 2.441987 <Inverted_Deviation>0.021982 0.041304 0.014502 0.016757 0.042436 0.014949 0.044584 0.058525 <LogVarVal> 33.217239<Mixture> 1 <Weight> 0.193069<Mean>105.268265 1.056072 95.867630 6.613261 -8.230984 -4.027469 -9.223823 -1.890299 <Inverted_Deviation>0.016956 0.025554 0.012963 0.014080 0.029512 0.020748 0.027063 0.040854 <LogVarVal> 35.137329<Mixture> 2 <Weight> 0.722772<Mean>10.478083 2.190120 -32.570210 1.983625 2.397516 8.352318 -1.068018 0.576043 <Inverted_Deviation>0.021509 0.058677 0.011861 0.032621 0.070711 0.019348 0.070711 0.070711 <LogVarVal> 31.003817<TransP>-0.067045 -2.735734 -10000000000.000000 -10000000000.000000 -0.024502 -3.721245 -10000000000.000000 -10000000000.000000 0.000000 <EndEmbeddedHMM>

La creazione di una HMM viene eseguita dal membro della classe CContHMM.

bool CContEHMM::CreateHMM( int* num_states, int* num_mix, int vect_size ){ if (m_hmm) cvRelease2DHMM( &m_hmm ); m_hmm = 0;

m_hmm = cvCreate2DHMM( num_states, num_mix, vect_size ); m_vectSize = vect_size;

Page 227: Bioidentià - Il Progetto Ottico

return true; //else return false;}

Viene utilizzata la funzione di OpenCV :

Create2DHMM

Creates 2D embedded HMM

CvEHMM* cvCreate2DHMM( int* stateNumber, int* numMix, int obsSize );

stateNumberArray, the first element of the which specifies the number of superstates in the HMM. All subsequent elements specify the number of states in every embedded HMM, corresponding to each superstate. So, the length of the array is stateNumber [0]+1 .

numMixArray with numbers of Gaussian mixture components per each internal state. The number of elements in the array is equal to number of internal states in the HMM, that is, superstates are not counted here.

obsSizeSize of observation vectors to be used with created HMM.

Il progetto di base da cui è derivato il sistema di riconoscimento è costituito dai seguenti files.

28/09/2003 08.34 9.517 EHMM.cpp28/09/2003 08.32 899 EHMM.h28/09/2003 08.32 1.503 EHMMObj.cpp28/09/2003 08.32 597 EHMMObj.h28/09/2003 09.39 8.466 EHMMObjDatabase.cpp28/09/2003 08.32 1.631 EHMMObjDatabase.h28/09/2003 09.35 8.871 EHMMObjRecognition.cpp28/09/2003 09.27 1.638 EHMMObjRecognition.h28/09/2003 20.22 5.181 ImgObj.cpp28/09/2003 08.08 1.045 ImgObj.h28/09/2003 08.15 5.805 ImgObjDatabase.cpp28/09/2003 08.12 1.238 ImgObjDatabase.h21/04/2004 15.57 43 lista.txt27/09/2003 12.44 723 Obj.cpp27/09/2003 12.50 386 Obj.h27/09/2003 23.39 3.180 RecognizeEHMM.cpp27/09/2003 23.29 802 RecognizeEHMM.h28/09/2003 21.36 13.874 RetinaRecognition.cpp22/01/2004 10.25 117.760 RetinaRecognition.ncb24/09/2003 20.40 919 RetinaRecognition.sln28/09/2003 09.38 4.635 RetinaRecognition.vcproj27/09/2003 18.56 1.007 Utils.cpp

Page 228: Bioidentià - Il Progetto Ottico

27/09/2003 18.57 504 Utils.h

Il cuore in cui sono gestiti gli HMM è descritto nei files che possiedono EHMM nella parte iniziale.E sta per EMBEDDED.

Il primo gruppo di files contiene le funzioni adatte alla lettura e al salvataggio dei parametri visti nelle pagine precedenti.

#ifndef _EHMM_H_#define _EHMM_H_

//Disable OpenCv type cast warning#pragma warning( disable : 4312 )

#include <string>#include "cv.h"#include "ipl.h"

#pragma warning( default : 4312 )

class EHMM{public:

EHMM( );

virtual ~EHMM( );

void Create( int *noStates, int *noMix, int vecSize );

void Load( const std::string &fileName );

void Save( const std::string &fileName );

void Release( );

bool GetTrained( );

void SetTrained( bool trained );

void GetNoStates( int *noStates ) const;

void GetNoMix( int *noMix ) const;

int GetVecSize( ) const;

CvEHMM* GetCvEHMM( );

private:

//Hidden markov modelCvEHMM* _ehmm;

//Size of the vector that is used as inputint _vecSize;

//If the ehmm is trained or notbool _trained;

};

Page 229: Bioidentià - Il Progetto Ottico

#endif //_EHMM_H

#include "EHMM.h"#include <stdio.h>

//*****************************************************************************

EHMM::EHMM( ){ _ehmm = 0; _vecSize = 0;

_trained = false;}

//*****************************************************************************

EHMM::~EHMM( ){

Release( );}

//*****************************************************************************

void EHMM::Release( ){ if ( _ehmm )

{cvRelease2DHMM( &_ehmm );

}

_vecSize = 0;_trained = false;

}

//*****************************************************************************

void EHMM::Create( int *noStates, int *noMix, int vecSize ){

assert( _ehmm == 0 );

_ehmm = cvCreate2DHMM( noStates, noMix, vecSize );

assert( _ehmm != 0 ); _vecSize = vecSize;

_trained = false;}

//*****************************************************************************

void EHMM::Load( const std::string &fileName ){

const int MAX_STATES = 128;

FILE *file; int states[ MAX_STATES ]; int gaussMix[ MAX_STATES ]; char tmpChar[ MAX_STATES ];

assert( _ehmm == 0 );

Page 230: Bioidentià - Il Progetto Ottico

file = fopen( fileName.c_str( ), "rt" );

assert( file != 0 );

//Read topology fscanf( file, "%s %d\n", tmpChar, states );

fscanf( file, "%s ", tmpChar );

for( int i = 0; i < states[ 0 ]; i++ ) { fscanf( file, "%d ", states + i + 1 ); }

fscanf( file, "\n" ); //Compute total number of internal states int total_states = 0;

for( i = 0; i < states[ 0 ]; i++ ) { total_states += states[ i+1 ]; } //Read number of mixtures fscanf( file, "%s ", tmpChar );

for( i = 0; i < total_states; i++ ) { fscanf( file, "%d ", &gaussMix[ i ] ); }

fscanf( file, "\n" );

fscanf( file, "%s %d\n", tmpChar, &_vecSize );

_ehmm = cvCreate2DHMM( states, gaussMix, _vecSize );

//Create HMM with known parametersassert( _ehmm != 0 );

//Consequently read all hmms

CvEHMM* hmm = _ehmm;

for( i = 0; i < states[ 0 ]+1; i++ ) { fscanf( file, "%s\n", tmpChar );

int temp_int;

fscanf( file, "%s %d\n", tmpChar , &temp_int ); assert( temp_int == states[ i ] );

if ( i!= 0 ) { for ( int j = 0; j < states[ i ]; j++) { CvEHMMState* state = &( hmm->u.state[ j ] );

fscanf( file, "%s %d\n", tmpChar, &temp_int ); assert( temp_int == j );

Page 231: Bioidentià - Il Progetto Ottico

fscanf( file, "%s %d\n", tmpChar, &temp_int ); assert( temp_int == state->num_mix );

float* mu = state->mu;

float* inv_var = state->inv_var;

for( int m = 0; m < state->num_mix; m++) { int temp_int;

fscanf( file, "%s %d %s %f\n", tmpChar, &temp_int, tmpChar, &( state->weight[ m ]) );

assert( temp_int == m );

fscanf( file, "%s\n", tmpChar );

for ( int k = 0; k < _vecSize; k++) { fscanf( file, "%f ", mu ); mu++; } fscanf( file, "\n" );

fscanf( file, "%s\n", tmpChar ); for ( k = 0; k < _vecSize; k++) { fscanf( file, "%f ", inv_var ); inv_var++; }

fscanf( file, "\n" );

fscanf( file, "%s %f\n", tmpChar, &( state->log_var_val[ m ]) ); } } }

//Read the transition probability matrix

fscanf( file, "%s\n", tmpChar );

float* prob = hmm->transP;

for ( int j = 0; j < hmm->num_states; j++) { for ( int k = 0; k < hmm->num_states; k++) { fscanf( file, "%f ", prob ); prob++; } fscanf( file, "\n" ); }

fscanf( file, "%s\n", tmpChar );

hmm = &( _ehmm->u.ehmm[ i ] );

Page 232: Bioidentià - Il Progetto Ottico

}

fclose( file );

_trained = true;}

//*****************************************************************************

void EHMM::Save( const std::string &fileName ){

FILE* file;int i;int j;int m;int k;

assert( _ehmm != 0 );

file = fopen( fileName.c_str( ), "wt" );

assert( file != 0 );

//Write topology

fprintf( file, "%s %d\n", "<NumSuperStates>", _ehmm->num_states );

fprintf( file, "%s ", "<NumStates>" );

for( i = 0; i < _ehmm->num_states; i++ ) { fprintf( file, "%d ", _ehmm->u.ehmm[ i ].num_states ); }

fprintf( file, "\n" );

fprintf( file, "%s ", "<NumMixtures>" );

for( i = 0; i < _ehmm->num_states; i++ ) { CvEHMM* ehmm = &( _ehmm->u.ehmm[ i ] );

for( int j = 0; j < ehmm->num_states; j++ ) { fprintf( file, "%d ", ehmm->u.state[ j ].num_mix ); } } fprintf( file, "\n" );

fprintf( file, "%s %d\n", "<VecSize>", _vecSize );

//Consequently write all hmms

CvEHMM* hmm = _ehmm;

for( i = 0; i < _ehmm->num_states + 1; i++ ) { if ( hmm->level == 0 )

{ fprintf( file, "%s\n", "<BeginEmbeddedHMM>" );

} else

Page 233: Bioidentià - Il Progetto Ottico

{ fprintf( file, "%s\n", "<BeginExternalHMM>" );

}

fprintf( file, "%s %d\n", "<NumStates>", hmm->num_states );

if ( hmm->level == 0 ) { for ( j = 0; j < hmm->num_states; j++) { CvEHMMState* state = &( hmm->u.state[ j ] );

fprintf( file, "%s %d\n", "<State>", j );

fprintf( file, "%s %d\n", "<NumMixes>", state->num_mix );

float* mu = state->mu; float* inv_var = state->inv_var;

for( m = 0; m < state->num_mix; m++) { fprintf( file, "%s %d %s %f\n", "<Mixture>", m, "<Weight>", state->weight[ m ] );

fprintf( file, "%s\n", "<Mean>" );

for ( k = 0; k < _vecSize; k++) { fprintf( file, "%f ", mu[ 0 ] ); mu++; } fprintf( file, "\n" );

fprintf( file, "%s\n", "<Inverted_Deviation>" ); for ( k = 0; k < _vecSize; k++) { fprintf( file, "%f ", inv_var[ 0 ] ); inv_var++; }

fprintf( file, "\n" );

fprintf( file, "%s %f\n", "<LogVarVal>", state->log_var_val[ m ] ); } } }

//Write the transition probability matrix fprintf( file, "%s\n", "<TransP>" ); float* prob = hmm->transP;

for ( int j = 0; j < hmm->num_states; j++) { for ( int k = 0; k < hmm->num_states; k++) { fprintf( file, "%f ", *prob ); prob++; } fprintf( file, "\n" );

Page 234: Bioidentià - Il Progetto Ottico

}

if( hmm->level == 0 ){

fprintf( file, "%s\n", "<EndEmbeddedHMM>" );}

else{

fprintf( file, "%s\n", "<EndExternalHMM>" );}

hmm = &( _ehmm->u.ehmm[ i ] ); }

fclose( file );}

//*****************************************************************************

bool EHMM::GetTrained( ){

assert( _ehmm != 0 );

return _trained;}

//*****************************************************************************

void EHMM::SetTrained( bool trained ){

assert( _ehmm != 0 );

_trained = trained;}

//*****************************************************************************

/** Fill in the noStates vector with the number of states*/void EHMM::GetNoStates( int *noStates ) const{

int i;

assert( _ehmm != 0 );

noStates[ 0 ] = _ehmm->num_states;

for( i = 0; i < _ehmm->num_states; i++ ) { noStates[ i + 1 ] = _ehmm->u.ehmm[ i ].num_states; }}

//*****************************************************************************

/** Fill in the noMix vector with the number of mixtures per state*/void EHMM::GetNoMix( int *noMix ) const{

int i;

Page 235: Bioidentià - Il Progetto Ottico

int j;int c;

assert( _ehmm != 0 );

for( c = 0, i = 0; i < _ehmm->num_states; i++ ) { CvEHMM* ehmm = &( _ehmm->u.ehmm[ i ] );

for( j = 0; j < ehmm->num_states; j++ ) { noMix[ c++ ] = ehmm->u.state[ j ].num_mix; }

}}

//*****************************************************************************

int EHMM::GetVecSize( ) const{

assert( _ehmm != 0 );

return _vecSize;}

//*****************************************************************************

CvEHMM* EHMM::GetCvEHMM( ){

assert( _ehmm != 0 );

return _ehmm;}

Il secondo gruppo di files permette di creare degli oggetti relativi a dei sistemi HMM.Si tratta del riporto in formato OBJECT ORIENTED degli HMM.

/*/* Description: Implements a simple description /* of an EHMMObj that is detected using EHMM*/

#ifndef _EHMMObj_H_#define _EHMMObj_H_

#include "Obj.h"#include "EHMM.h"

class EHMMObj : public Obj{public:

EHMMObj( );

virtual ~EHMMObj( );

void Create( const std::string &userName, int *noStates, int *noMix, int vecSize );

void Load( const std::string &userName, const std::string &path );

Page 236: Bioidentià - Il Progetto Ottico

void Save( const std::string &path );

EHMM& GetEHMM( );

private:

//Hidden markov model associated to the objectEHMM _ehmm;

};

#endif //_EHMMObj_H_

#include "EHMMObj.h"

using std::string;

//Standard extension to the user filestatic const string EXTENSION = ".ehmm";

//*****************************************************************************

EHMMObj::EHMMObj( ){}

//*****************************************************************************

EHMMObj::~EHMMObj( ){}

//*****************************************************************************

void EHMMObj::Create( const string &userName, int *noStates, int *noMix, int vecSize )

{assert( _name == "" );

Obj::Create( userName );

//Create the ehmm for the object_ehmm.Create( noStates, noMix, vecSize );

}

//*****************************************************************************

void EHMMObj::Load( const string &userName, const string &path ){

const string EHMM_FILE = path + userName + EXTENSION;

assert( _name == "" );

Obj::Create( userName );

//Load the ehmm for each of the users_ehmm.Load( EHMM_FILE );

}

//****************************************************************

void EHMMObj::Save( const string &path ){

Page 237: Bioidentià - Il Progetto Ottico

const string EHMM_FILE = path + _name + EXTENSION;

assert( _name != "" );

//Save the ehmm for the object_ehmm.Save( EHMM_FILE );

}

//****************************************************************

EHMM& EHMMObj::GetEHMM( ){

return _ehmm;}

//****************************************************************

I seguenti files implementano un semplice database per la gestione del riconoscimento

/*/* Description: Implements a simple database used /* for the ehmm retina detection algorithm*/

#ifndef _EHMMObjDatabase_H_#define _EHMMObjDatabase_H_

#include "EHMMObj.h"#include <vector>#include <iostream>

//Exception specification warning#pragma warning( disable : 4290 )

class EHMMObjDatabase{private:

enum{ MAX_STATES = 128 };

public:

EHMMObjDatabase( );

virtual ~EHMMObjDatabase( );

void Create( const std::string &databaseName, int *noStates, int *noMix, int vecSize );

void Load( const std::string &databaseName, const std::string &path );

void Save( const std::string &path );

void Release( );

void LoadObj( const std::string &userName, const std::string &path );

void AddObj( const std::string &userName );

Page 238: Bioidentià - Il Progetto Ottico

void RemoveObj( size_t index );

void RemoveObj( const std::string &userName );

EHMMObj& GetObj( size_t index );

EHMMObj& GetObj( const std::string &userName ) throw( exception );

size_t GetNoObjs( ) const;

friend std::ostream& operator<<( std::ostream &os, EHMMObjDatabase &obj );

private:

void CheckEHMMConsistence( EHMMObj &ehmmObj );

//Stores all the users with their //associated propertiesstd::vector< EHMMObj* > _objs;

//Total number of states/substates in the ehmmint _numStates[ MAX_STATES ];

//Number of gaussian mixtures per stateint _numMix[ MAX_STATES - 1 ];

//Size of the input vectorint _vecSize;

//Name of the database filestd::string _databaseName;

};

std::ostream& operator<<( std::ostream &os, EHMMObjDatabase &obj );

#endif //_EHMMObjDatabase_H_

#include "EHMMObjDatabase.h"#include <fstream>#include <iostream>#include <assert.h>

using std::vector;using std::ifstream;using std::ofstream;using std::iostream;using std::ostream;using std::string;using std::cout;using std::endl;using std::cerr;

//*****************************************************************************

EHMMObjDatabase::EHMMObjDatabase( ){

_databaseName = "";memset( _numStates, 0, sizeof( _numStates ) );memset( _numMix, 0, sizeof( _numMix ) );_vecSize = 0;

Page 239: Bioidentià - Il Progetto Ottico

}

//*****************************************************************************

EHMMObjDatabase::~EHMMObjDatabase( ){

Release( );}

//*****************************************************************************

/** Create an empty data base*/void EHMMObjDatabase::Create( const string &databaseName, int *noStates,

int *noMix, int vecSize ){

int i;int totalNoInternalStates;

assert( noStates != 0 );assert( noMix != 0 );assert( vecSize != 0 );assert( databaseName != "" );

//Save the name of the database_databaseName = databaseName;

//Save the ehmm creation parameters

memcpy( _numStates, noStates, sizeof( int ) * ( noStates[ 0 ] + 1 ) );

//Count the number of internal statesfor ( totalNoInternalStates = 0, i = 1; i < noStates[ 0 ] + 1; i++ ){

totalNoInternalStates += noStates[ i ];}

memcpy( _numMix, noMix, sizeof( int ) * totalNoInternalStates );

_vecSize = vecSize;}

//*****************************************************************************

/** Load a database from disk*/void EHMMObjDatabase::Load( const string &databaseName,

const string &path ){

const string DATABASE_PATH = path + databaseName;const int MAX_LINE_WIDTH = 255;const int INITIAL_SIZE = 1000;

ifstream file( DATABASE_PATH.c_str( ) );vector< EHMMObj* >::iterator objsIt;char line[ MAX_LINE_WIDTH ];

assert( file.is_open( ) );

//Save the name of the database

Page 240: Bioidentià - Il Progetto Ottico

_databaseName = databaseName;

_objs.reserve( INITIAL_SIZE );

while ( file.getline( line, sizeof( line ) ) ){

_objs.push_back( new EHMMObj( ) );

try{

_objs[ _objs.size( ) - 1 ]->Load( line, path );}catch( ... ){

if ( _objs[ _objs.size( ) - 1 ] ){

delete _objs[ _objs.size( ) - 1 ];_objs[ _objs.size( ) - 1 ] = 0;

}

_objs.pop_back( );

cerr << "Exception occured when creating " << line << "." << endl;

}}

//Save the ehmm creation parametersif ( _objs.size( ) == 0 ){

cerr << "Database is emtpy. Please use 'Create' before ""adding new users" << endl;

}else{

_objs[ 0 ]->GetEHMM( ).GetNoStates( _numStates );_objs[ 0 ]->GetEHMM( ).GetNoMix( _numMix );_vecSize = _objs[ 0 ]->GetEHMM( ).GetVecSize( );

}

//Check to see if the db is consistentfor ( objsIt = _objs.begin( ); objsIt < _objs.end( ); objsIt++ ){

CheckEHMMConsistence( *(*objsIt) );}

}

//*****************************************************************************

/** Save the database to disk. It will overwrite the previous data*/void EHMMObjDatabase::Save( const string &path ){

const string DATABASE_PATH = path + _databaseName;

vector< EHMMObj* >::iterator objsIt;ofstream file( DATABASE_PATH.c_str( ) );

assert( _databaseName != "" );assert( file.is_open( ) );

Page 241: Bioidentià - Il Progetto Ottico

for ( objsIt = _objs.begin( ); objsIt < _objs.end( ); objsIt++ ){

file << (*objsIt)->GetName( ) << endl;(*objsIt)->Save( path );

}}

//*****************************************************************************

void EHMMObjDatabase::Release( ){

vector< EHMMObj* >::iterator objsIt;

for ( objsIt = _objs.begin( ); objsIt < _objs.end( ); objsIt++ ){

if ( *objsIt ){

delete (*objsIt);*objsIt = 0;

}}

_databaseName = "";}

//*****************************************************************************

/** Load the object from an already trained ehmm*/void EHMMObjDatabase::LoadObj( const string &userName,

const string &path ){

_objs.push_back( new EHMMObj( ) );

try{

_objs[ _objs.size( ) - 1 ]->Load( userName, path );

//Check to see if the object is a correct oneCheckEHMMConsistence( *_objs[ _objs.size( ) - 1 ] );

}catch( ... ){

if ( _objs[ _objs.size( ) - 1 ] ){

delete _objs[ _objs.size( ) - 1 ];_objs[ _objs.size( ) - 1 ] = 0;

}

_objs.pop_back( );

cerr << "Exception occured when creating " << userName << "." << endl;

}}

//*****************************************************************************

/** Add a new with not yet trained ehmm object*/

Page 242: Bioidentià - Il Progetto Ottico

void EHMMObjDatabase::AddObj( const string &userName ){

assert( _vecSize != 0 );

_objs.push_back( new EHMMObj( ) );_objs[ _objs.size( ) - 1 ]->Create( userName, _numStates, _numMix,

_vecSize );}

//*****************************************************************************

/** Remove an object from the database by index*/void EHMMObjDatabase::RemoveObj( size_t index ){

assert( _databaseName != "" );assert( index < _objs.size( ) );

_objs.erase( _objs.begin( ) + index );}

//*****************************************************************************

/** Remove the first occurance of an object from the database by name*/void EHMMObjDatabase::RemoveObj( const string &userName ){

const string EXCEPTION_STR = "EHMMObjDatabase::RemoveObj: " + userName + " not found.";

vector< EHMMObj* >::iterator objsIt;

assert( _databaseName != "" );

for ( objsIt = _objs.begin( ); objsIt < _objs.end( ); objsIt++ ){

if ( (*objsIt)->GetName( ) == userName ){

_objs.erase( objsIt );

return;}

}

throw exception( EXCEPTION_STR.c_str( ) );}

//*****************************************************************************

EHMMObj& EHMMObjDatabase::GetObj( size_t index ){

assert( _databaseName != "" );assert( index < _objs.size( ) );

return *_objs[ index ];}

//*****************************************************************************

/*

Page 243: Bioidentià - Il Progetto Ottico

* If more than one object has the same name the first object is returned*/EHMMObj& EHMMObjDatabase::GetObj( const string &userName ){

const string EXCEPTION_STR = "EHMMObjDatabase::GetObj: " + userName + " not found.";

vector< EHMMObj* >::iterator objsIt;

assert( _databaseName != "" );

for ( objsIt = _objs.begin( ); objsIt < _objs.end( ); objsIt++ ){

if ( (*objsIt)->GetName( ) == userName ){

return *(*objsIt);}

}

throw exception( EXCEPTION_STR.c_str( ) );}

//*****************************************************************************

size_t EHMMObjDatabase::GetNoObjs( ) const{

assert( _databaseName != "" );

return _objs.size( );}

//*****************************************************************************

/** Check that the new loaded object has the same parameters * for his ehmm as the database*/void EHMMObjDatabase::CheckEHMMConsistence( EHMMObj &ehmmObj ){

const string ERROR = "Database '" + _databaseName + "' is not consistent. Terminating application.";

int noStates[ MAX_STATES ];int noMix[ MAX_STATES - 1 ];int totalNoInternalStates;int i;

assert( _databaseName != "" );

ehmmObj.GetEHMM( ).GetNoStates( noStates );ehmmObj.GetEHMM( ).GetNoMix( noMix );

//Count the number of internal statesfor ( totalNoInternalStates = 0, i = 1; i < noStates[ 0 ] + 1; i++ ){

totalNoInternalStates += noStates[ i ];}

//Check vector size, states and mixturesif ( ehmmObj.GetEHMM( ).GetVecSize( ) != _vecSize

|| memcmp( noStates, _numStates, _numStates[ 0 ] + 1 )|| memcmp( noMix, _numMix, totalNoInternalStates ) )

{

Page 244: Bioidentià - Il Progetto Ottico

cerr << ERROR;abort( );

}}

//*****************************************************************************

ostream& operator<<( ostream &os, EHMMObjDatabase &obj ){

vector< EHMMObj* >::iterator objsIt;int c;

assert( obj._databaseName != "" );

os << "Database of ehmms '" << obj._databaseName << "' contains..." << endl;

for ( c = 1, objsIt = obj._objs.begin( ); objsIt < obj._objs.end( ); objsIt++, c++ )

{os << c << ")" << " " << (*objsIt)->GetName( ) << endl;

}

return os;}

//*****************************************************************************

I seguenti files invece costituiscono il cuore degli HMM in quanto nel codice è implementato il training e il riconoscimento.

/*/* Description: Implements the training/recogniton with embedded /* hidden markov model suing A. Nefian's algorithm*/

#ifndef _EHMMObjRecognition_H_#define _EHMMObjRecognition_H_

//Forward declarationsclass EHMMObj;class ImgObj;class EHMMObjDatabase;class ImgObjDatabase;

//Disable OpenCv type cast warning#pragma warning( disable : 4312 )

#include <vector>#include "cv.h"#include "ipl.h"

#pragma warning( default : 4312 )

class EHMMObjRecognition{public:

EHMMObjRecognition( );

virtual ~EHMMObjRecognition( );

Page 245: Bioidentià - Il Progetto Ottico

void Create( int imgWidth, int imgHeight, int obsWidth, int obsHeight, int noDCTCoeffX,

int noDCTCoeffY, int stepX, int stepY, bool suppressIntensity = false );

void Release( );

void Train( ImgObj &imgObj, EHMMObj &ehmmObj );

void Train( ImgObjDatabase &imgObjDb, EHMMObjDatabase &ehmmObjDb );

float ComputeLikelihood( IplImage &img, EHMMObj &ehmmObj );

size_t ComputeLikelihood( IplImage &img, EHMMObjDatabase &ehmmObjDb, std::vector< float > &likelihood );

private:

void CountObs( IplROI &roi, CvSize &winSize, CvSize &stepSize, CvSize &noObs );

void ExtractDCT( float* src, float* dst, int num_vec, int dst_len );

//Controls the size of the observation vectors (the DCT window size)CvSize _dctSize;

//Step of the DCT through the input imageCvSize _stepSize;

//Number of DCT coefficients to useCvSize _noDCTCoeff;

//Controls how the image is resizesint _imgWidth;int _imgHeight;

//Keep or not the first DCT coefficientbool _suppressIntensity;

};

#endif //_EHMMObjRecognition_H_

#include "EHMMObjRecognition.h"#include "EHMMObj.h"#include "ImgObj.h"#include "ImgObjDatabase.h"#include "EHMMObjDatabase.h"#include "Utils.h"#include <iostream>#include <cv.h>#include <vector>#include <math.h>#include <float.h>

using std::cerr;using std::endl;using std::vector;

//*****************************************************************************

EHMMObjRecognition::EHMMObjRecognition( ){

Page 246: Bioidentià - Il Progetto Ottico

Release( );}

//*****************************************************************************

EHMMObjRecognition::~EHMMObjRecognition( ){}

//*****************************************************************************

void EHMMObjRecognition::Create( int imgWidth, int imgHeight, int obsWidth, int obsHeight, int noDCTCoeffX,

int noDCTCoeffY, int stepX, int stepY, bool

suppressIntensity ){

assert( _imgWidth == -1 );assert( _imgHeight == -1 );

_dctSize = cvSize( obsWidth, obsHeight );

_stepSize = cvSize( stepX, stepY );

_noDCTCoeff = cvSize( noDCTCoeffX, noDCTCoeffY );

//They are used only for training_imgWidth = imgWidth;_imgHeight = imgHeight;

_suppressIntensity = suppressIntensity;}

//*****************************************************************************

void EHMMObjRecognition::Release( ){

assert( _imgWidth != -1 );assert( _imgHeight != -1 );

_imgWidth = _imgHeight = -1;}

//*****************************************************************************

/** Train the CvEHMM using A. Nefian's algorithm (See OpenCV documentation)*/void EHMMObjRecognition::Train( ImgObj &imgObj, EHMMObj &ehmmObj ){

const int MAX_ITER = 80; const double STOP_STEP_ITER = 0.01;

CvImgObsInfo **obsInfoVec;IplImage *iplImg;int obsVecLen = _noDCTCoeff.width * _noDCTCoeff.height;CvSize _noObs;CvEHMM *tmplEhmm = ehmmObj.GetEHMM( ).GetCvEHMM( );int numImages = (int)imgObj.GetNoImages( );

bool trained = false; float oldLikelihood = 0; int counter = 0;

Page 247: Bioidentià - Il Progetto Ottico

int i;

assert( _imgWidth != -1 );assert( _imgHeight != -1 );

if( _suppressIntensity ) {

//Suppress first DCT coefficientobsVecLen--;

}

//Create the obsinfo array obsInfoVec = new CvImgObsInfo*[ numImages ];

assert( obsInfoVec != 0 );

for( i = 0; i < numImages; i++ ) {

iplImg = imgObj.GetGrayScaleImage( i, _imgWidth, _imgHeight );

//Get how many DCT transforms we computeCountObs( *iplImg->roi, _dctSize, _stepSize, _noObs );

//Create the observation for each of the transforms

obsInfoVec[ i ] = cvCreateObsInfo( _noObs, obsVecLen );

if( _suppressIntensity ) { float *observations = new float[ _noObs.height * _noObs.width * ( obsVecLen + 1 ) ];

cvImgToObs_DCT( iplImg, observations, _dctSize, _noDCTCoeff, _stepSize );

ExtractDCT( observations, obsInfoVec[ i ]->obs, _noObs.height * _noObs.width, obsVecLen );

if ( observations ){

delete( observations);}

} else { cvImgToObs_DCT( iplImg, obsInfoVec[ i ]->obs, _dctSize, _noDCTCoeff, _stepSize ); }

cvUniformImgSegm( obsInfoVec[ i ], tmplEhmm );

cvReleaseImage( &iplImg ); }

cvInitMixSegm( obsInfoVec, numImages, tmplEhmm );

//Start the iterative training procedurewhile( ( !trained ) && ( counter < MAX_ITER ) )

{ int j; float likelihood = 0;

counter++;

Page 248: Bioidentià - Il Progetto Ottico

cvEstimateHMMStateParams( obsInfoVec, numImages, tmplEhmm );

cvEstimateTransProb( obsInfoVec, numImages, tmplEhmm); for( j = 0; j < numImages; j++ ) { cvEstimateObsProb( obsInfoVec[ j ], tmplEhmm );

likelihood += cvEViterbi( obsInfoVec[ j ], tmplEhmm ); }

likelihood /= numImages * obsInfoVec[ 0 ]->obs_size;

cvMixSegmL2( &obsInfoVec[ 0 ], numImages, tmplEhmm );

trained = ( fabs( likelihood - oldLikelihood ) < STOP_STEP_ITER );

oldLikelihood = likelihood; }

//Clear the observationsfor( i = 0; i < numImages; i++ ){

cvReleaseObsInfo( &(obsInfoVec[ i ]) );}delete []obsInfoVec;

ehmmObj.GetEHMM( ).SetTrained( trained );

}

//*****************************************************************************

/** Apply the training algorithm on two databases of images and ehmms.* Train only for the users that appear in the ImgObjDatabase*/void EHMMObjRecognition::Train( ImgObjDatabase &imgObjDb, EHMMObjDatabase &ehmmObjDb ){

size_t i;EHMMObj *tmpEHMMObj;ImgObj *tmpImgObj;

//Train for every object in imgObjDbfor ( i = 0; i < imgObjDb.GetNoObjs( ); i++ ){

try{

tmpImgObj = &imgObjDb.GetObj( i );

tmpEHMMObj = &ehmmObjDb.GetObj( tmpImgObj->GetName( ) );

Train( *tmpImgObj, *tmpEHMMObj );}catch( exception &e ){

cerr << e.what( ) << endl;}catch( ... ){

abort( );}

Page 249: Bioidentià - Il Progetto Ottico

}

//Check that all users are trainedfor ( i = 0; i < ehmmObjDb.GetNoObjs( ); i++ ){

if ( !ehmmObjDb.GetObj( i ).GetEHMM( ).GetTrained( ) ){

cerr << "Warning: Obj " << ehmmObjDb.GetObj( i ).GetName( ) << " is not trained." << endl;

}}

}

//*****************************************************************************

/** Recognize with ehmm using A. Nefian's algorithm (See OpenCV documentation)* This function returns the match likelihood*/float EHMMObjRecognition::ComputeLikelihood( IplImage &img, EHMMObj &ehmmObj ){

CvSize _noObs;

CvEHMM *tmplEhmm = ehmmObj.GetEHMM( ).GetCvEHMM( );int obsVecLen = _noDCTCoeff.width * _noDCTCoeff.height;

CvImgObsInfo* info; if( _suppressIntensity ) { obsVecLen--; }

//Get how many DCT transforms we computeCountObs( *img.roi, _dctSize, _stepSize, _noObs );

info = cvCreateObsInfo( _noObs, obsVecLen );assert( info != 0 );

if( _suppressIntensity ) { float *observations = new float[ _noObs.height * _noObs.width * ( obsVecLen + 1 ) ];

cvImgToObs_DCT( &img, observations, _dctSize, _noDCTCoeff, _stepSize );

ExtractDCT( observations, info->obs, _noObs.height * _noObs.width, obsVecLen );

if ( observations ){

delete( observations);}

} else { cvImgToObs_DCT( &img, info->obs, _dctSize, _noDCTCoeff, _stepSize ); }

cvEstimateObsProb( info, tmplEhmm );

return cvEViterbi( info, tmplEhmm );

Page 250: Bioidentià - Il Progetto Ottico

}

//*****************************************************************************

/** Apply the recognition algorithm on a database of ehmms. Returns all the * likelihoods for all the ehmms in teh database and the index of the best match*/size_t EHMMObjRecognition::ComputeLikelihood( IplImage &img, EHMMObjDatabase &ehmmObjDb,

vector< float > &likelihood ){

size_t i;EHMMObj *tmpEHMMObj;size_t maxLikelihoodPos = -1;float maxLikelihood = -FLT_MAX;

//Train for every object in imgObjDbfor ( i = 0; i < ehmmObjDb.GetNoObjs( ); i++ ){

try{

tmpEHMMObj = &ehmmObjDb.GetObj( i );

if ( tmpEHMMObj->GetEHMM( ).GetTrained( ) ){

likelihood.push_back( ComputeLikelihood( img, *tmpEHMMObj ) );

if ( likelihood[ likelihood.size( ) - 1 ] > maxLikelihood )

{maxLikelihood = likelihood[ likelihood.size( ) - 1

];maxLikelihoodPos = i;

}}

}catch( exception &e ){

cerr << e.what( ) << endl;}catch( ... ){

abort( );}

}

return maxLikelihoodPos;}

//*****************************************************************************

void EHMMObjRecognition::CountObs( IplROI &roi, CvSize &winSize, CvSize &_stepSize,

CvSize &_noObs ) {

_noObs.width = ( roi.width - winSize.width + _stepSize.width ) / _stepSize.width;

_noObs.height = ( roi.height - winSize.height + _stepSize.height ) /

Page 251: Bioidentià - Il Progetto Ottico

_stepSize.height;}

//*****************************************************************************

/** Used to suppress the first DCT coefficient*/void EHMMObjRecognition::ExtractDCT( float* src, float* dst, int numVec, int dstLen ){ float *tmpSrc = src + 1; float *tmpDst = dst;

int i;

for( i = 0; i < numVec; i++ ) { memcpy( tmpDst, tmpSrc, dstLen * sizeof( float ) ); tmpSrc += dstLen + 1; tmpDst += dstLen; }}

//*****************************************************************************

/*/* Description: Implements the recognition using embedded /* hidden markov model for face recognition*/

#ifndef _RecognizeEHMM_H_#define _RecognizeEHMM_H_

//Disable OpenCv type cast warning#pragma warning( disable : 4312 )

#include <ipl.h>#include <cv.h>

#pragma warning( default : 4312 )

//Forward declarationsclass EHMMObj;class EHMMObjDatabase;

float RecognizeEHMM( IplImage &img, EHMMObj &ehmmObj, int obsWidth, int obsHeight,

int noDCTCoeffX, int noDCTCoeffY, int stepX, int stepY,

bool suppressIntensity = false );

size_t RecognizeEHMM( IplImage &img, EHMMObjDatabase &ehmmObjDb, int obsWidth, int obsHeight,

int noDCTCoeffX, int noDCTCoeffY, int stepX, int stepY,

bool suppressIntensity = false );

#endif //_RecognizeEHMM_H_

#include "EHMMObj.h"#include "EHMMObjDatabase.h"#include "Utils.h"

Page 252: Bioidentià - Il Progetto Ottico

#include "RecognizeEHMM.h"#include <vector>#include <iostream>#include <float.h>

using std::cerr;using std::endl;using std::vector;

//*****************************************************************************

/** Recognize with ehmm using A. Nefian's algorithm (See OpenCV documentation)* This function returns the match likelihood*/float RecognizeEHMM( IplImage &img, EHMMObj &ehmmObj, int obsWidth, int obsHeight,

int noDCTCoeffX, int noDCTCoeffY, int stepX, int stepY,

bool suppressIntensity ){

CvSize noObs;CvSize dctSize = cvSize( obsWidth, obsHeight );CvSize stepSize = cvSize( stepX, stepY );CvSize obsSize = cvSize( noDCTCoeffX, noDCTCoeffY );CvEHMM *tmplEhmm = ehmmObj.GetEHMM( ).GetCvEHMM( );int obsVecLen = noDCTCoeffX * noDCTCoeffY;

CvImgObsInfo* info; if( suppressIntensity ) { obsVecLen--; }

//Get how many DCT transforms we computeCountObs( *img.roi, dctSize.width, dctSize.height, stepSize.width,

stepSize.height, noObs.width, noObs.height );

info = cvCreateObsInfo( noObs, obsVecLen );assert( info != 0 );

if( suppressIntensity ) { float *observations = new float[ noObs.height * noObs.width * ( obsVecLen + 1 ) ];

cvImgToObs_DCT( &img, observations, dctSize, obsSize, stepSize );

ExtractDCT( observations, info->obs, noObs.height * noObs.width, obsVecLen );

if ( observations ){

delete( observations);}

} else { cvImgToObs_DCT( &img, info->obs, dctSize, obsSize, stepSize ); }

Page 253: Bioidentià - Il Progetto Ottico

cvEstimateObsProb( info, tmplEhmm );

return cvEViterbi( info, tmplEhmm );}

//*****************************************************************************

/** Apply the recognition algorithm on a database of ehmms*/size_t RecognizeEHMM( IplImage &img, EHMMObjDatabase &ehmmObjDb, int obsWidth,

int obsHeight, int noDCTCoeffX, int noDCTCoeffY, int stepX,

int stepY, bool suppressIntensity ){

size_t i;EHMMObj *tmpEHMMObj;vector< float > likelihood;size_t maxLikelihoodPos = -1;float maxLikelihood = -FLT_MAX;

//JUST FOR DEBUGcerr << "Probability scores are" << endl;

//Train for every object in imgObjDbfor ( i = 0; i < ehmmObjDb.GetNoObjs( ); i++ ){

try{

tmpEHMMObj = &ehmmObjDb.GetObj( i );

if ( tmpEHMMObj->GetEHMM( ).GetTrained( ) ){

likelihood.push_back( RecognizeEHMM( img, *tmpEHMMObj, obsWidth, obsHeight,

noDCTCoeffX, noDCTCoeffY, stepX, stepY, suppressIntensity ) );

if ( likelihood[ likelihood.size( ) - 1 ] > maxLikelihood )

{maxLikelihood = likelihood[ likelihood.size( ) - 1

];maxLikelihoodPos = i;

}

//JUST FOR DEBUGcerr << likelihood[ i ] << " ";

}}catch( exception &e ){

cerr << e.what( ) << endl;}catch( ... ){

abort( );}

}

//JUST FOR DEBUGcerr << endl;

Page 254: Bioidentià - Il Progetto Ottico

return maxLikelihoodPos;}

La gestione delle immagini invece viene eseguita da una classe appositamente scritta.

/*/* Description: Implements a simple description of an ImgObj /* that stores all the available images for that object*/

#ifndef _ImgObj_H_#define _ImgObj_H_

#include "Obj.h"#include "EHMM.h"#include <vector>#include <string>#include <ostream>#include <ipl.h>#include <cv.h>

class ImgObj : public Obj{public:

ImgObj( );

virtual ~ImgObj( );

void Create( const std::string &userName );

void Load( const std::string &userName, const std::string &path );

void Save( const std::string &path );

void Release( );

void AddImage( const std::string &imagePath );

IplImage* GetGrayScaleImage( size_t index, int imgWidth = 0, int imgHeight = 0,

bool showImage = false );

size_t GetNoImages( );

friend std::ostream& operator<<( std::ostream &os, ImgObj &obj );

private:

//Stores the paths to the imagesstd::vector< std::string > _imagePaths;

int _imgWidth;int _imgHeight;

};

Page 255: Bioidentià - Il Progetto Ottico

std::ostream& operator<<( std::ostream &os, ImgObj &obj );

#endif //_ImgObj_H_

#include "ImgObj.h"#include <fstream>#include <iostream>#include <assert.h>#include <highgui.h>

using std::string;using std::vector;using std::ifstream;using std::ofstream;using std::endl;using std::ostream;

using std::cout;

//Standard extension to the user filestatic const string EXTENSION = ".imobj";

//*****************************************************************************

ImgObj::ImgObj( ){}

//*****************************************************************************

ImgObj::~ImgObj( ){}

//*****************************************************************************

void ImgObj::Create( const string &userName ){

assert( _name == "" );

Obj::Create( userName );}

//*****************************************************************************

void ImgObj::Load( const string &userName, const string &path ){

const int INITIAL_SIZE = 1000;const int MAX_LINE_WIDTH = _MAX_PATH;const string IMGUSER_FILE = path + userName + EXTENSION;

char line[ MAX_LINE_WIDTH ];ifstream file( IMGUSER_FILE.c_str( ) );

assert( _name == "" );assert( file.is_open( ) );

Obj::Create( userName );

_imagePaths.reserve( INITIAL_SIZE );

while ( file.getline( line, sizeof( line ) ) )

Page 256: Bioidentià - Il Progetto Ottico

{_imagePaths.push_back( line );

}}

//*****************************************************************************

void ImgObj::Save( const string &path ){

const string IMGUSER_FILE = path + _name + EXTENSION;

vector< string >::iterator imIt;ofstream file( IMGUSER_FILE.c_str( ) );

assert( _name != "" );assert( file.is_open( ) );

for ( imIt = _imagePaths.begin( ); imIt < _imagePaths.end( ); imIt++ ){

file << (*imIt) << endl;}

}

//*****************************************************************************

void ImgObj::Release( ){

vector< string >::iterator imIt;

assert( _name != "" );

for ( imIt = _imagePaths.begin( ); imIt < _imagePaths.end( ); imIt++ ){

(*imIt) = "";}

_name = "";}

//*****************************************************************************

void ImgObj::AddImage( const string &imagePath ){

assert( _name != "" );

_imagePaths.push_back( imagePath );}

//*****************************************************************************

/** Load the image from the disk. Convert it to gray scale * because it is always loaded as a color image.* The IplImage will be returned by GetImage with * this dimensions no matter the dimensions * of image stored on disk. If one of the dimensions* is 0 then only the other dimension is used. If both* are 0 the image will not be rescaled*/IplImage* ImgObj::GetGrayScaleImage( size_t index, int imgWidth, int imgHeight,

bool showImage ){

Page 257: Bioidentià - Il Progetto Ottico

IplImage *imgDb;IplImage *imgHdd;IplImage *imgGray;

assert( _name != "" );

imgHdd = cvLoadImage( _imagePaths[ index ].c_str( ), 0 );assert( imgHdd != 0 );

imgGray = cvCreateImage( cvSize( imgHdd->width, imgHdd->height ), IPL_DEPTH_8U, 1 );

assert( imgGray != 0 );

//Resize the output image to the requested sizeif ( imgWidth && imgHeight ){

imgDb = cvCreateImage( cvSize( imgWidth, imgHeight ), IPL_DEPTH_8U, 1 );

}elseif ( imgHeight ){

imgDb = cvCreateImage( cvSize( imgHdd->width * imgHeight / imgHdd->height, imgHeight ),

IPL_DEPTH_8U, 1 );}if ( imgWidth ){

imgDb = cvCreateImage( cvSize( imgWidth, imgHdd->height * imgWidth / imgHdd->width ),

IPL_DEPTH_8U, 1 );}else{

imgDb = cvCreateImage( cvSize( imgHdd->width, imgHdd->height ), IPL_DEPTH_8U, 1 );

}assert( imgDb != 0 );

//Check that the image is already grayscaleif ( imgHdd->nChannels > 1 ){

//Make sure the output is gray scaleiplColorToGray( imgHdd, imgGray );

//Resize to the desired dimensioniplResizeFit( imgGray, imgDb, IPL_INTER_NN );

}else{

//Resize to the desired dimensioniplResizeFit( imgHdd, imgDb, IPL_INTER_NN );

}

//Set a roi to the full imagecvSetImageROI( imgDb, cvRect( 0, 0, imgDb->width, imgDb->height ) );

if ( showImage ){

cvNamedWindow( _imagePaths[ index ].c_str( ), 0 );cvShowImage( _imagePaths[ index ].c_str( ), imgDb );cvWaitKey( 0 );

Page 258: Bioidentià - Il Progetto Ottico

cvDestroyWindow( _imagePaths[ index ].c_str( ) );}

//Delete all the temp imagescvReleaseImage( &imgHdd );cvReleaseImage( &imgGray );

return imgDb;}

//*****************************************************************************

size_t ImgObj::GetNoImages( ){

assert( _name != "" );

return _imagePaths.size( );}

//*****************************************************************************

ostream& operator<<( ostream &os, ImgObj &obj ){

vector< string >::iterator imIt;int c;

assert( obj._name != "" );

os << "Obj '" << obj._name << "' contains..." << endl << endl;

for ( c = 1, imIt = obj._imagePaths.begin( ); imIt < obj._imagePaths.end( );

imIt++, c++ ){

os << c << ")" << " " << (*imIt) << endl;}

return os;}

//*****************************************************************************

L’ultima classe invece gestisce il database delle immagini.

/*/* Description: Implements a simple database of imgusers */

#ifndef _ImgObjDatabase_H_#define _ImgObjDatabase_H_

#include "ImgObj.h"#include <vector>#include <iostream>

//Exception specification warning#pragma warning( disable : 4290 )

class ImgObjDatabase{public:

Page 259: Bioidentià - Il Progetto Ottico

ImgObjDatabase( );

virtual ~ImgObjDatabase( );

void Create( const std::string &databaseName );

void Load( const std::string &databaseName, const std::string &path );

void Save( const std::string &path );

void Release( );

void LoadObj( const std::string &userName, const std::string &path );

void AddObj( const std::string &userName );

void RemoveObj( size_t index );

void RemoveObj( const std::string &userName );

ImgObj& GetObj( size_t index );

ImgObj& GetObj( const std::string &userName ) throw( exception );

size_t GetNoObjs( ) const;

friend std::ostream& operator<<( std::ostream &os, ImgObjDatabase &obj );

private:

//Stores all the users with their //associated propertiesstd::vector< ImgObj* > _objs;

//Name of the database filestd::string _databaseName;

};

std::ostream& operator<<( std::ostream &os, ImgObjDatabase &obj );

#endif //_ImgObjDatabase_H_

#include "ImgObjDatabase.h"#include <fstream>#include <iostream>#include <assert.h>

using std::vector;using std::ifstream;using std::ofstream;using std::iostream;using std::ostream;using std::string;using std::cout;using std::endl;using std::cerr;

//*****************************************************************************

ImgObjDatabase::ImgObjDatabase( ){

Page 260: Bioidentià - Il Progetto Ottico

_databaseName = "";}

//*****************************************************************************

ImgObjDatabase::~ImgObjDatabase( ){

Release( );}

//*****************************************************************************

void ImgObjDatabase::Create( const string &databaseName ){

assert( _databaseName == "" );

_databaseName = databaseName;}

//*****************************************************************************

/** Load a database from disk*/void ImgObjDatabase::Load( const string &databaseName, const string &path ){

const string DATABASE_PATH = path + databaseName;const int MAX_LINE_WIDTH = 255;const int INITIAL_SIZE = 1000;

ifstream file( DATABASE_PATH.c_str( ) );char line[ MAX_LINE_WIDTH ];

assert( file.is_open( ) );

_objs.reserve( INITIAL_SIZE );

while ( file.getline( line, sizeof( line ) ) ){

//Create a new object_objs.push_back( new ImgObj( ) );

try{

//Create the corresponding object and load ehmm_objs[ _objs.size( ) - 1 ]->Load( line, path );

}catch( ... ){

if ( _objs[ _objs.size( ) - 1 ] ){

delete _objs[ _objs.size( ) - 1 ];_objs[ _objs.size( ) - 1 ] = 0;

}

_objs.pop_back( );

cerr << "Exception occured when creating " << line << "." << endl;

}}

Page 261: Bioidentià - Il Progetto Ottico

//Save the name of the database_databaseName = databaseName;

}

//*****************************************************************************

/** Save the database to disk. It will overwrite the previous data*/void ImgObjDatabase::Save( const string &path ){

const string DATABASE_PATH = path + _databaseName;

vector< ImgObj* >::iterator usersIt;ofstream file( DATABASE_PATH.c_str( ) );

assert( _databaseName != "" );assert( file.is_open( ) );

for ( usersIt = _objs.begin( ); usersIt < _objs.end( ); usersIt++ ){

file << (*usersIt)->GetName( ) << endl;(*usersIt)->Save( path );

}}

//*****************************************************************************

void ImgObjDatabase::Release( ){

vector< ImgObj* >::iterator usersIt;

assert( _databaseName != "" );

for ( usersIt = _objs.begin( ); usersIt < _objs.end( ); usersIt++ ){

delete (*usersIt);*usersIt = 0;

}

_databaseName = "";}

//*****************************************************************************

/** Load the object*/void ImgObjDatabase::LoadObj( const string &userName, const string &path ){

_objs.push_back( new ImgObj( ) );_objs[ _objs.size( ) - 1 ]->Load( userName, path );

}

//*****************************************************************************

/** Add a new object to the database*/void ImgObjDatabase::AddObj( const string &userName ){

_objs.push_back( new ImgObj( ) );

Page 262: Bioidentià - Il Progetto Ottico

_objs[ _objs.size( ) - 1 ]->Create( userName );}

//*****************************************************************************

/** Remove an object from the database by index*/void ImgObjDatabase::RemoveObj( size_t index ){

assert( _databaseName != "" );assert( index < _objs.size( ) );

_objs.erase( _objs.begin( ) + index );}

//*****************************************************************************

/** Remove the first occurance of an object from the database by name*/void ImgObjDatabase::RemoveObj( const string &userName ){

const string EXCEPTION_STR = "ImgObjDatabase::RemoveObj: " + userName + " not found.";

vector< ImgObj* >::iterator usersIt;

assert( _databaseName != "" );

for ( usersIt = _objs.begin( ); usersIt < _objs.end( ); usersIt++ ){

if ( (*usersIt)->GetName( ) == userName ){

_objs.erase( usersIt );

return;}

}

throw exception( EXCEPTION_STR.c_str( ) );}

//*****************************************************************************

ImgObj& ImgObjDatabase::GetObj( size_t index ){

assert( _databaseName != "" );assert( index < _objs.size( ) );

return *_objs[ index ];}

//*****************************************************************************

/** If more than one object has the same name the first object is returned*/ImgObj& ImgObjDatabase::GetObj( const string &userName ){

const string EXCEPTION_STR = "ImgObjDatabase::GetObj: " + userName + " not found.";

Page 263: Bioidentià - Il Progetto Ottico

vector< ImgObj* >::iterator usersIt;

assert( _databaseName != "" );

for ( usersIt = _objs.begin( ); usersIt < _objs.end( ); usersIt++ ){

if ( (*usersIt)->GetName( ) == userName ){

return *(*usersIt);}

}

throw exception( EXCEPTION_STR.c_str( ) );}

//*****************************************************************************

size_t ImgObjDatabase::GetNoObjs( ) const{

assert( _databaseName != "" );

return _objs.size( );}

//*****************************************************************************

ostream& operator<<( ostream &os, ImgObjDatabase &obj ){

vector< ImgObj* >::iterator usersIt;int c;

assert( obj._databaseName != "" );

os << "Database of images '" << obj._databaseName << "' contains..." << endl;

for ( c = 1, usersIt = obj._objs.begin( ); usersIt < obj._objs.end( ); usersIt++, c++ )

{os << c << ")" << " " << (*usersIt)->GetName( ) << endl;

}

return os;}

La gestione delle descrizioni viene trattata da :

/*/* Description: Implements a simple description of an object*/

#ifndef _Obj_H_#define _Obj_H_

#include <string>#include <vector>

class Obj{

Page 264: Bioidentià - Il Progetto Ottico

public:

Obj( );

virtual ~Obj( );

void Create( const std::string &userName );

const std::string& GetName( ) const;

protected:

//Stores the name of the objectstd::string _name;

};

#endif //_Obj_H_

#include "Obj.h"#include <assert.h>

using std::string;

//*****************************************************************************

Obj::Obj( ) : _name(""){}

//*****************************************************************************

Obj::~Obj( ){}

//*****************************************************************************

void Obj::Create( const string &userName ){

assert( userName != "" );

_name = userName;}

//*****************************************************************************

const string& Obj::GetName( ) const{

assert( _name != "" );

return _name;}

//*****************************************************************************

Le funzioni legate alla gestione delle HMM di Open CV sono utilizzate in questo modo nelle due parti fondamentali del programma.Queste due sono precisamente :

Page 265: Bioidentià - Il Progetto Ottico

il trainingil riconoscimento

Tutte le funzioni usate sono le seguenti :

Embedded Hidden Markov Models Functions

In order to support embedded models the user must define structures to represent 1D HMM and 2D embedded HMM model. CvHMM

Embedded HMM Structure

typedef struct _CvEHMM { int level; int num_states; float* transP; float** obsProb; union { CvEHMMState* state; struct _CvEHMM* ehmm; } u; } CvEHMM;

LevelLevel of embedded HMM. If level ==0, HMM is most external. In 2D HMM there are two types of HMM: 1 external and several embedded. External HMM has level ==1, embedded HMMs have level ==0 .

num_statesNumber of states in 1D HMM.

transPState-to-state transition probability, square matrix (num_state×num_state ).

obsProbObservation probability matrix.

stateArray of HMM states. For the last-level HMM, that is, an HMM without embedded HMMs, HMM states are real.

ehmmArray of embedded HMMs. If HMM is not last-level, then HMM states are not real and they are HMMs.

For representation of observations the following structure is defined:CvImgObsInfo

Image Observation Structure

Page 266: Bioidentià - Il Progetto Ottico

typedef struct CvImgObsInfo { int obs_x; int obs_y; int obs_size; float** obs; int* state; int* mix; } CvImgObsInfo;

obs_xNumber of observations in the horizontal direction.

obs_yNumber of observations in the vertical direction.

obs_sizeLength of every observation vector.

obsPointer to observation vectors stored consequently. Number of vectors is obs_x*obs_y .

stateArray of indices of states, assigned to every observation vector.

mixIndex of mixture component, corresponding to the observation vector within an assigned state.

Create2DHMM

Creates 2D embedded HMM

CvEHMM* cvCreate2DHMM( int* stateNumber, int* numMix, int obsSize );

stateNumberArray, the first element of the which specifies the number of superstates in the HMM. All subsequent elements specify the number of states in every embedded HMM, corresponding to each superstate. So, the length of the array is stateNumber [0]+1 .

numMixArray with numbers of Gaussian mixture components per each internal state. The number of elements in the array is equal to number of internal states in the HMM, that is, superstates are not counted here.

obsSizeSize of observation vectors to be used with created HMM.

The function cvCreate2DHMM returns the created structure of the type CvEHMM with specified parameters.

Release2DHMM

Page 267: Bioidentià - Il Progetto Ottico

Releases 2D embedded HMM

void cvRelease2DHMM(CvEHMM** hmm );

hmmAddress of pointer to HMM to be released.

The function cvRelease2DHMM frees all the memory used by HMM and clears the pointer to HMM. CreateObsInfo

Creates structure to store image observation vectors

CvImgObsInfo* cvCreateObsInfo( CvSize numObs, int obsSize );

numObsNumbers of observations in the horizontal and vertical directions. For the given image and scheme of extracting observations the parameter can be computed via the macro CV_COUNT_OBS( roi, dctSize, delta, numObs ), where roi, dctSize, delta, numObs are the pointers to structures of the type CvSize . The pointer roi means size of roi of image observed, numObs is the output parameter of the macro.

obsSizeSize of observation vectors to be stored in the structure.

The function cvCreateObsInfo creates new structures to store image observation vectors. For definitions of the parameters roi, dctSize, and delta see the specification of the function cvImgToObs_DCT. ReleaseObsInfo

Releases observation vectors structure

void cvReleaseObsInfo( CvImgObsInfo** obsInfo );

obsInfoAddress of the pointer to the structure CvImgObsInfo .

The function cvReleaseObsInfo frees all memory used by observations and clears pointer to the structure CvImgObsInfo . ImgToObs_DCT

Extracts observation vectors from image

void cvImgToObs_DCT( IplImage* image, float* obs, CvSize dctSize, CvSize obsSize, CvSize delta );

imageInput image.

obsPointer to consequently stored observation vectors.

Page 268: Bioidentià - Il Progetto Ottico

dctSizeSize of image blocks for which DCT (Discrete Cosine Transform) coefficients are to be computed.

obsSizeNumber of the lowest DCT coefficients in the horizontal and vertical directions to be put into the observation vector.

deltaShift in pixels between two consecutive image blocks in the horizontal and vertical directions.

The function cvImgToObs_DCT extracts observation vectors, that is, DCT coefficients, from the image. The user must pass obsInfo.obs as the parameter obs to use this function with other HMM functions and use the structure obsInfo of the CvImgObsInfo type.

Calculating Observations for HMM

CvImgObsInfo* obs_info;

...

cvImgToObs_DCT( image,obs_info->obs, //!!!

dctSize, obsSize, delta );

UniformImgSegm

Performs uniform segmentation of image observations by HMM states

void cvUniformImgSegm( CvImgObsInfo* obsInfo, CvEHMM* hmm );

obsInfoObservations structure.

hmmHMM structure.

The function cvUniformImgSegm segments image observations by HMM states uniformly (see Initial Segmentation for 2D Embedded HMM for 2D embedded HMM with 5 superstates and 3, 6, 6, 6, 3 internal states of every corresponding superstate).

Initial Segmentation for 2D Embedded HMM

InitMixSegm

Segments all observations within every internal state of HMM by state mixture components

void cvInitMixSegm( CvImgObsInfo** obsInfoArray, int numImg, CvEHMM* hmm );

Page 269: Bioidentià - Il Progetto Ottico

obsInfoArrayArray of pointers to the observation structures.

numImgLength of above array.

hmmHMM.

The function cvInitMixSegm takes a group of observations from several training images already segmented by states and splits a set of observation vectors within every internal HMM state into as many clusters as the number of mixture components in the state. EstimateHMMStateParams

Estimates all parameters of every HMM state

void cvEstimateHMMStateParams( CvImgObsInfo** obsInfoArray, int numImg, CvEHMM* hmm );

obsInfoArrayArray of pointers to the observation structures.

numImgLength of the array.

hmmHMM.

The function cvEstimateHMMStateParams computes all inner parameters of every HMM state, including Gaussian means, variances, etc. EstimateTransProb

Computes transition probability matrices for embedded HMM

void cvEstimateTransProb( CvImgObsInfo** obsInfoArray, int numImg, CvEHMM* hmm );

obsInfoArrayArray of pointers to the observation structures.

numImgLength of the above array.

hmmHMM.

The function cvEstimateTransProb uses current segmentation of image observations to compute transition probability matrices for all embedded and external HMMs. EstimateObsProb

Computes probability of every observation of several images

void cvEstimateObsProb( CvImgObsInfo* obsInfo, CvEHMM* hmm );

Page 270: Bioidentià - Il Progetto Ottico

obsInfoObservation structure.

hmmHMM structure.

The function cvEstimateObsProb computes Gaussian probabilities of each observation to occur in each of the internal HMM states.

EViterbi

Executes Viterbi algorithm for embedded HMM

float cvEViterbi( CvImgObsInfo* obsInfo, CvEHMM* hmm );

obsInfoObservation structure.

hmmHMM structure.

The function cvEViterbi executes Viterbi algorithm for embedded HMM. Viterbi algorithm evaluates the likelihood of the best match between the given image observations and the given HMM and performs segmentation of image observations by HMM states. The segmentation is done on the basis of the match found. MixSegmL2

Segments observations from all training images by mixture components of newly assigned states

void cvMixSegmL2( CvImgObsInfo** obsInfoArray, int numImg, CvEHMM* hmm );

obsInfoArrayArray of pointers to the observation structures.

numImgLength of the array.

hmmHMM.

The function cvMixSegmL2 segments observations from all training images by mixture components of newly Viterbi algorithm-assigned states. The function uses Euclidean distance to group vectors around the existing mixtures centers.

Tutta le teoria legata a queste funzionisi basa sulla creazione di vettori di osservazione e sulle procedure eseguite mediante la teoria di Markov inerente alla valutazione degli stati.In altre parole alcune funzioni si interessando di creare degli osservatori i quali sono rappresentati dalla struttura vista all’inizio della serie precedente di funzioni.Questi osservatori sono indirizzati a rappresentare i particolari di una certa immagine.

Page 271: Bioidentià - Il Progetto Ottico

Altre funzioni sono in grado di collegare gli osservatori agli stati interni degli HMM per fare in modo che questi possano eseguire le valutazioni di attinenza.In altre parole in fase di training il sistema crea di vettori di osservazione tipici delle immagini usate nel training stesso.Successivamente i vettori di osservazione di una nuova immagine sono valutati per ottenere le probabilità che questi siano riferiti a quelli di immagini trinate.

void EHMMObjRecognition::Train( ImgObj &imgObj, EHMMObj &ehmmObj ){

const int MAX_ITER = 80; const double STOP_STEP_ITER = 0.01;

CvImgObsInfo **obsInfoVec;IplImage *iplImg;

int obsVecLen = _noDCTCoeff.width * _noDCTCoeff.height;

Tramite I coefficenti settati viene calcolata la lunghezza dei vettori di osservazione.

CvSize _noObs;

CvEHMM *tmplEhmm = ehmmObj.GetEHMM( ).GetCvEHMM( );

Recupera il puntatore all’ EHMM.

int numImages = (int)imgObj.GetNoImages( );

Il numero delle immagini.

bool trained = false; float oldLikelihood = 0; int counter = 0;

int i;

assert( _imgWidth != -1 );assert( _imgHeight != -1 );

if( _suppressIntensity ) {

obsVecLen--;

Elimina il primo coefficente DCT

}

obsInfoVec = new CvImgObsInfo*[ numImages ];assert( obsInfoVec != 0 );

Page 272: Bioidentià - Il Progetto Ottico

Crea l’array per le informazioni relative all’ osservatore in funzione del numero d’immagini.A questo punto per ciascuna immagine vengono eseguite un certo numero di funzioni:

for( i = 0; i < numImages; i++ ) {

iplImg = imgObj.GetGrayScaleImage( i, _imgWidth, _imgHeight );

Si assicura che l’immagine sia a 8 BITS in scale di grigio,

CountObs( *iplImg->roi, _dctSize, _stepSize, _noObs );

Riporta il numero di DCT (DISCRETE COSENE TRANSFORM) che sono stati computati. obsInfoVec[ i ] = cvCreateObsInfo( _noObs, obsVecLen );

Crea losservatore per ciascuna trasformata.

if( _suppressIntensity ) { float *observations = new float[ _noObs.height * _noObs.width * ( obsVecLen + 1 ) ];

Alloca il vettore

cvImgToObs_DCT( iplImg, observations, _dctSize, _noDCTCoeff, _stepSize );

Finalmente estrae I vettori di osservazione di un immagine.

ExtractDCT( observations, obsInfoVec[ i ]->obs, _noObs.height * _noObs.width, obsVecLen );

Estrae I DCT

if ( observations ){

delete( observations);}

} else { cvImgToObs_DCT( iplImg, obsInfoVec[ i ]->obs, _dctSize, _noDCTCoeff, _stepSize ); }

cvUniformImgSegm( obsInfoVec[ i ], tmplEhmm );

Esegue una segmentazione uniforma basandosi sull’osservazione

Page 273: Bioidentià - Il Progetto Ottico

degli stati HMM.

cvReleaseImage( &iplImg ); } cvInitMixSegm( obsInfoVec, numImages, tmplEhmm );

Segmenta tutte le osservazioni utilizzando gli stati interni HMM.In altre parole la funzione prende un gruppo di osservazioni da immagine sulle quali è stato eseguito il training già segmentate per stato e gli splitta un set di vettori di osservazione insieme a ogni singolo stato HMM interno.Lo split produce un insieme di cluster di numero uguale a quello dei misture components degli stati.

while( ( !trained ) && ( counter < MAX_ITER ) ) {

int j; float likelihood = 0;

counter++; cvEstimateHMMStateParams( obsInfoVec, numImages, tmplEhmm );

Valuta i parametri di ogni stato HMM

cvEstimateTransProb( obsInfoVec, numImages, tmplEhmm);

Computa la matrice probabilistica delle transazioni per gli EHMM for( j = 0; j < numImages; j++ ) { cvEstimateObsProb( obsInfoVec[ j ], tmplEhmm ); likelihood += cvEViterbi( obsInfoVec[ j ], tmplEhmm ); }

Per ciascuna immagine presente computa la probablità di ciascun osservatore per ogni immagine.La seconda funzione esegue l’algoritmo di VITERBI sugli EHMM.Tale funzionalità è finalizzata a valutare la verisomiglianza sul l’osservatore migliore trovato relativo ad un immagine.Inoltre viene eseguita la segmentazione.

likelihood /= numImages * obsInfoVec[ 0 ]->obs_size; cvMixSegmL2( &obsInfoVec[ 0 ], numImages, tmplEhmm );

ricava l’osservatore segmentato da tutte le immagini trainate attraverso i misture components dei nuovi stati assegnati.

trained = ( fabs( likelihood - oldLikelihood ) <

Page 274: Bioidentià - Il Progetto Ottico

STOP_STEP_ITER ); oldLikelihood = likelihood; }

for( i = 0; i < numImages; i++ ){

cvReleaseObsInfo( &(obsInfoVec[ i ]) );}delete []obsInfoVec;

ehmmObj.GetEHMM( ).SetTrained( trained );

}

La funzione che calcola la verisomiglianza è la seguente :

float EHMMObjRecognition::ComputeLikelihood( IplImage &img, EHMMObj &ehmmObj ){

CvSize _noObs;

CvEHMM *tmplEhmm = ehmmObj.GetEHMM( ).GetCvEHMM( );int obsVecLen = _noDCTCoeff.width * _noDCTCoeff.height;

CvImgObsInfo* info; if( _suppressIntensity ) { obsVecLen--; }

//Get how many DCT transforms we computeCountObs( *img.roi, _dctSize, _stepSize, _noObs );

info = cvCreateObsInfo( _noObs, obsVecLen );assert( info != 0 );

if( _suppressIntensity ) { float *observations = new float[ _noObs.height * _noObs.width * ( obsVecLen + 1 ) ];

cvImgToObs_DCT( &img, observations, _dctSize, _noDCTCoeff, _stepSize );

ExtractDCT( observations, info->obs, _noObs.height * _noObs.width, obsVecLen );

if ( observations ){

delete( observations);}

}

Page 275: Bioidentià - Il Progetto Ottico

else { cvImgToObs_DCT( &img, info->obs, _dctSize, _noDCTCoeff, _stepSize ); }

cvEstimateObsProb( info, tmplEhmm );

return cvEViterbi( info, tmplEhmm );}

Un punto critico è quello legato alla scelta dei valori legati ai superstati come avviene nella funzione :

void CEHMMRetinalIDDlg::CreateOpenRetinalEHMMDb( const string &pathEhmmDb, const string &ehmmCvDbName )

{EHMMObjDatabase ehmmDb;int noStates[] = { 5, 4, 4, 4, 4, 4 };int numMixtures[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,

3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };int vecSize = 15; //because we suppress the first coefficient

DCT_SIZE_X * DCT_SIZE_Y - 1ehmmDb.Create( ehmmCvDbName, noStates, numMixtures, vecSize );

Il metodo Create della classe ehmmDb è :

void EHMMObjDatabase::Create( const string &databaseName, int *noStates,

int *noMix, int vecSize ){

int i;int totalNoInternalStates;

assert( noStates != 0 );assert( noMix != 0 );assert( vecSize != 0 );assert( databaseName != "" );

//Save the name of the database_databaseName = databaseName;

//Save the ehmm creation parameters

memcpy( _numStates, noStates, sizeof( int ) * ( noStates[ 0 ] + 1 ) );

//Count the number of internal statesfor ( totalNoInternalStates = 0, i = 1; i < noStates[ 0 ] + 1;

i++ ){

Page 276: Bioidentià - Il Progetto Ottico

totalNoInternalStates += noStates[ i ];}

memcpy( _numMix, noMix, sizeof( int ) * totalNoInternalStates );

_vecSize = vecSize;}

Nel manuale, ad esempio, viene mostrata un immagine su cui vengono applicati 5 superstati e 3, 6, 6, 6, 3 stati interni.Tale scelta di valori viene graficamente visualizzata su di un immagine come in quella a fianco.Nel caso della retina la scelta dovrà essere fatta in modo tale da riuscire a coprire nel modo migliore i particolari dell’immagine stessa.Una scelta di 5 superstati e 4,4,4,4,4 potrebbe essere una soluzione equilibrata.

La valutazione relativa alla scelta dei valori dovrà avvenire mediante prove.Nel caso dell'immagine vista precedentemente la scelta è stata quella relativa ai cinque super stati e successivamente quella degli stati interni visti in quanto le caratteristiche del viso venivano settorizzate in modo ottimale mediante queste valorizzazione.Il passo successivo dovrà essere quello

di implementare mediante le classi ADO già sviluppate la gestione dei database.

Page 277: Bioidentià - Il Progetto Ottico

Le classi di gestione delle basi di datiIl sistema d’identificazione retinale necessita anche di una parte legata alla gestione dei database.MICROSOFT possiede diversi metodi per la gestione di questi tra i quali il metodo ODBC, quello ADO, il metodo OLEDB ecc.Ad ogni modo il sistema ADO è tra quelli più funzionali ed inoltre è facilmente inseribile all’interno di calssi indirizzate alla gestione del sistema.

I files che gestiscono la classe ADO Database sono quelli che seguono.

//// MODULE: Ado.h//

#ifndef _ADO_H_#define _ADO_H_

#if _MSC_VER >= 1000#pragma once#endif // _MSC_VER >= 1000#include <afx.h>#include <afxdisp.h>#include <math.h>

#pragma warning (disable: 4146)// CG : In order to use this code against a different version of ADO, the appropriate// ADO library needs to be used in the #import statement#import "C:\Program Files\Common Files\System\ADO\msado15.dll" rename_namespace("ADOCG") rename("EOF", "EndOfFile")using namespace ADOCG;

#pragma warning (default: 4146)

#include "icrsint.h"

class CADOCommand;

struct CADOFieldInfo{

char m_strName[30]; short m_nType;long m_lSize; long m_lDefinedSize;long m_lAttributes;short m_nOrdinalPosition;BOOL m_bRequired; BOOL m_bAllowZeroLength; long m_lCollatingOrder;

};

CString IntToStr(int nVal);

CString LongToStr(long lVal);

CString ULongToStr(unsigned long ulVal);

Page 278: Bioidentià - Il Progetto Ottico

CString DblToStr(double dblVal, int ndigits = 20);

CString DblToStr(float fltVal);

class CADODatabase{public:

enum cadoConnectModeEnum {

connectModeUnknown = adModeUnknown,connectModeRead = adModeRead,connectModeWrite = adModeWrite,connectModeReadWrite = adModeReadWrite,connectModeShareDenyRead = adModeShareDenyRead,connectModeShareDenyWrite = adModeShareDenyWrite,connectModeShareExclusive = adModeShareExclusive,connectModeShareDenyNone = adModeShareDenyNone

};

CADODatabase(){

::CoInitialize(NULL);

m_pConnection = NULL;m_strConnection = _T("");m_strLastError = _T("");m_dwLastError = 0;m_pConnection.CreateInstance(__uuidof(Connection));m_nRecordsAffected = 0;m_nConnectionTimeout = 0;

}

virtual ~CADODatabase(){

Close();m_pConnection.Release();m_pConnection = NULL;m_strConnection = _T("");m_strLastError = _T("");m_dwLastError = 0;::CoUninitialize();

}

BOOL Open(LPCTSTR lpstrConnection = _T(""), LPCTSTR lpstrUserID = _T(""), LPCTSTR lpstrPassword = _T(""));

_ConnectionPtr GetActiveConnection() {return m_pConnection;};

BOOL Execute(LPCTSTR lpstrExec);int GetRecordsAffected()

{return m_nRecordsAffected;};DWORD GetRecordCount(_RecordsetPtr m_pRs);long BeginTransaction()

{return m_pConnection->BeginTrans();};long CommitTransaction()

{return m_pConnection->CommitTrans();};long RollbackTransaction()

{return m_pConnection->RollbackTrans();};BOOL IsOpen();void Close();void SetConnectionMode(cadoConnectModeEnum nMode)

Page 279: Bioidentià - Il Progetto Ottico

{m_pConnection->PutMode((enum ConnectModeEnum)nMode);};void SetConnectionString(LPCTSTR lpstrConnection)

{m_strConnection = lpstrConnection;};CString GetConnectionString()

{return m_strConnection;};CString GetLastErrorString()

{return m_strLastError;};DWORD GetLastError()

{return m_dwLastError;};CString GetErrorDescription()

{return m_strErrorDescription;};void SetConnectionTimeout(long nConnectionTimeout = 30)

{m_nConnectionTimeout = nConnectionTimeout;};

protected:void dump_com_error(_com_error &e);

public:_ConnectionPtr m_pConnection;

protected:CString m_strConnection;CString m_strLastError;CString m_strErrorDescription;DWORD m_dwLastError;int m_nRecordsAffected;long m_nConnectionTimeout;

};

class CADORecordset{public:

BOOL Clone(CADORecordset& pRs);

enum cadoOpenEnum{

openUnknown = 0,openQuery = 1,openTable = 2,openStoredProc = 3

};

enum cadoEditEnum{

dbEditNone = 0,dbEditNew = 1,dbEdit = 2

};

enum cadoPositionEnum{

positionUnknown = -1,positionBOF = -2,positionEOF = -3

};

enum cadoSearchEnum{

searchForward = 1,searchBackward = -1

};

Page 280: Bioidentià - Il Progetto Ottico

enum cadoDataType{

typeEmpty = adEmpty,typeTinyInt = adTinyInt,typeSmallInt = adSmallInt,typeInteger = adInteger,typeBigInt = adBigInt,typeUnsignedTinyInt = adUnsignedTinyInt,typeUnsignedSmallInt = adUnsignedSmallInt,typeUnsignedInt = adUnsignedInt,typeUnsignedBigInt = adUnsignedBigInt,typeSingle = adSingle,typeDouble = adDouble,typeCurrency = adCurrency,typeDecimal = adDecimal,typeNumeric = adNumeric,typeBoolean = adBoolean,typeError = adError,typeUserDefined = adUserDefined,typeVariant = adVariant,typeIDispatch = adIDispatch,typeIUnknown = adIUnknown,typeGUID = adGUID,typeDate = adDate,typeDBDate = adDBDate,typeDBTime = adDBTime,typeDBTimeStamp = adDBTimeStamp,typeBSTR = adBSTR,typeChar = adChar,typeVarChar = adVarChar,typeLongVarChar = adLongVarChar,typeWChar = adWChar,typeVarWChar = adVarWChar,typeLongVarWChar = adLongVarWChar,typeBinary = adBinary,typeVarBinary = adVarBinary,typeLongVarBinary = adLongVarBinary,typeChapter = adChapter,typeFileTime = adFileTime,typePropVariant = adPropVariant,typeVarNumeric = adVarNumeric,typeArray = adVariant

};

enum cadoSchemaType {

schemaSpecific = adSchemaProviderSpecific,schemaAsserts = adSchemaAsserts,schemaCatalog = adSchemaCatalogs,schemaCharacterSet = adSchemaCharacterSets,schemaCollections = adSchemaCollations,schemaColumns = adSchemaColumns,schemaConstraints = adSchemaCheckConstraints,schemaConstraintColumnUsage = adSchemaConstraintColumnUsage,schemaConstraintTableUsage = adSchemaConstraintTableUsage,shemaKeyColumnUsage = adSchemaKeyColumnUsage,schemaTableConstraints = adSchemaTableConstraints,schemaColumnsDomainUsage = adSchemaColumnsDomainUsage,schemaIndexes = adSchemaIndexes,schemaColumnPrivileges = adSchemaColumnPrivileges,schemaTablePrivileges = adSchemaTablePrivileges,

Page 281: Bioidentià - Il Progetto Ottico

schemaUsagePrivileges = adSchemaUsagePrivileges,schemaProcedures = adSchemaProcedures,schemaTables =adSchemaTables,schemaProviderTypes = adSchemaProviderTypes,schemaViews = adSchemaViews,schemaProcedureParameters = adSchemaProcedureParameters,schemaForeignKeys = adSchemaForeignKeys,schemaPrimaryKeys = adSchemaPrimaryKeys,schemaProcedureColumns = adSchemaProcedureColumns,schemaDBInfoKeywords = adSchemaDBInfoKeywords,schemaDBInfoLiterals = adSchemaDBInfoLiterals,schemaCubes = adSchemaCubes,schemaDimensions = adSchemaDimensions,schemaHierarchies = adSchemaHierarchies, schemaLevels = adSchemaLevels,schemaMeasures = adSchemaMeasures,schemaProperties = adSchemaProperties,schemaMembers = adSchemaMembers,

};

BOOL SetFieldValue(int nIndex, int nValue);BOOL SetFieldValue(LPCTSTR lpFieldName, int nValue);BOOL SetFieldValue(int nIndex, long lValue);BOOL SetFieldValue(LPCTSTR lpFieldName, long lValue);BOOL SetFieldValue(int nIndex, unsigned long lValue);BOOL SetFieldValue(LPCTSTR lpFieldName, unsigned long lValue);BOOL SetFieldValue(int nIndex, double dblValue);BOOL SetFieldValue(LPCTSTR lpFieldName, double dblValue);BOOL SetFieldValue(int nIndex, CString strValue);BOOL SetFieldValue(LPCTSTR lpFieldName, CString strValue);BOOL SetFieldValue(int nIndex, COleDateTime time);BOOL SetFieldValue(LPCTSTR lpFieldName, COleDateTime time);BOOL SetFieldValue(int nIndex, bool bValue);BOOL SetFieldValue(LPCTSTR lpFieldName, bool bValue);BOOL SetFieldValue(int nIndex, COleCurrency cyValue);BOOL SetFieldValue(LPCTSTR lpFieldName, COleCurrency cyValue);BOOL SetFieldValue(int nIndex, _variant_t vtValue);BOOL SetFieldValue(LPCTSTR lpFieldName, _variant_t vtValue);

BOOL SetFieldEmpty(int nIndex);BOOL SetFieldEmpty(LPCTSTR lpFieldName);

void CancelUpdate();BOOL Update();void Edit();BOOL AddNew();BOOL AddNew(CADORecordBinding &pAdoRecordBinding);

BOOL Find(LPCTSTR lpFind, int nSearchDirection = CADORecordset::searchForward);

BOOL FindFirst(LPCTSTR lpFind);BOOL FindNext();

CADORecordset();

CADORecordset(CADODatabase* pAdoDatabase);

virtual ~CADORecordset(){

Close();if(m_pRecordset)

Page 282: Bioidentià - Il Progetto Ottico

m_pRecordset.Release();if(m_pCmd)

m_pCmd.Release();m_pRecordset = NULL;m_pCmd = NULL;m_pRecBinding = NULL;m_strQuery = _T("");m_strLastError = _T("");m_dwLastError = 0;m_nEditStatus = dbEditNone;

}

CString GetQuery() {return m_strQuery;};

void SetQuery(LPCSTR strQuery) {m_strQuery = strQuery;};

BOOL RecordBinding(CADORecordBinding &pAdoRecordBinding);DWORD GetRecordCount();BOOL IsOpen();void Close();BOOL Open(_ConnectionPtr mpdb, LPCTSTR lpstrExec = _T(""), int nOption =

CADORecordset::openUnknown);BOOL Open(LPCTSTR lpstrExec = _T(""), int nOption =

CADORecordset::openUnknown);BOOL OpenSchema(int nSchema, LPCTSTR SchemaID = _T(""));long GetFieldCount()

{return m_pRecordset->Fields->GetCount();};BOOL GetFieldValue(LPCTSTR lpFieldName, int& nValue);BOOL GetFieldValue(int nIndex, int& nValue);BOOL GetFieldValue(LPCTSTR lpFieldName, long& lValue);BOOL GetFieldValue(int nIndex, long& lValue);BOOL GetFieldValue(LPCTSTR lpFieldName, unsigned long& ulValue);BOOL GetFieldValue(int nIndex, unsigned long& ulValue);BOOL GetFieldValue(LPCTSTR lpFieldName, double& dbValue);BOOL GetFieldValue(int nIndex, double& dbValue);BOOL GetFieldValue(LPCTSTR lpFieldName, CString& strValue, CString

strDateFormat = _T(""));BOOL GetFieldValue(int nIndex, CString& strValue, CString strDateFormat =

_T(""));BOOL GetFieldValue(LPCTSTR lpFieldName, COleDateTime& time);BOOL GetFieldValue(int nIndex, COleDateTime& time);BOOL GetFieldValue(int nIndex, bool& bValue);BOOL GetFieldValue(LPCTSTR lpFieldName, bool& bValue);BOOL GetFieldValue(int nIndex, COleCurrency& cyValue);BOOL GetFieldValue(LPCTSTR lpFieldName, COleCurrency& cyValue);BOOL GetFieldValue(int nIndex, _variant_t& vtValue);BOOL GetFieldValue(LPCTSTR lpFieldName, _variant_t& vtValue);

BOOL IsFieldNull(LPCTSTR lpFieldName);BOOL IsFieldNull(int nIndex);BOOL IsFieldEmpty(LPCTSTR lpFieldName);BOOL IsFieldEmpty(int nIndex);BOOL IsEof()

{return m_pRecordset->EndOfFile == VARIANT_TRUE;};BOOL IsEOF()

{return m_pRecordset->EndOfFile == VARIANT_TRUE;};BOOL IsBof()

{return m_pRecordset->BOF == VARIANT_TRUE;};BOOL IsBOF()

{return m_pRecordset->BOF == VARIANT_TRUE;};void MoveFirst()

{m_pRecordset->MoveFirst();};

Page 283: Bioidentià - Il Progetto Ottico

void MoveNext() {m_pRecordset->MoveNext();};

void MovePrevious() {m_pRecordset->MovePrevious();};

void MoveLast() {m_pRecordset->MoveLast();};

long GetAbsolutePage(){return m_pRecordset->GetAbsolutePage();};

void SetAbsolutePage(int nPage){m_pRecordset->PutAbsolutePage((enum PositionEnum)nPage);};

long GetPageCount(){return m_pRecordset->GetPageCount();};

long GetPageSize(){return m_pRecordset->GetPageSize();};

void SetPageSize(int nSize){m_pRecordset->PutPageSize(nSize);};

long GetAbsolutePosition(){return m_pRecordset->GetAbsolutePosition();};

void SetAbsolutePosition(int nPosition){m_pRecordset->PutAbsolutePosition((enum PositionEnum)nPosition);};

BOOL GetFieldInfo(LPCTSTR lpFieldName, CADOFieldInfo* fldInfo);BOOL GetFieldInfo(int nIndex, CADOFieldInfo* fldInfo);BOOL AppendChunk(LPCTSTR lpFieldName, LPVOID lpData, UINT nBytes);BOOL AppendChunk(int nIndex, LPVOID lpData, UINT nBytes);

BOOL GetChunk(LPCTSTR lpFieldName, CString& strValue);BOOL GetChunk(int nIndex, CString& strValue);

BOOL GetChunk(LPCTSTR lpFieldName, LPVOID pData);BOOL GetChunk(int nIndex, LPVOID pData);

CString GetString(LPCTSTR lpCols, LPCTSTR lpRows, LPCTSTR lpNull, long numRows = 0);

CString GetLastErrorString() {return m_strLastError;};

DWORD GetLastError(){return m_dwLastError;};

void GetBookmark(){m_varBookmark = m_pRecordset->Bookmark;};

BOOL SetBookmark();BOOL Delete();BOOL IsConnectionOpen()

{return m_pConnection != NULL && m_pConnection->GetState() != adStateClosed;};

_RecordsetPtr GetRecordset(){return m_pRecordset;};

_ConnectionPtr GetActiveConnection() {return m_pConnection;};

BOOL SetFilter(LPCTSTR strFilter);BOOL SetSort(LPCTSTR lpstrCriteria);BOOL SaveAsXML(LPCTSTR lpstrXMLFile);BOOL OpenXML(LPCTSTR lpstrXMLFile);BOOL Execute(CADOCommand* pCommand);BOOL Requery();

public:_RecordsetPtr m_pRecordset;_CommandPtr m_pCmd;

protected:_ConnectionPtr m_pConnection;

Page 284: Bioidentià - Il Progetto Ottico

int m_nSearchDirection;CString m_strFind;_variant_t m_varBookFind;_variant_t m_varBookmark;int m_nEditStatus;CString m_strLastError;DWORD m_dwLastError;void dump_com_error(_com_error &e);IADORecordBinding *m_pRecBinding;CString m_strQuery;

protected:BOOL PutFieldValue(LPCTSTR lpFieldName, _variant_t vtFld);BOOL PutFieldValue(_variant_t vtIndex, _variant_t vtFld);BOOL GetFieldInfo(FieldPtr pField, CADOFieldInfo* fldInfo);BOOL GetChunk(FieldPtr pField, CString& strValue);BOOL GetChunk(FieldPtr pField, LPVOID lpData);BOOL AppendChunk(FieldPtr pField, LPVOID lpData, UINT nBytes);

};

class CADOParameter{public:

enum cadoParameterDirection{

paramUnknown = adParamUnknown,paramInput = adParamInput,paramOutput = adParamOutput,paramInputOutput = adParamInputOutput,paramReturnValue = adParamReturnValue

};

CADOParameter(int nType, long lSize = 0, int nDirection = paramInput, CString strName = _T(""));

virtual ~CADOParameter(){

m_pParameter.Release();m_pParameter = NULL;m_strName = _T("");

}

BOOL SetValue(int nValue);BOOL SetValue(long lValue);BOOL SetValue(double dbValue);BOOL SetValue(CString strValue);BOOL SetValue(COleDateTime time);BOOL SetValue(_variant_t vtValue);BOOL GetValue(int& nValue);BOOL GetValue(long& lValue);BOOL GetValue(double& dbValue);BOOL GetValue(CString& strValue, CString strDateFormat = _T(""));BOOL GetValue(COleDateTime& time);BOOL GetValue(_variant_t& vtValue);void SetPrecision(int nPrecision)

{m_pParameter->PutPrecision(nPrecision);};void SetScale(int nScale)

{m_pParameter->PutNumericScale(nScale);};

void SetName(CString strName)

Page 285: Bioidentià - Il Progetto Ottico

{m_strName = strName;};CString GetName()

{return m_strName;};int GetType()

{return m_nType;};_ParameterPtr GetParameter()

{return m_pParameter;};

protected:void dump_com_error(_com_error &e);

protected:_ParameterPtr m_pParameter;CString m_strName;int m_nType;CString m_strLastError;DWORD m_dwLastError;

};

class CADOCommand{public:

enum cadoCommandType{

typeCmdText = adCmdText,typeCmdTable = adCmdTable,typeCmdTableDirect = adCmdTableDirect,typeCmdStoredProc = adCmdStoredProc,typeCmdUnknown = adCmdUnknown,typeCmdFile = adCmdFile

};

CADOCommand(CADODatabase* pAdoDatabase, CString strCommandText = _T(""), int nCommandType = typeCmdStoredProc);

virtual ~CADOCommand(){

m_pCommand.Release();m_pCommand = NULL;m_strCommandText = _T("");

}

void SetTimeout(long nTimeOut){m_pCommand->PutCommandTimeout(nTimeOut);};

void SetText(CString strCommandText);void SetType(int nCommandType);int GetType()

{return m_nCommandType;};BOOL AddParameter(CADOParameter* pAdoParameter);BOOL AddParameter(CString strName, int nType, int nDirection, long lSize,

int nValue);BOOL AddParameter(CString strName, int nType, int nDirection, long lSize,

long lValue);BOOL AddParameter(CString strName, int nType, int nDirection, long lSize,

double dblValue, int nPrecision = 0, int nScale = 0);BOOL AddParameter(CString strName, int nType, int nDirection, long lSize,

CString strValue);BOOL AddParameter(CString strName, int nType, int nDirection, long lSize,

COleDateTime time);BOOL AddParameter(CString strName, int nType, int nDirection, long lSize,

_variant_t vtValue, int nPrecision = 0, int nScale = 0);CString GetText()

Page 286: Bioidentià - Il Progetto Ottico

{return m_strCommandText;};BOOL Execute();int GetRecordsAffected()

{return m_nRecordsAffected;};_CommandPtr GetCommand()

{return m_pCommand;};

protected:void dump_com_error(_com_error &e);

protected:_CommandPtr m_pCommand;int m_nCommandType;int m_nRecordsAffected;CString m_strCommandText;CString m_strLastError;DWORD m_dwLastError;

};

class CADOException : public CException{public:

enum{

noError, // no errorUnknown, // unknown error

};

DECLARE_DYNAMIC(CADOException);

CADOException(int nCause = 0, CString strErrorString = _T(""));virtual ~CADOException();

static int GetError(int nADOError);

public:int m_nCause; CString m_strErrorString;

protected:

};

void AfxThrowADOException(int nADOError = 1000, CString strErrorString = _T(""));

#endif

Il file .CPP con il codice di gestione invece è quello che segue.

//// MODULE: Ado.cpp////

#include "ado.h"

#define ChunkSize 100

/////////////////////////////////////////////////////////

Page 287: Bioidentià - Il Progetto Ottico

// CADODatabase Class//

DWORD CADODatabase::GetRecordCount(_RecordsetPtr m_pRs){

DWORD numRows = 0;

numRows = m_pRs->GetRecordCount();

if(numRows == -1){

if(m_pRs->EndOfFile != VARIANT_TRUE)m_pRs->MoveFirst();

while(m_pRs->EndOfFile != VARIANT_TRUE){

numRows++;m_pRs->MoveNext();

}if(numRows > 0)

m_pRs->MoveFirst();}return numRows;

}

BOOL CADODatabase::Open(LPCTSTR lpstrConnection, LPCTSTR lpstrUserID, LPCTSTR lpstrPassword){

HRESULT hr = S_OK;

if(IsOpen())Close();

if(strcmp(lpstrConnection, _T("")) != 0)m_strConnection = lpstrConnection;

ASSERT(!m_strConnection.IsEmpty());

try{

if(m_nConnectionTimeout != 0)m_pConnection->PutConnectionTimeout(m_nConnectionTimeout);

hr = m_pConnection->Open(_bstr_t(m_strConnection), _bstr_t(lpstrUserID), _bstr_t(lpstrPassword), NULL);

return hr == S_OK;}catch(_com_error &e){

dump_com_error(e);return FALSE;

}

}

void CADODatabase::dump_com_error(_com_error &e){

CString ErrorStr;

_bstr_t bstrSource(e.Source());_bstr_t bstrDescription(e.Description());ErrorStr.Format( "CADODataBase Error\n\tCode = %08lx\n\tCode meaning = %s\

n\tSource = %s\n\tDescription = %s\n",

Page 288: Bioidentià - Il Progetto Ottico

e.Error(), e.ErrorMessage(), (LPCSTR)bstrSource, (LPCSTR)bstrDescription);

m_strErrorDescription = (LPCSTR)bstrDescription ;m_strLastError = _T("Connection String = " + GetConnectionString() + '\n'

+ ErrorStr);m_dwLastError = e.Error(); #ifdef _DEBUG

AfxMessageBox(ErrorStr, MB_OK | MB_ICONERROR );#endif

}

BOOL CADODatabase::IsOpen(){

if(m_pConnection )return m_pConnection->GetState() != adStateClosed;

return FALSE;}

void CADODatabase::Close(){

if(IsOpen())m_pConnection->Close();

}

/////////////////////////////////////////////////////////// CADORecordset Class//

CADORecordset::CADORecordset(){

m_pRecordset = NULL;m_pCmd = NULL;m_strQuery = _T("");m_strLastError = _T("");m_dwLastError = 0;m_pRecBinding = NULL;m_pRecordset.CreateInstance(__uuidof(Recordset));m_pCmd.CreateInstance(__uuidof(Command));m_nEditStatus = CADORecordset::dbEditNone;m_nSearchDirection = CADORecordset::searchForward;

}

CADORecordset::CADORecordset(CADODatabase* pAdoDatabase){

m_pRecordset = NULL;m_pCmd = NULL;m_strQuery = _T("");m_strLastError = _T("");m_dwLastError = 0;m_pRecBinding = NULL;m_pRecordset.CreateInstance(__uuidof(Recordset));m_pCmd.CreateInstance(__uuidof(Command));m_nEditStatus = CADORecordset::dbEditNone;m_nSearchDirection = CADORecordset::searchForward;

m_pConnection = pAdoDatabase->GetActiveConnection();}

BOOL CADORecordset::Open(_ConnectionPtr mpdb, LPCTSTR lpstrExec, int nOption){

Page 289: Bioidentià - Il Progetto Ottico

Close();

if(strcmp(lpstrExec, _T("")) != 0)m_strQuery = lpstrExec;

ASSERT(!m_strQuery.IsEmpty());

if(m_pConnection == NULL)m_pConnection = mpdb;

m_strQuery.TrimLeft();BOOL bIsSelect = m_strQuery.Mid(0, strlen("Select

")).CompareNoCase("select ") == 0 && nOption == openUnknown;

try{

m_pRecordset->CursorType = adOpenStatic;m_pRecordset->CursorLocation = adUseClient;if(bIsSelect || nOption == openQuery || nOption == openUnknown)

m_pRecordset->Open((LPCSTR)m_strQuery, _variant_t((IDispatch*)mpdb, TRUE),

adOpenStatic, adLockOptimistic, adCmdUnknown);

else if(nOption == openTable)m_pRecordset->Open((LPCSTR)m_strQuery,

_variant_t((IDispatch*)mpdb, TRUE), adOpenKeyset, adLockOptimistic,

adCmdTable);else if(nOption == openStoredProc){

m_pCmd->ActiveConnection = mpdb;m_pCmd->CommandText = _bstr_t(m_strQuery);m_pCmd->CommandType = adCmdStoredProc;m_pConnection->CursorLocation = adUseClient;

m_pRecordset = m_pCmd->Execute(NULL, NULL, adCmdText);}else{

TRACE( "Unknown parameter. %d", nOption);return FALSE;

}}catch(_com_error &e){

dump_com_error(e);return FALSE;

}

return m_pRecordset != NULL;}

BOOL CADORecordset::Open(LPCTSTR lpstrExec, int nOption){

ASSERT(m_pConnection != NULL);ASSERT(m_pConnection->GetState() != adStateClosed);return Open(m_pConnection, lpstrExec, nOption);

}

BOOL CADORecordset::OpenSchema(int nSchema, LPCTSTR SchemaID){

try

Page 290: Bioidentià - Il Progetto Ottico

{_variant_t vtSchemaID = vtMissing;

if(strlen(SchemaID) != 0)vtSchemaID = SchemaID;

m_pRecordset = m_pConnection->OpenSchema((enum SchemaEnum)nSchema, vtMissing, vtSchemaID);

return TRUE;}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::Requery(){

if(IsOpen()){

try{

m_pRecordset->Requery(adExecuteRecord);}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}return TRUE;

}

BOOL CADORecordset::GetFieldValue(LPCTSTR lpFieldName, double& dbValue){

double val = (double)NULL;_variant_t vtFld;

try{

vtFld = m_pRecordset->Fields->GetItem(lpFieldName)->Value;switch(vtFld.vt){case VT_R4:

val = vtFld.fltVal;break;

case VT_R8:val = vtFld.dblVal;break;

case VT_DECIMAL://Corrected by José Carlos Martínez Galánval = vtFld.decVal.Lo32;val *= (vtFld.decVal.sign == 128)? -1 : 1;val /= pow(10, vtFld.decVal.scale); break;

case VT_UI1:val = vtFld.iVal;break;

case VT_I2:case VT_I4:

Page 291: Bioidentià - Il Progetto Ottico

val = vtFld.lVal;break;

case VT_INT:val = vtFld.intVal;break;

case VT_NULL:case VT_EMPTY:

val = 0;break;

default:val = vtFld.dblVal;

}dbValue = val;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(int nIndex, double& dbValue){

double val = (double)NULL;_variant_t vtFld;_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

try{

vtFld = m_pRecordset->Fields->GetItem(vtIndex)->Value;switch(vtFld.vt){case VT_R4:

val = vtFld.fltVal;break;

case VT_R8:val = vtFld.dblVal;break;

case VT_DECIMAL://Corrected by José Carlos Martínez Galánval = vtFld.decVal.Lo32;val *= (vtFld.decVal.sign == 128)? -1 : 1;val /= pow(10, vtFld.decVal.scale); break;

case VT_UI1:val = vtFld.iVal;break;

case VT_I2:case VT_I4:

val = vtFld.lVal;break;

case VT_INT:val = vtFld.intVal;break;

case VT_NULL:case VT_EMPTY:

val = 0;

Page 292: Bioidentià - Il Progetto Ottico

break;default:

val = 0;}dbValue = val;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(LPCTSTR lpFieldName, long& lValue){

long val = (long)NULL;_variant_t vtFld;

try{

vtFld = m_pRecordset->Fields->GetItem(lpFieldName)->Value;if(vtFld.vt != VT_NULL && vtFld.vt != VT_EMPTY)

val = vtFld.lVal;lValue = val;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(int nIndex, long& lValue){

long val = (long)NULL;_variant_t vtFld;_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

try{

vtFld = m_pRecordset->Fields->GetItem(vtIndex)->Value;if(vtFld.vt != VT_NULL && vtFld.vt != VT_EMPTY)

val = vtFld.lVal;lValue = val;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(LPCTSTR lpFieldName, unsigned long& ulValue){

Page 293: Bioidentià - Il Progetto Ottico

long val = (long)NULL;_variant_t vtFld;

try{

vtFld = m_pRecordset->Fields->GetItem(lpFieldName)->Value;if(vtFld.vt != VT_NULL && vtFld.vt != VT_EMPTY)

val = vtFld.ulVal;ulValue = val;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(int nIndex, unsigned long& ulValue){

long val = (long)NULL;_variant_t vtFld;_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

try{

vtFld = m_pRecordset->Fields->GetItem(vtIndex)->Value;if(vtFld.vt != VT_NULL && vtFld.vt != VT_EMPTY)

val = vtFld.ulVal;ulValue = val;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(LPCTSTR lpFieldName, int& nValue){

int val = NULL;_variant_t vtFld;

try{

vtFld = m_pRecordset->Fields->GetItem(lpFieldName)->Value;switch(vtFld.vt){case VT_BOOL:

val = vtFld.boolVal;break;

case VT_I2:case VT_UI1:

val = vtFld.iVal;break;

case VT_INT:val = vtFld.intVal;break;

Page 294: Bioidentià - Il Progetto Ottico

case VT_NULL:case VT_EMPTY:

val = 0;break;

default:val = vtFld.iVal;

}nValue = val;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(int nIndex, int& nValue){

int val = (int)NULL;_variant_t vtFld;_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

try{

vtFld = m_pRecordset->Fields->GetItem(vtIndex)->Value;switch(vtFld.vt){case VT_BOOL:

val = vtFld.boolVal;break;

case VT_I2:case VT_UI1:

val = vtFld.iVal;break;

case VT_INT:val = vtFld.intVal;break;

case VT_NULL:case VT_EMPTY:

val = 0;break;

default:val = vtFld.iVal;

}nValue = val;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(LPCTSTR lpFieldName, CString& strValue, CString strDateFormat){

CString str = _T("");

Page 295: Bioidentià - Il Progetto Ottico

_variant_t vtFld;

try{

vtFld = m_pRecordset->Fields->GetItem(lpFieldName)->Value;switch(vtFld.vt) {case VT_R4:

str = DblToStr(vtFld.fltVal);break;

case VT_R8:str = DblToStr(vtFld.dblVal);break;

case VT_BSTR:str = vtFld.bstrVal;break;

case VT_I2:case VT_UI1:

str = IntToStr(vtFld.iVal);break;

case VT_INT:str = IntToStr(vtFld.intVal);break;

case VT_I4:str = LongToStr(vtFld.lVal);break;

case VT_UI4:str = ULongToStr(vtFld.ulVal);break;

case VT_DECIMAL:{//Corrected by José Carlos Martínez Galándouble val = vtFld.decVal.Lo32;val *= (vtFld.decVal.sign == 128)? -1 : 1;val /= pow(10, vtFld.decVal.scale); str = DblToStr(val);}break;

case VT_DATE:{

COleDateTime dt(vtFld);

if(strDateFormat.IsEmpty())strDateFormat = _T("%Y-%m-%d %H:%M:%S");

str = dt.Format(strDateFormat);}break;

case VT_EMPTY:case VT_NULL:

str.Empty();break;

case VT_BOOL:str = vtFld.boolVal == VARIANT_TRUE? 'T':'F';break;

default:str.Empty();return FALSE;

}strValue = str;return TRUE;

}catch(_com_error &e)

Page 296: Bioidentià - Il Progetto Ottico

{dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(int nIndex, CString& strValue, CString strDateFormat){

CString str = _T("");_variant_t vtFld;_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

try{

vtFld = m_pRecordset->Fields->GetItem(vtIndex)->Value;switch(vtFld.vt) {case VT_R4:

str = DblToStr(vtFld.fltVal);break;

case VT_R8:str = DblToStr(vtFld.dblVal);break;

case VT_BSTR:str = vtFld.bstrVal;break;

case VT_I2:case VT_UI1:

str = IntToStr(vtFld.iVal);break;

case VT_INT:str = IntToStr(vtFld.intVal);break;

case VT_I4:str = LongToStr(vtFld.lVal);break;

case VT_UI4:str = ULongToStr(vtFld.ulVal);break;

case VT_DECIMAL:{//Corrected by José Carlos Martínez Galándouble val = vtFld.decVal.Lo32;val *= (vtFld.decVal.sign == 128)? -1 : 1;val /= pow(10, vtFld.decVal.scale); str = DblToStr(val);}break;

case VT_DATE:{

COleDateTime dt(vtFld);

if(strDateFormat.IsEmpty())strDateFormat = _T("%Y-%m-%d %H:%M:%S");

str = dt.Format(strDateFormat);}break;

case VT_BOOL:

Page 297: Bioidentià - Il Progetto Ottico

str = vtFld.boolVal == VARIANT_TRUE? 'T':'F';break;

case VT_EMPTY:case VT_NULL:

str.Empty();break;

default:str.Empty();return FALSE;

}strValue = str;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(LPCTSTR lpFieldName, COleDateTime& time){

_variant_t vtFld;

try{

vtFld = m_pRecordset->Fields->GetItem(lpFieldName)->Value;switch(vtFld.vt) {case VT_DATE:

{COleDateTime dt(vtFld);time = dt;

}break;

case VT_EMPTY:case VT_NULL:

time.SetStatus(COleDateTime::null);break;

default:return FALSE;

}return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(int nIndex, COleDateTime& time){

_variant_t vtFld;_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

try{

vtFld = m_pRecordset->Fields->GetItem(vtIndex)->Value;

Page 298: Bioidentià - Il Progetto Ottico

switch(vtFld.vt) {case VT_DATE:

{COleDateTime dt(vtFld);time = dt;

}break;

case VT_EMPTY:case VT_NULL:

time.SetStatus(COleDateTime::null);break;

default:return FALSE;

}return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(LPCTSTR lpFieldName, bool& bValue){

_variant_t vtFld;

try{

vtFld = m_pRecordset->Fields->GetItem(lpFieldName)->Value;switch(vtFld.vt) {case VT_BOOL:

bValue = vtFld.boolVal == VARIANT_TRUE? true: false;break;

case VT_EMPTY:case VT_NULL:

bValue = false;break;

default:return FALSE;

}return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(int nIndex, bool& bValue){

_variant_t vtFld;_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

try{

Page 299: Bioidentià - Il Progetto Ottico

vtFld = m_pRecordset->Fields->GetItem(vtIndex)->Value;switch(vtFld.vt) {case VT_BOOL:

bValue = vtFld.boolVal == VARIANT_TRUE? true: false;break;

case VT_EMPTY:case VT_NULL:

bValue = false;break;

default:return FALSE;

}return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(LPCTSTR lpFieldName, COleCurrency& cyValue){

_variant_t vtFld;

try{

vtFld = m_pRecordset->Fields->GetItem(lpFieldName)->Value;switch(vtFld.vt) {case VT_CY:

cyValue = (CURRENCY)vtFld.cyVal;break;

case VT_EMPTY:case VT_NULL:

{cyValue = COleCurrency();cyValue.m_status = COleCurrency::null;}break;

default:return FALSE;

}return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(int nIndex, COleCurrency& cyValue){

_variant_t vtFld;_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

try

Page 300: Bioidentià - Il Progetto Ottico

{vtFld = m_pRecordset->Fields->GetItem(vtIndex)->Value;switch(vtFld.vt) {case VT_CY:

cyValue = (CURRENCY)vtFld.cyVal;break;

case VT_EMPTY:case VT_NULL:

{cyValue = COleCurrency();cyValue.m_status = COleCurrency::null;}break;

default:return FALSE;

}return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(LPCTSTR lpFieldName, _variant_t& vtValue){

try{

vtValue = m_pRecordset->Fields->GetItem(lpFieldName)->Value;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::GetFieldValue(int nIndex, _variant_t& vtValue){

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

try{

vtValue = m_pRecordset->Fields->GetItem(vtIndex)->Value;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::IsFieldNull(LPCTSTR lpFieldName){

_variant_t vtFld;

Page 301: Bioidentià - Il Progetto Ottico

try{

vtFld = m_pRecordset->Fields->GetItem(lpFieldName)->Value;return vtFld.vt == VT_NULL;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::IsFieldNull(int nIndex){

_variant_t vtFld;_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

try{

vtFld = m_pRecordset->Fields->GetItem(vtIndex)->Value;return vtFld.vt == VT_NULL;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::IsFieldEmpty(LPCTSTR lpFieldName){

_variant_t vtFld;

try{

vtFld = m_pRecordset->Fields->GetItem(lpFieldName)->Value;return vtFld.vt == VT_EMPTY || vtFld.vt == VT_NULL;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::IsFieldEmpty(int nIndex){

_variant_t vtFld;_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

try{

vtFld = m_pRecordset->Fields->GetItem(vtIndex)->Value;return vtFld.vt == VT_EMPTY || vtFld.vt == VT_NULL;

}

Page 302: Bioidentià - Il Progetto Ottico

catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::SetFieldEmpty(LPCTSTR lpFieldName){

_variant_t vtFld;vtFld.vt = VT_EMPTY;

return PutFieldValue(lpFieldName, vtFld);}

BOOL CADORecordset::SetFieldEmpty(int nIndex){

_variant_t vtFld;vtFld.vt = VT_EMPTY;

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

return PutFieldValue(vtIndex, vtFld);}

DWORD CADORecordset::GetRecordCount(){

DWORD nRows = 0;

nRows = m_pRecordset->GetRecordCount();

if(nRows == -1){

nRows = 0;if(m_pRecordset->EndOfFile != VARIANT_TRUE)

m_pRecordset->MoveFirst();

while(m_pRecordset->EndOfFile != VARIANT_TRUE){

nRows++;m_pRecordset->MoveNext();

}if(nRows > 0)

m_pRecordset->MoveFirst();}

return nRows;}

BOOL CADORecordset::IsOpen(){

if(m_pRecordset != NULL && IsConnectionOpen())return m_pRecordset->GetState() != adStateClosed;

return FALSE;}

void CADORecordset::Close(){

Page 303: Bioidentià - Il Progetto Ottico

if(IsOpen()){

if (m_nEditStatus != dbEditNone) CancelUpdate();

m_pRecordset->PutSort(_T(""));m_pRecordset->Close();

}}

BOOL CADODatabase::Execute(LPCTSTR lpstrExec){

ASSERT(m_pConnection != NULL);ASSERT(strcmp(lpstrExec, _T("")) != 0);_variant_t vRecords;

m_nRecordsAffected = 0;

try{

m_pConnection->CursorLocation = adUseClient;m_pConnection->Execute(_bstr_t(lpstrExec), &vRecords,

adExecuteNoRecords);m_nRecordsAffected = vRecords.iVal;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::RecordBinding(CADORecordBinding &pAdoRecordBinding){

HRESULT hr;m_pRecBinding = NULL;

//Open the binding interface.if(FAILED(hr = m_pRecordset->QueryInterface(__uuidof(IADORecordBinding),

(LPVOID*)&m_pRecBinding ))){

_com_issue_error(hr);return FALSE;

}

//Bind the recordset to classif(FAILED(hr = m_pRecBinding->BindToRecordset(&pAdoRecordBinding))){

_com_issue_error(hr);return FALSE;

}return TRUE;

}

BOOL CADORecordset::GetFieldInfo(LPCTSTR lpFieldName, CADOFieldInfo* fldInfo){

FieldPtr pField = m_pRecordset->Fields->GetItem(lpFieldName);

return GetFieldInfo(pField, fldInfo);}

Page 304: Bioidentià - Il Progetto Ottico

BOOL CADORecordset::GetFieldInfo(int nIndex, CADOFieldInfo* fldInfo){

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

FieldPtr pField = m_pRecordset->Fields->GetItem(vtIndex);

return GetFieldInfo(pField, fldInfo);}

BOOL CADORecordset::GetFieldInfo(FieldPtr pField, CADOFieldInfo* fldInfo){

memset(fldInfo, 0, sizeof(CADOFieldInfo));

strcpy(fldInfo->m_strName, (LPCTSTR)pField->GetName());fldInfo->m_lDefinedSize = pField->GetDefinedSize();fldInfo->m_nType = pField->GetType();fldInfo->m_lAttributes = pField->GetAttributes();if(!IsEof())

fldInfo->m_lSize = pField->GetActualSize();return TRUE;

}

BOOL CADORecordset::GetChunk(LPCTSTR lpFieldName, CString& strValue){

FieldPtr pField = m_pRecordset->Fields->GetItem(lpFieldName);

return GetChunk(pField, strValue);}

BOOL CADORecordset::GetChunk(int nIndex, CString& strValue){

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

FieldPtr pField = m_pRecordset->Fields->GetItem(vtIndex);

return GetChunk(pField, strValue);}

BOOL CADORecordset::GetChunk(FieldPtr pField, CString& strValue){

CString str = _T("");long lngSize, lngOffSet = 0;_variant_t varChunk;

lngSize = pField->ActualSize;

str.Empty();while(lngOffSet < lngSize){

try{

varChunk = pField->GetChunk(ChunkSize);

Page 305: Bioidentià - Il Progetto Ottico

str += varChunk.bstrVal;lngOffSet += ChunkSize;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

lngOffSet = 0;strValue = str;return TRUE;

}

BOOL CADORecordset::GetChunk(LPCTSTR lpFieldName, LPVOID lpData){

FieldPtr pField = m_pRecordset->Fields->GetItem(lpFieldName);

return GetChunk(pField, lpData);}

BOOL CADORecordset::GetChunk(int nIndex, LPVOID lpData){

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

FieldPtr pField = m_pRecordset->Fields->GetItem(vtIndex);

return GetChunk(pField, lpData);}

BOOL CADORecordset::GetChunk(FieldPtr pField, LPVOID lpData){

long lngSize, lngOffSet = 0;_variant_t varChunk; UCHAR chData;HRESULT hr;long lBytesCopied = 0;

lngSize = pField->ActualSize;

while(lngOffSet < lngSize){

try{

varChunk = pField->GetChunk(ChunkSize);

//Copy the data only upto the Actual Size of Field. for(long lIndex = 0; lIndex <= (ChunkSize - 1); lIndex++) { hr= SafeArrayGetElement(varChunk.parray, &lIndex, &chData); if(SUCCEEDED(hr)) { //Take BYTE by BYTE and advance Memory Location //hr = SafeArrayPutElement((SAFEARRAY FAR*)lpData, &lBytesCopied ,&chData);

((UCHAR*)lpData)[lBytesCopied] = chData; lBytesCopied++; }

Page 306: Bioidentià - Il Progetto Ottico

else break; }

lngOffSet += ChunkSize;}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

lngOffSet = 0;return TRUE;

}

BOOL CADORecordset::AppendChunk(LPCTSTR lpFieldName, LPVOID lpData, UINT nBytes){

FieldPtr pField = m_pRecordset->Fields->GetItem(lpFieldName);

return AppendChunk(pField, lpData, nBytes);}

BOOL CADORecordset::AppendChunk(int nIndex, LPVOID lpData, UINT nBytes){

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

FieldPtr pField = m_pRecordset->Fields->GetItem(vtIndex);

return AppendChunk(pField, lpData, nBytes);}

BOOL CADORecordset::AppendChunk(FieldPtr pField, LPVOID lpData, UINT nBytes){

HRESULT hr;_variant_t varChunk;long lngOffset = 0;UCHAR chData;SAFEARRAY FAR *psa = NULL;SAFEARRAYBOUND rgsabound[1];

try{

//Create a safe array to store the array of BYTES rgsabound[0].lLbound = 0;rgsabound[0].cElements = nBytes;psa = SafeArrayCreate(VT_UI1,1,rgsabound);

while(lngOffset < (long)nBytes){

chData = ((UCHAR*)lpData)[lngOffset];hr = SafeArrayPutElement(psa, &lngOffset, &chData);

if(FAILED(hr))return FALSE;

lngOffset++;

Page 307: Bioidentià - Il Progetto Ottico

}lngOffset = 0;

//Assign the Safe array to a variant. varChunk.vt = VT_ARRAY|VT_UI1;varChunk.parray = psa;

hr = pField->AppendChunk(varChunk);

if(SUCCEEDED(hr)) return TRUE;}catch(_com_error &e){

dump_com_error(e);return FALSE;

}

return FALSE;}

CString CADORecordset::GetString(LPCTSTR lpCols, LPCTSTR lpRows, LPCTSTR lpNull, long numRows){

_bstr_t varOutput;_bstr_t varNull("");_bstr_t varCols("\t");_bstr_t varRows("\r");

if(strlen(lpCols) != 0)varCols = _bstr_t(lpCols);

if(strlen(lpRows) != 0)varRows = _bstr_t(lpRows);

if(numRows == 0)numRows =(long)GetRecordCount();

varOutput = m_pRecordset->GetString(adClipString, numRows, varCols, varRows, varNull);

return (LPCTSTR)varOutput;}

CString IntToStr(int nVal){

CString strRet;char buff[10];

itoa(nVal, buff, 10);strRet = buff;return strRet;

}

CString LongToStr(long lVal){

CString strRet;char buff[20];

ltoa(lVal, buff, 10);strRet = buff;return strRet;

}

Page 308: Bioidentià - Il Progetto Ottico

CString ULongToStr(unsigned long ulVal){

CString strRet;char buff[20];

ultoa(ulVal, buff, 10);strRet = buff;return strRet;

}

CString DblToStr(double dblVal, int ndigits){

CString strRet;char buff[50];

_gcvt(dblVal, ndigits, buff);strRet = buff;return strRet;

}

CString DblToStr(float fltVal){

CString strRet = _T("");char buff[50];

_gcvt(fltVal, 10, buff);strRet = buff;return strRet;

}

void CADORecordset::Edit(){

m_nEditStatus = dbEdit;}

BOOL CADORecordset::AddNew(){

m_nEditStatus = dbEditNone;if(m_pRecordset->AddNew() != S_OK)

return FALSE;

m_nEditStatus = dbEditNew;return TRUE;

}

BOOL CADORecordset::AddNew(CADORecordBinding &pAdoRecordBinding){

try{

if(m_pRecBinding->AddNew(&pAdoRecordBinding) != S_OK){

return FALSE;}else{

m_pRecBinding->Update(&pAdoRecordBinding);return TRUE;

}

Page 309: Bioidentià - Il Progetto Ottico

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::Update(){

BOOL bret = TRUE;

if(m_nEditStatus != dbEditNone){

try{

if(m_pRecordset->Update() != S_OK)bret = FALSE;

}catch(_com_error &e){

dump_com_error(e);bret = FALSE;

}

if(!bret)m_pRecordset->CancelUpdate();

m_nEditStatus = dbEditNone;}return bret;

}

void CADORecordset::CancelUpdate(){

m_pRecordset->CancelUpdate();m_nEditStatus = dbEditNone;

}

BOOL CADORecordset::SetFieldValue(int nIndex, CString strValue){

_variant_t vtFld;_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

if(!strValue.IsEmpty())vtFld.vt = VT_BSTR;

elsevtFld.vt = VT_NULL;

//Corrected by Giles Forster 10/03/2001vtFld.bstrVal = strValue.AllocSysString();

return PutFieldValue(vtIndex, vtFld);}

BOOL CADORecordset::SetFieldValue(LPCTSTR lpFieldName, CString strValue){

_variant_t vtFld;

Page 310: Bioidentià - Il Progetto Ottico

if(!strValue.IsEmpty())vtFld.vt = VT_BSTR;

elsevtFld.vt = VT_NULL;

//Corrected by Giles Forster 10/03/2001vtFld.bstrVal = strValue.AllocSysString();

return PutFieldValue(lpFieldName, vtFld);}

BOOL CADORecordset::SetFieldValue(int nIndex, int nValue){

_variant_t vtFld;

vtFld.vt = VT_I2;vtFld.iVal = nValue;

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

return PutFieldValue(vtIndex, vtFld);}

BOOL CADORecordset::SetFieldValue(LPCTSTR lpFieldName, int nValue){

_variant_t vtFld;

vtFld.vt = VT_I2;vtFld.iVal = nValue;

return PutFieldValue(lpFieldName, vtFld);}

BOOL CADORecordset::SetFieldValue(int nIndex, long lValue){

_variant_t vtFld;vtFld.vt = VT_I4;vtFld.lVal = lValue;

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

return PutFieldValue(vtIndex, vtFld);

}

BOOL CADORecordset::SetFieldValue(LPCTSTR lpFieldName, long lValue){

_variant_t vtFld;vtFld.vt = VT_I4;vtFld.lVal = lValue;

return PutFieldValue(lpFieldName, vtFld);}

BOOL CADORecordset::SetFieldValue(int nIndex, unsigned long ulValue)

Page 311: Bioidentià - Il Progetto Ottico

{_variant_t vtFld;vtFld.vt = VT_UI4;vtFld.ulVal = ulValue;

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

return PutFieldValue(vtIndex, vtFld);

}

BOOL CADORecordset::SetFieldValue(LPCTSTR lpFieldName, unsigned long ulValue){

_variant_t vtFld;vtFld.vt = VT_UI4;vtFld.ulVal = ulValue;

return PutFieldValue(lpFieldName, vtFld);}

BOOL CADORecordset::SetFieldValue(int nIndex, double dblValue){

_variant_t vtFld;vtFld.vt = VT_R8;vtFld.dblVal = dblValue;

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

return PutFieldValue(vtIndex, vtFld);}

BOOL CADORecordset::SetFieldValue(LPCTSTR lpFieldName, double dblValue){

_variant_t vtFld;vtFld.vt = VT_R8;vtFld.dblVal = dblValue;

return PutFieldValue(lpFieldName, vtFld);}

BOOL CADORecordset::SetFieldValue(int nIndex, COleDateTime time){

_variant_t vtFld;vtFld.vt = VT_DATE;vtFld.date = time;

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

return PutFieldValue(vtIndex, vtFld);}

BOOL CADORecordset::SetFieldValue(LPCTSTR lpFieldName, COleDateTime time){

Page 312: Bioidentià - Il Progetto Ottico

_variant_t vtFld;vtFld.vt = VT_DATE;vtFld.date = time;

return PutFieldValue(lpFieldName, vtFld);}

BOOL CADORecordset::SetFieldValue(int nIndex, bool bValue){

_variant_t vtFld;vtFld.vt = VT_BOOL;vtFld.boolVal = bValue;

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

return PutFieldValue(vtIndex, vtFld);}

BOOL CADORecordset::SetFieldValue(LPCTSTR lpFieldName, bool bValue){

_variant_t vtFld;vtFld.vt = VT_BOOL;vtFld.boolVal = bValue;

return PutFieldValue(lpFieldName, vtFld);}

BOOL CADORecordset::SetFieldValue(int nIndex, COleCurrency cyValue){

if(cyValue.m_status == COleCurrency::invalid)return FALSE;

_variant_t vtFld;

vtFld.vt = VT_CY;vtFld.cyVal = cyValue.m_cur;

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

return PutFieldValue(vtIndex, vtFld);}

BOOL CADORecordset::SetFieldValue(LPCTSTR lpFieldName, COleCurrency cyValue){

if(cyValue.m_status == COleCurrency::invalid)return FALSE;

_variant_t vtFld;

vtFld.vt = VT_CY;vtFld.cyVal = cyValue.m_cur;

return PutFieldValue(lpFieldName, vtFld);

Page 313: Bioidentià - Il Progetto Ottico

}

BOOL CADORecordset::SetFieldValue(int nIndex, _variant_t vtValue){

_variant_t vtIndex;

vtIndex.vt = VT_I2;vtIndex.iVal = nIndex;

return PutFieldValue(vtIndex, vtValue);}

BOOL CADORecordset::SetFieldValue(LPCTSTR lpFieldName, _variant_t vtValue){

return PutFieldValue(lpFieldName, vtValue);}

BOOL CADORecordset::SetBookmark(){

if(m_varBookmark.vt != VT_EMPTY){

m_pRecordset->Bookmark = m_varBookmark;return TRUE;

}return FALSE;

}

BOOL CADORecordset::Delete(){

if(m_pRecordset->Delete(adAffectCurrent) != S_OK)return FALSE;

if(m_pRecordset->Update() != S_OK)return FALSE;

m_nEditStatus = dbEditNone;return TRUE;

}

BOOL CADORecordset::Find(LPCTSTR lpFind, int nSearchDirection){

m_strFind = lpFind;m_nSearchDirection = nSearchDirection;

ASSERT(!m_strFind.IsEmpty());

if(m_nSearchDirection == searchForward){

m_pRecordset->Find(_bstr_t(m_strFind), 0, adSearchForward, "");if(!IsEof()){

m_varBookFind = m_pRecordset->Bookmark;return TRUE;

}}else if(m_nSearchDirection == searchBackward){

m_pRecordset->Find(_bstr_t(m_strFind), 0, adSearchBackward, "");if(!IsBof()){

Page 314: Bioidentià - Il Progetto Ottico

m_varBookFind = m_pRecordset->Bookmark;return TRUE;

}}else{

TRACE("Unknown parameter. %d", nSearchDirection);m_nSearchDirection = searchForward;

}return FALSE;

}

BOOL CADORecordset::FindFirst(LPCTSTR lpFind){

m_pRecordset->MoveFirst();return Find(lpFind);

}

BOOL CADORecordset::FindNext(){

if(m_nSearchDirection == searchForward){

m_pRecordset->Find(_bstr_t(m_strFind), 1, adSearchForward, m_varBookFind);

if(!IsEof()){

m_varBookFind = m_pRecordset->Bookmark;return TRUE;

}}else{

m_pRecordset->Find(_bstr_t(m_strFind), 1, adSearchBackward, m_varBookFind);

if(!IsBof()){

m_varBookFind = m_pRecordset->Bookmark;return TRUE;

}}return FALSE;

}

BOOL CADORecordset::PutFieldValue(LPCTSTR lpFieldName, _variant_t vtFld){

if(m_nEditStatus == dbEditNone)return FALSE;

try{

m_pRecordset->Fields->GetItem(lpFieldName)->Value = vtFld; return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::PutFieldValue(_variant_t vtIndex, _variant_t vtFld)

Page 315: Bioidentià - Il Progetto Ottico

{if(m_nEditStatus == dbEditNone)

return FALSE;

try{

m_pRecordset->Fields->GetItem(vtIndex)->Value = vtFld;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::Clone(CADORecordset &pRs){

try{

pRs.m_pRecordset = m_pRecordset->Clone(adLockUnspecified);return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::SetFilter(LPCTSTR strFilter){

ASSERT(IsOpen());

try{

m_pRecordset->PutFilter(strFilter);return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::SetSort(LPCTSTR strCriteria){

ASSERT(IsOpen());

try{

m_pRecordset->PutSort(strCriteria);return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

Page 316: Bioidentià - Il Progetto Ottico

BOOL CADORecordset::SaveAsXML(LPCTSTR lpstrXMLFile){

HRESULT hr;

ASSERT(IsOpen());

try{

hr = m_pRecordset->Save(lpstrXMLFile, adPersistXML);return hr == S_OK;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}return TRUE;

}

BOOL CADORecordset::OpenXML(LPCTSTR lpstrXMLFile){

HRESULT hr = S_OK;

if(IsOpen())Close();

try{

hr = m_pRecordset->Open(lpstrXMLFile, "Provider=MSPersist;", adOpenForwardOnly, adLockOptimistic, adCmdFile);

return hr == S_OK;}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADORecordset::Execute(CADOCommand* pAdoCommand){

if(IsOpen())Close();

ASSERT(!pAdoCommand->GetText().IsEmpty());try{

m_pConnection->CursorLocation = adUseClient;m_pRecordset = pAdoCommand->GetCommand()->Execute(NULL, NULL,

pAdoCommand->GetType());return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

void CADORecordset::dump_com_error(_com_error &e){

CString ErrorStr;

Page 317: Bioidentià - Il Progetto Ottico

_bstr_t bstrSource(e.Source());_bstr_t bstrDescription(e.Description());ErrorStr.Format( "CADORecordset Error\n\tCode = %08lx\n\tCode meaning =

%s\n\tSource = %s\n\tDescription = %s\n",e.Error(), e.ErrorMessage(), (LPCSTR)bstrSource,

(LPCSTR)bstrDescription );m_strLastError = _T("Query = " + GetQuery() + '\n' + ErrorStr);m_dwLastError = e.Error();#ifdef _DEBUG

AfxMessageBox( ErrorStr, MB_OK | MB_ICONERROR );#endif

}

/////////////////////////////////////////////////////////// CADOCommad Class//

CADOCommand::CADOCommand(CADODatabase* pAdoDatabase, CString strCommandText, int nCommandType){

m_pCommand = NULL;m_pCommand.CreateInstance(__uuidof(Command));m_strCommandText = strCommandText;m_pCommand->CommandText = m_strCommandText.AllocSysString();m_nCommandType = nCommandType;m_pCommand->CommandType = (CommandTypeEnum)m_nCommandType;m_pCommand->ActiveConnection = pAdoDatabase->GetActiveConnection();m_nRecordsAffected = 0;

}

BOOL CADOCommand::AddParameter(CADOParameter* pAdoParameter){

ASSERT(pAdoParameter->GetParameter() != NULL);

try{

m_pCommand->Parameters->Append(pAdoParameter->GetParameter());return TRUE;

}catch(_com_error& e){

dump_com_error(e);return FALSE;

}}

BOOL CADOCommand::AddParameter(CString strName, int nType, int nDirection, long lSize, int nValue){

_variant_t vtValue;

vtValue.vt = VT_I2;vtValue.iVal = nValue;

return AddParameter(strName, nType, nDirection, lSize, vtValue);}

Page 318: Bioidentià - Il Progetto Ottico

BOOL CADOCommand::AddParameter(CString strName, int nType, int nDirection, long lSize, long lValue){

_variant_t vtValue;

vtValue.vt = VT_I4;vtValue.lVal = lValue;

return AddParameter(strName, nType, nDirection, lSize, vtValue);}

BOOL CADOCommand::AddParameter(CString strName, int nType, int nDirection, long lSize, double dblValue, int nPrecision, int nScale){

_variant_t vtValue;

vtValue.vt = VT_R8;vtValue.dblVal = dblValue;

return AddParameter(strName, nType, nDirection, lSize, vtValue, nPrecision, nScale);}

BOOL CADOCommand::AddParameter(CString strName, int nType, int nDirection, long lSize, CString strValue){

_variant_t vtValue;

vtValue.vt = VT_BSTR;vtValue.bstrVal = strValue.AllocSysString();

return AddParameter(strName, nType, nDirection, lSize, vtValue);}

BOOL CADOCommand::AddParameter(CString strName, int nType, int nDirection, long lSize, COleDateTime time){

_variant_t vtValue;

vtValue.vt = VT_DATE;vtValue.date = time;

return AddParameter(strName, nType, nDirection, lSize, vtValue);}

BOOL CADOCommand::AddParameter(CString strName, int nType, int nDirection, long lSize, _variant_t vtValue, int nPrecision, int nScale){

try{

_ParameterPtr pParam = m_pCommand->CreateParameter(strName.AllocSysString(), (DataTypeEnum)nType, (ParameterDirectionEnum)nDirection, lSize, vtValue);

pParam->PutPrecision(nPrecision);pParam->PutNumericScale(nScale);m_pCommand->Parameters->Append(pParam);

Page 319: Bioidentià - Il Progetto Ottico

return TRUE;}catch(_com_error& e){

dump_com_error(e);return FALSE;

}}

void CADOCommand::SetText(CString strCommandText){

ASSERT(!strCommandText.IsEmpty());

m_strCommandText = strCommandText;m_pCommand->CommandText = m_strCommandText.AllocSysString();

}

void CADOCommand::SetType(int nCommandType){

m_nCommandType = nCommandType;m_pCommand->CommandType = (CommandTypeEnum)m_nCommandType;

}

BOOL CADOCommand::Execute(){

_variant_t vRecords;m_nRecordsAffected = 0;try{

m_pCommand->Execute(&vRecords, NULL, adCmdStoredProc);m_nRecordsAffected = vRecords.iVal;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

void CADOCommand::dump_com_error(_com_error &e){

CString ErrorStr;

_bstr_t bstrSource(e.Source());_bstr_t bstrDescription(e.Description());ErrorStr.Format( "CADOCommand Error\n\tCode = %08lx\n\tCode meaning = %s\

n\tSource = %s\n\tDescription = %s\n",e.Error(), e.ErrorMessage(), (LPCSTR)bstrSource,

(LPCSTR)bstrDescription );m_strLastError = ErrorStr;m_dwLastError = e.Error();#ifdef _DEBUG

AfxMessageBox(ErrorStr, MB_OK | MB_ICONERROR);#endif

}

/////////////////////////////////////////////////////////

Page 320: Bioidentià - Il Progetto Ottico

// CADOParameter Class//

CADOParameter::CADOParameter(int nType, long lSize, int nDirection, CString strName){

m_pParameter = NULL;m_pParameter.CreateInstance(__uuidof(Parameter));m_strName = _T("");m_pParameter->Direction = (ParameterDirectionEnum)nDirection;m_strName = strName;m_pParameter->Name = m_strName.AllocSysString();m_pParameter->Type = (DataTypeEnum)nType;m_pParameter->Size = lSize;m_nType = nType;

}

BOOL CADOParameter::SetValue(int nValue){

_variant_t vtVal;

ASSERT(m_pParameter != NULL);

vtVal.vt = VT_I2;vtVal.iVal = nValue;

try{

if(m_pParameter->Size == 0)m_pParameter->Size = sizeof(int);

m_pParameter->Value = vtVal;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADOParameter::SetValue(long lValue){

_variant_t vtVal;

ASSERT(m_pParameter != NULL);

vtVal.vt = VT_I4;vtVal.lVal = lValue;

try{

if(m_pParameter->Size == 0)m_pParameter->Size = sizeof(long);

m_pParameter->Value = vtVal;return TRUE;

}catch(_com_error &e){

dump_com_error(e);

Page 321: Bioidentià - Il Progetto Ottico

return FALSE;}

}

BOOL CADOParameter::SetValue(double dblValue){

_variant_t vtVal;

ASSERT(m_pParameter != NULL);

vtVal.vt = VT_R8;vtVal.dblVal = dblValue;

try{

if(m_pParameter->Size == 0)m_pParameter->Size = sizeof(double);

m_pParameter->Value = vtVal;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADOParameter::SetValue(CString strValue){

_variant_t vtVal;

ASSERT(m_pParameter != NULL);

if(!strValue.IsEmpty())vtVal.vt = VT_BSTR;

elsevtVal.vt = VT_NULL;

//Corrected by Giles Forster 10/03/2001vtVal.bstrVal = strValue.AllocSysString();

try{

if(m_pParameter->Size == 0)m_pParameter->Size = sizeof(char) * strValue.GetLength();

m_pParameter->Value = vtVal;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADOParameter::SetValue(COleDateTime time){

_variant_t vtVal;

ASSERT(m_pParameter != NULL);

Page 322: Bioidentià - Il Progetto Ottico

vtVal.vt = VT_DATE;vtVal.date = time;

try{

if(m_pParameter->Size == 0)m_pParameter->Size = sizeof(DATE);

m_pParameter->Value = vtVal;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADOParameter::SetValue(_variant_t vtValue){

ASSERT(m_pParameter != NULL);

try{

if(m_pParameter->Size == 0)m_pParameter->Size = sizeof(VARIANT);

m_pParameter->Value = vtValue;return TRUE;

}catch(_com_error &e){

dump_com_error(e);return FALSE;

}}

BOOL CADOParameter::GetValue(int& nValue){

_variant_t vtVal;int nVal = 0;

try{

vtVal = m_pParameter->Value;

switch(vtVal.vt){case VT_BOOL:

nVal = vtVal.boolVal;break;

case VT_I2:case VT_UI1:

nVal = vtVal.iVal;break;

case VT_INT:nVal = vtVal.intVal;break;

case VT_NULL:case VT_EMPTY:

Page 323: Bioidentià - Il Progetto Ottico

nVal = 0;break;

default:nVal = vtVal.iVal;

}nValue = nVal;return TRUE;

}catch(_com_error& e){

dump_com_error(e);return FALSE;

}}

BOOL CADOParameter::GetValue(long& lValue){

_variant_t vtVal;long lVal = 0;

try{

vtVal = m_pParameter->Value;if(vtVal.vt != VT_NULL && vtVal.vt != VT_EMPTY)

lVal = vtVal.lVal;lValue = lVal;return TRUE;

}catch(_com_error& e){

dump_com_error(e);return FALSE;

}}

BOOL CADOParameter::GetValue(double& dbValue){

_variant_t vtVal;double dblVal;try{

vtVal = m_pParameter->Value;switch(vtVal.vt){case VT_R4:

dblVal = vtVal.fltVal;break;

case VT_R8:dblVal = vtVal.dblVal;break;

case VT_DECIMAL://Corrected by José Carlos Martínez GalándblVal = vtVal.decVal.Lo32;dblVal *= (vtVal.decVal.sign == 128)? -1 : 1;dblVal /= pow(10, vtVal.decVal.scale); break;

case VT_UI1:dblVal = vtVal.iVal;break;

case VT_I2:case VT_I4:

dblVal = vtVal.lVal;

Page 324: Bioidentià - Il Progetto Ottico

break;case VT_INT:

dblVal = vtVal.intVal;break;

case VT_NULL:case VT_EMPTY:

dblVal = 0;break;

default:dblVal = 0;

}dbValue = dblVal;return TRUE;

}catch(_com_error& e){

dump_com_error(e);return FALSE;

}}

BOOL CADOParameter::GetValue(CString& strValue, CString strDateFormat){

_variant_t vtVal;CString strVal = _T("");

try{

vtVal = m_pParameter->Value;switch(vtVal.vt) {case VT_R4:

strVal = DblToStr(vtVal.fltVal);break;

case VT_R8:strVal = DblToStr(vtVal.dblVal);break;

case VT_BSTR:strVal = vtVal.bstrVal;break;

case VT_I2:case VT_UI1:

strVal = IntToStr(vtVal.iVal);break;

case VT_INT:strVal = IntToStr(vtVal.intVal);break;

case VT_I4:strVal = LongToStr(vtVal.lVal);break;

case VT_DECIMAL:{//Corrected by José Carlos Martínez Galándouble val = vtVal.decVal.Lo32;val *= (vtVal.decVal.sign == 128)? -1 : 1;val /= pow(10, vtVal.decVal.scale); strVal = DblToStr(val);}break;

case VT_DATE:{

COleDateTime dt(vtVal);

Page 325: Bioidentià - Il Progetto Ottico

if(strDateFormat.IsEmpty())strDateFormat = _T("%Y-%m-%d %H:%M:%S");

strVal = dt.Format(strDateFormat);}break;

case VT_EMPTY:case VT_NULL:

strVal.Empty();break;

default:strVal.Empty();return FALSE;

}strValue = strVal;return TRUE;

}catch(_com_error& e){

dump_com_error(e);return FALSE;

}}

BOOL CADOParameter::GetValue(COleDateTime& time){

_variant_t vtVal;

try{

vtVal = m_pParameter->Value;switch(vtVal.vt) {case VT_DATE:

{COleDateTime dt(vtVal);time = dt;

}break;

case VT_EMPTY:case VT_NULL:

time.SetStatus(COleDateTime::null);break;

default:return FALSE;

}return TRUE;

}catch(_com_error& e){

dump_com_error(e);return FALSE;

}}

BOOL CADOParameter::GetValue(_variant_t& vtValue){

try{

vtValue = m_pParameter->Value;return TRUE;

}

Page 326: Bioidentià - Il Progetto Ottico

catch(_com_error& e){

dump_com_error(e);return FALSE;

}}

void CADOParameter::dump_com_error(_com_error &e){

CString ErrorStr;

_bstr_t bstrSource(e.Source());_bstr_t bstrDescription(e.Description());ErrorStr.Format( "CADOParameter Error\n\tCode = %08lx\n\tCode meaning =

%s\n\tSource = %s\n\tDescription = %s\n",e.Error(), e.ErrorMessage(), (LPCSTR)bstrSource,

(LPCSTR)bstrDescription );m_strLastError = ErrorStr;m_dwLastError = e.Error();#ifdef _DEBUG

AfxMessageBox(ErrorStr, MB_OK | MB_ICONERROR);#endif

}

IMPLEMENT_DYNAMIC(CADOException, CException)

CADOException::CADOException(int nCause, CString strErrorString) : CException(TRUE){

m_nCause = nCause;m_strErrorString = strErrorString;

}

CADOException::~CADOException(){

}

int CADOException::GetError(int nADOError){

switch (nADOError){case noError:

return CADOException::noError;break;

default:return CADOException::Unknown;

}

}

void AfxThrowADOException(int nADOError, CString strErrorString){

throw new CADOException(nADOError, strErrorString);}

Page 327: Bioidentià - Il Progetto Ottico

La creazione dei BARCODE

In alcune procedure vengono usate le codifiche a BARCODE per la creazione delle etichette.Di questi ne esistono diversi formati anche se quelli che possono trattatare sia caratteri che numeri sono pochi come ad esempio il CODE 39.La seguente classe gestisce questo formato.

// Code39.cpp: implementation of the CCode39 class.//////////////////////////////////////////////////////////////////////////

#include "stdafx.h"#include "Code39.h"

//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////

CCode39::CCode39(){

// code 39m_nSymbology = CODE39;

}

CCode39::~CCode39(){

}

//////////////////////////////////////////////////////////////////////////////////////// Name:// DrawBitmap()//// Description:// draws a barcode using the previously loaded data//// Arguments:// none//// Return:// void//// Called by:// public class interface//////////////////////////////////////////////////////////////////////////////////////

void CCode39::DrawBitmap(){

int i;CString csCurrentPattern;

// draw start character, an asterisk

Page 328: Bioidentià - Il Progetto Ottico

DrawPattern(RetrievePattern('*'));

// draw each character in the messagefor (i=0;i<m_csMessage.GetLength();i++)

DrawPattern(RetrievePattern(m_csMessage.GetAt(i)));

// draw stop character, also an asteriskDrawPattern(RetrievePattern('*'));

return;}

//////////////////////////////////////////////////////////////////////////////////////// Name:// DrawPattern()//// Description:// draws the passed character pattern at the end of the barcode//// Arguments:// CString csPattern - the bar pattern to draw//// Return:// void//// Called by:// CRationalCodabar::DrawBitmap()//////////////////////////////////////////////////////////////////////////////////////

void CCode39::DrawPattern( CString csPattern ){

int i,nXPixel,nYPixel,nTempWidth;CDC oDC;

// attach to the device contextoDC.Attach(m_hDC);

// initialize X pixel valuenXPixel = m_nStartingXPixel;

for (i=0;i<csPattern.GetLength();i++){

// decide if narrow or wide barif (csPattern.GetAt(i)=='n')

nTempWidth = m_nNarrowBarPixelWidth;else

nTempWidth = m_nWideBarPixelWidth;

// X value for loopfor

(nXPixel=m_nStartingXPixel;nXPixel<m_nStartingXPixel+nTempWidth;nXPixel++){

// Y value for loopfor

(nYPixel=m_nStartingYPixel;nYPixel<m_nStartingYPixel+m_nPixelHeight;nYPixel++){

// if this is a barif (i%2==0)

Page 329: Bioidentià - Il Progetto Ottico

oDC.SetPixelV(nXPixel,nYPixel,COLORBLACK);else

oDC.SetPixelV(nXPixel,nYPixel,COLORWHITE);}

}

// advance the starting positionm_nStartingXPixel+= nTempWidth;

}

// detach from the device contextoDC.Detach();

return;}

//////////////////////////////////////////////////////////////////////////////////////// Name:// RetrievePattern()//// Description:// retrieves the bar pattern for a given character//// Arguments:// char cInputCharacter - the input character to get the bar pattern for//// Return:// CString - the bar pattern for the input character//// Called by:// CRationalCodabar::DrawBitmap()//////////////////////////////////////////////////////////////////////////////////////

CString CCode39::RetrievePattern(char c){

CString csCharPattern;

switch (c){

case '1':csCharPattern = "wnnwnnnnwn";break;

case '2':csCharPattern = "nnwwnnnnwn";break;

case '3':csCharPattern = "wnwwnnnnnn";break;

case '4':csCharPattern = "nnnwwnnnwn";break;

case '5':csCharPattern = "wnnwwnnnnn";break;

case '6':csCharPattern = "nnwwwnnnnn";break;

Page 330: Bioidentià - Il Progetto Ottico

case '7':csCharPattern = "nnnwnnwnwn";break;

case '8':csCharPattern = "wnnwnnwnnn";break;

case '9':csCharPattern = "nnwwnnwnnn";break;

case '0':csCharPattern = "nnnwwnwnnn";break;

case 'A':csCharPattern = "wnnnnwnnwn";break;

case 'B':csCharPattern = "nnwnnwnnwn";break;

case 'C':csCharPattern = "wnwnnwnnnn";break;

case 'D':csCharPattern = "nnnnwwnnwn";break;

case 'E':csCharPattern = "wnnnwwnnnn";break;

case 'F':csCharPattern = "nnwnwwnnnn";break;

case 'G':csCharPattern = "nnnnnwwnwn";break;

case 'H':csCharPattern = "wnnnnwwnnn";break;

case 'I':csCharPattern = "nnwnnwwnnn";break;

case 'J':csCharPattern = "nnnnwwwnnn";break;

case 'K':csCharPattern = "wnnnnnnwwn";break;

case 'L':csCharPattern = "nnwnnnnwwn";break;

case 'M':csCharPattern = "wnwnnnnwnn";break;

case 'N':csCharPattern = "nnnnwnnwwn";break;

case 'O':csCharPattern = "wnnnwnnwnn";break;

case 'P':csCharPattern = "nnwnwnnwnn";break;

case 'Q':csCharPattern = "nnnnnnwwwn";

Page 331: Bioidentià - Il Progetto Ottico

break;case 'R':

csCharPattern = "wnnnnnwwnn";break;

case 'S':csCharPattern = "nnwnnnwwnn";break;

case 'T':csCharPattern = "nnnnwnwwnn";break;

case 'U':csCharPattern = "wwnnnnnnwn";break;

case 'V':csCharPattern = "nwwnnnnnwn";break;

case 'W':csCharPattern = "wwwnnnnnnn";break;

case 'X':csCharPattern = "nwnnwnnnwn";break;

case 'Y':csCharPattern = "wwnnwnnnnn";break;

case 'Z':csCharPattern = "nwwnwnnnnn";break;

case '-':csCharPattern = "nwnnnnwnwn";break;

case '.':csCharPattern = "wwnnnnwnnn";break;

case ' ':csCharPattern = "nwwnnnwnnn";break;

case '*':csCharPattern = "nwnnwnwnnn";break;

case '$':csCharPattern = "nwnwnwnnnn";break;

case '/':csCharPattern = "nwnwnnnwnn";break;

case '+':csCharPattern = "nwnnnwnwnn";break;

case '%':csCharPattern = "nnnwnwnwnn";break;

}

return csCharPattern;}

//////////////////////////////////////////////////////////////////////////////////////// Name:// BitmapToClipboard()

Page 332: Bioidentià - Il Progetto Ottico

//// Description:// puts the specified bitmap on the clipboard//// Arguments:// none//// Return:// void//// Called by:// public class interface - called by users of the class//////////////////////////////////////////////////////////////////////////////////////

void CCode39::BitmapToClipboard(){

CDC memDC;CBitmap oBitmap;

memDC.CreateCompatibleDC(NULL);

m_hDC = memDC.GetSafeHdc();

// create compatible, correctly sized bitmap

oBitmap.CreateCompatibleBitmap(&memDC,m_nFinalBarcodePixelWidth,m_nPixelHeight);

// select our bitmap into the device contextCBitmap * oldbm = memDC.SelectObject(&oBitmap);

// turn area white - stock black bitmap is selected

memDC.BitBlt(0,0,m_nFinalBarcodePixelWidth,m_nPixelHeight,NULL,0,0,WHITENESS);

// draw bitmap into memory device contextDrawBitmap();

// put bitmap on clipboard::OpenClipboard(NULL);::EmptyClipboard();::SetClipboardData(CF_BITMAP, oBitmap.m_hObject);::CloseClipboard();

// deselect object out of device contextmemDC.SelectObject(oldbm);

// make sure bitmap not deleted with CBitmap objectoBitmap.Detach();

return;}

Il file di header :

// Code39.h: interface for the CCode39 class.//////////////////////////////////////////////////////////////////////////

#if !defined(AFX_CODE39_H__6FE17747_EADF_4E89_9DCF_7688B04897BC__INCLUDED_)

Page 333: Bioidentià - Il Progetto Ottico

#define AFX_CODE39_H__6FE17747_EADF_4E89_9DCF_7688B04897BC__INCLUDED_

#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000

#include "Barcode.h"

class CCode39 : public CBarcode {public:

void BitmapToClipboard();void DrawBitmap();CCode39();virtual ~CCode39();

private:void DrawPattern(CString csPattern);CString RetrievePattern( char c );

};

#endif // !defined(AFX_CODE39_H__6FE17747_EADF_4E89_9DCF_7688B04897BC__INCLUDED_)