UNIVERSITA’
DEGLI STUDI DI GENOVA
FACOLTA’ DI
INGEGNERIA

Corso di Laurea in Ingegneria
Elettronica
TESI DI
LAUREA
STUDIO E
REALIZZAZIONE DI TECNICHE PER IL RICONOSCIMENTO VOCALE
Relatore
: Chiar.mo Prof. Francesco
Curatelli
Studente
:
Lorenzo Banderali
Anno
accademico: 2002 – 2003
Capitolo 1 : Funzionamento di un sistema di riconoscimento vocale 8
1.1 Teorema del campionamento 8
1.2 Acquisizione del segnale 9
1.3 Metodi
di analisi del segnale 11
1.4 Passi della
tecnica PLP 12
1.5 Memoria associativa 15
1.6 Dinamic time
warping 17
1.7 Algoritmo
di programmazione dinamica 19
Capitolo 2
:Teoria ed algoritmi 20
2.1 Algoritmo Lloyd 21
2.2 Algoritmo K-Means 22
2.3 AlgoritmoVoronoi 22
Capitolo 3 : Ottimizzazione 26
Capitolo 4 : I programmi 29
4.1 Soluzioni principali e funzioni del programma 31
4.2 Programmi accessori 34
Capitolo 5 : I risultati 35
5.1 Risultati ottenuti tramite l’uso di Spear 47
Capitolo 6 : Conclusioni 63
Capitolo 7 :
Appendice 64
Bibliografia 110
Indice delle Tabelle e delle Figure
Capitolo
1 : Funzionamento di un
sistema di riconoscimento vocale
Figura 1a: campionamento del segnale di ingresso 8
Figura 1b: Sistema a due sorgenti per la limitazione del rumore 10
Figura 1c: Passi della tecnica PLP 14
Figura 1d: rappresentazione dello spazio di train e di test 16
Figura 1e: Percorso di normalizzazione. 18
Capitolo 2 : Teoria ed algoritmi
Figura 2.1a: spostamento dei vettori di riferimento 21
Figura 2.2c: ordinare tutti i punti in secondo x ascendente 22
Figura 2.2d: Dai primi due semi si genera il più semplice diagramma di Voronoi 24
Figura
2.2e: Generazione ed inserimento di una nuova linea bisettrice derivante
dalla considerazione del terzo punto e del primo 24
Figura
2.2f: individuazione delle intersezioni tra le rette e creazione di una
nuova retta bisettrice dell’angolo formato dalle prime due rette 25
Figura 2.2g: termine dell’algoritmo 25
Capitolo
3 : Ottimizzazione
Figura 3 a: Insieme di partenza 26
Figura 3 b: I punti neri sono stati disattivati 26
Figura 3 c: Punti rimasti 27
Capitolo
5 : I risultati
Figura 5 a: Lloyd fatrid = 50 modo XàV 35
Figura 5 b: k-means fatrid =
50 modo XàV 36
Figura 5 c: k-means fatrid =
10 modo XàV 37
Figura 5 d: k-means fatrid =
10 modo XàVàV* 38
Figura 5 f: Voronoi di k-means fatrid = 10 modo XàV 40
Figura 5 g: k-means fatrid = 100 modo XàV 41
Figura 5 h: k-means fatrid =
100 modo XàVàV* 42
Figura 5 i: k-means fatrid = 100 modo XàX*àV 43
Figura 5 l: Voronoi di k-means fatrid = 100 modo XàV 44
Figura 5 m: Voronoi di k-means fatrid = 100 modo XàVàV* 45
Figura 5 n: Voronoi di k-means fatrid = 100 modo XàX*àV 46
Tabella
5.1: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con Lloyd modo X à V 48
Grafico
5.1: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con Lloyd modo X à V 48
Tabella 5.2: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con Lloyd modo X à V à V* 49
Grafico 5.2: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con Lloyd modo X à V à V* 49
Tabella 5.3: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con Lloyd modo X à X* à V 50
Grafico 5.3: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con Lloyd modo X à X* à V 50
Tabella
5.4: Riconoscimento di file interni con tutte le sessioni di anco e
le sue riduzioni con Lloyd modo X à
V 51
Grafico 5.4: Riconoscimento di file interni con tutte le sessioni di anco e
le
sue riduzioni con Lloyd modo X à
V 51
Tabella 5.5: Riconoscimento di file interni con tutte le sessioni di anco e
le sue riduzioni con Lloyd modo X à V à V* 52
Grafico 5.5: Riconoscimento di file interni con tutte le sessioni di anco e
le sue riduzioni con Lloyd modo X à V à V* 52
Tabella 5.6: Riconoscimento di file interni con tutte le sessioni di anco e
le sue riduzioni con Lloyd modo X à X* à V 53
Grafico 5.6: Riconoscimento di file interni con tutte le sessioni di anco e
le sue riduzioni con Lloyd modo X à X* à V 53
Tabella 5.7: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con K-Means modo X à V 54
Tabella 5.8: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con K-means modo X à V à V* 54
Tabella 5.9: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con K-Means modo X à X* à V 55
Tabella 5.10: Riconoscimento di file interni con tutte le sessioni di anco
e le sue riduzioni con K-Means modo X à V 55
Tabella 5.11: Riconoscimento di file interni con tutte le sessioni di anco
e le sue riduzioni con K-Means modo X à V à V* 56
Tabella 5.12: Riconoscimento di file interni con tutte le sessioni di anco
e le sue riduzioni con K-Means modo X à
X* à
V 56
Tabella
5.13: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con Lloyd modo X à V 57
Tabella 5.14: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con Lloyd modo X à V à V* 57
Tabella 5.15: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con Lloyd modo X à X* à V 58
Tabella
5.16: Riconoscimento di file interni con tutte le sessioni di anco e
le sue riduzioni con Lloyd modo X à
V 58
Tabella 5.17: Riconoscimento di file interni con tutte le sessioni di anco e
le sue riduzioni con Lloyd modo X à V à V* 59
Tabella 5.18: Riconoscimento di file interni con tutte le sessioni di anco e
le sue riduzioni con Lloyd modo X à X* à V 59
Tabella 5.19: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con K-Means modo X à V 60
Tabella 5.20: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con K-means modo X à V à V* 60
Tabella 5.21: Riconoscimento di file interni con la sessione 1 di anco e le
sue riduzioni con K-Means modo X à X* à V 61
Tabella 5.22: Riconoscimento di file interni con tutte le sessioni di anco
e le sue riduzioni con K-Means modo X à V 61
Tabella 5.23: Riconoscimento di file interni con tutte le sessioni di anco
e le sue riduzioni con K-Means modo X à V à V* 62
Tabella 5.24: Riconoscimento di file interni con tutte le sessioni di anco
e le sue riduzioni con K-Means modo
X à
X* à
V 62
Studio e realizzazione di tecniche per il
riconoscimento vocale
Abstract
The goal of our work has been that
to improve the performance of an already existing vocal recognition system
(Spear), based on the paradigm of associative memories. In particular, it has
been afforded the task to decrease the overall computational time of the vocal
recognition program by properly decreasing the number of vectors actually used by
the associative memory to recognize speech utterances.
The method adopted is based on
vector quantization by using some well-known tecniques for reducing the number
of points. In particular, the number of
items belonging to the training set file are properly reduced through the
application of either Lloyd or K-means algorithms.
Several tests have been performed
for what concerns the percentage of
recognition of single-digit speech utterances provided by a Italian segmented speech database, both for
reduced and non-reduced training sets. The results have shown that training set
redution yields acceptable decreasing in recognition percentages.
Ai miei cari , e a tutti
coloro che contribuiscono
all’informazione gratuita
tramite internet
Grazie
Prefazione
Questa tesi si è svolta presso il Laboratorio di microelettronica del Dipartimento di Ingegneria Elettronica (D.I.B.E.) dell’Università degli Studi di Genova.
Il riconoscimento vocale, grazie all’incremento delle prestazioni e all’abbattimento dei costi dei sistemi hardware e software che lo implementano, ha trovato largo uso in molte applicazioni. Ad esempio il riconoscimento vocale è stato inserito con successo nei telefoni cellulari per facilitare l’interazione tra l’utente ed i dispositivi, nelle stazioni telefoniche con funzione di centralino, ma anche in ambito medico per la refertazione automatica, ecc… così permettendo un notevole risparmio di risorse umane. In questa tesi, in particolare, si è affrontato il problema dello studio e della realizzazione di tecniche per il riconoscimento vocale attraverso l’ uso di algoritmi come Lloyd e K-means implementati da un programma scritto in visual C++ allo scopo di visualizzare graficamente dati contenuti nel file di ingresso e di elaborarli.
Lo scopo principale del programma è stato quello di ridurre il numero di dati presenti nel file di entrata perdendo la minor informazione possibile; tale operazione permette di ridurre i tempi di esecuzione del programma di riconoscimento vocale “Spear” con degrado accettabile nella precisione del riconoscimento vocale.
Le attività connesse alla tesi si sono svolte in detto laboratorio, con l’ausilio di materiale di studio fornito dal Relatore Accademico e mediante l’utilizzo di Internet .

Fino ad ora si è visto come è possibile passare dal segnale tempo-continuo ad un segnale tempo-discreto per mezzo del campionamento, ma a monte di questa operazione, per ottenere una rappresentazione più robusta del parlato, possono essere applicati vari metodi, che hanno il compito di ridurre il rumore le distorsioni dovute ai canali di comunicazione, come le linee telefoniche o i microfoni, o alle distorsioni fisiologiche del parlato.
Successivamente, filtraggi ottenute con varie tecniche, possono migliorare ulteriormente la qualità del segnale acquisito.
Si procede all’analisi del parlato trasformando il segnale digitale in una sequenza spettrale; inoltre per ottenere una buona analisi sono stati sviluppati modelli matematici dell’udito, che tendono a riprodurre gli organi unmani oppure le caratteristiche acustiche dell’udito.
Per convertire un segnale dalla rappresentazione analogica a quella digitale sono necessari un certo numero di passi: innanzitutto il segnale deve essere acquisito da un microfono o da un array di microfoni , campionato e codificato in una rappresentazione digitale.
In base alla tecnica utilizzata per acquisire il segnale, il rumore ed il riverbero incidono in maniera differente sugli stadi successividell’analisi, per cui la fase di acquisizione non può essere sottovalutata se si vuole ottenere un buon risultato nel riconoscimento. Ad esempio, per limitare il rumore ambientale, vengono utilizzati tipi speciali di microfoni detti “close-talking” che sono microfoni da utilizzare molto vicino alle labbra.
Se il rumore ambientale è particolarmente elevato vengono utilizzati più microfoni , il cui segnale verrà elaborato da speciali algoritmi di riduzione del rumore che hanno bisogno di più di una sorgente di ingresso.

Figura 1b: Sistema a due sorgenti per la limitazione del rumore
1.3 Metodi di analisi del segnale
Per analizzare il segnale vocale sono stati studiati vari modelli per
avvicinarsi al sistema uditivo umano.
Un modello per simulare l’udito può essere sviluppato in due maniere:
- secondo un approccio strutturale o
fisiologico
- secondo un approccio funzionale
Con il primo approccio ci si aspetta una modellazione di tutti i fonemi osservati, con il secondo sono modellati solo gli aspetti più importanti.
Viene spesso preferito il secondo approccio, perché l’obiettivo è quello di inserire il modello per l’udito in un front-end per il riconoscimento del parlato, inoltre non si è ancora in grado di descrivere tutti i meccanismi dell’udito.
Tra i modelli maggiormante utilizzati troviamo il modello LP (linear
prediction) ed il modello PLP (perceptually – based linear prediction) che è
una delle più importanti tecniche di analisi del parlato poiché permette di
stimare con accuratezza i parametri del parlato in modo veloce.
Il modello PLP è un approccio relativamente nuovo basato su una funzione a soli
poli ed una tecnica di autocorrelazione. Il modello prevede l’introduzione
della “critical-band” delo spettro di potenza del parlato, della preenfasi
“equal-loudness” e per la compressione “cubic-root intensity loudness”.
In seguito viene applicato un modello a soli poli del quint’ordine che ha anche
il vantaggio di enfatizzare i picchi spettrali.
Nell’analisi viene utilizzato il modello autoregressivo a soli poli ,
, dello “short-term power spectrum”
stimato attraverso il
modello LP. Se l’ordine del modello è scelto appropriatamente ,
approssima bene le
aree di alta concentrazione di energia di
e smorza i dettagli
meno rilevanti dello spettro. Tali aree spesso corrispondono alle frequenze di
risonanza del tratto vocale (formanti).
1.4 Passi della tecnica PLP
- Analisi Spettrale.
Il parlato viene segmentato utilizzando la finestratura di “Hamming”
dove N è la lunghezza
della finestra (tipicamente 20 ms).
La trasformata di Fourier discreta (DFT) permette poi di passare nel dominio
delle frequenze (per ottimizzare i tempi di calcolo normalmente viene
utilizzata
dove
è il valore della FFT alla frequenza
.
- Risoluzione Spettrale della banda critica.
Lo spettro
viene trasformato dal
dominio delle frequenze al dominio delle frequenze di Bark
per mezzo della relazione:
dove
è la frequenza
angolare in rad/s. Il risultato della trasformazione viene poi convoluito con
lo spettro di potenza di una banda critica simulata. Nella tecnica PLP, la
curva della banda critica è data dalla funzione:

La convoluzione discreta di
con
produce i campioni
dello spettro di potenza della banda critica:
![]()
La convoluzione della banda critica con la funzione
riduce in modo significativo la risoluzione spettrale di
rispetto all’originale
. In questo metodo
è campionata con intervalli di l-Bark, il valore esatto
dell’ampiezza di tali intervalli viene scelto in modo che sia un numero intero
di campioni spettrali a coprire l’intera banda di analisi. Tipicamente vengono
utilizzati 18 campioni spettrali di
per coprire l’intera
banda di analisi di Bark che va da
- Equal-loudness preemphasis.
La funzione
campionata
viene preenfatizzata
con la curva equal-loudness simulata dalla relazione:
![]()
La funzione ![]()
è un’approssimazione
del fatto che l’udito umano ha una diversa sensibilità a differenti frequenze e
simula proprio questa sensibilità ad un livello di circa 40dB. La particolare
approssimazione adottata è la seguente:
![]()
Questa è la funzione di trasferimento di un filtro con asintoti a 12 dB/oct tra
0 e 400 Hz, 0 dB/oct tra 400 e 1200 Hz,
6 dB/oct tra 1200 e 3100 Hz, e 0 dB/oct tra 3100 Hz e la frequenza di Nyquist.
Per limitare i livelli del suono, questa approssimazione è buona oltre i 5000
Hz.
Per applicazioni che richiedono frequenze di nyquist elevate, viene aggiunto un
termine all’equazione che rappresenta un ulteriore decremento della sensibilità
dell’udito per frequenze oltre i 5000 Hz (circa –18 dB/oct), avremo quindi:
![]()
- Intesdity-loudness power law.
L’ultima operazione da compiere, prima di applicare il modello a soli
poli, è quella di effettuare la compressione dell’ampiezza secondo la seguente
relazione:
![]()
Questa operazione è un’approssimazione della power law of hearing e simula la
relzione non lineare tra l’itensità del suono e il loudness percepito. Questa
operazione riduce anche la variazione dell’ampiezza dello spettro della banda
critica, cosicché il modello a soli poli possa essere realizzato per mezzo di
un modello di ordine relativamente basso.

Figura 1c: Passi della tecnica PLP
- Modello Autoregressivo.
Nell’ultima operazione dell’analisi PLP,
è approssimata con lo spettro di un modello a soli poli, a
questo punto si applica la trasformata discreta inversa (IDFT) per ottenere la
funzione di autocorrelazione duali di
. La scelta della IDFT invece che della IFFT è migliore in
quanto servono solo pochi valori di autocorrelazione. I primi M+1 valori
vengono usati per risolvere le equazioni di Yule-Walker per trovare i
coefficienti autoregressivi del modello a soli poli M-esimo ordine.
Tali coefficienti possono essere poi trasformati in altri tipi di
parametri.
La memoria associativa è utilizzata per analizzare e classificare i parametri del parlato, estratti tramite la tecnica PLP ed associarli ad un set predefinito di caratteristiche, che rendono possibile il riconoscimento della forma d’onda.
Tra tutte le
tecniche la memoria associativa è stata ,in un primo momento, quella che ha
riflettuto nel migliore dei modi l’intenzione di emulare la natura associativa
del cervello umano. Per questa ragione tali memorie sono state largamente
studiatre negli anni ’80, ma presto ,con l’avanzare della ricerca, sono state
sostituite con altri modelli. Comunque in molti campi di applicazione queste
memorie mostrano ancora molti vantaggi rispetto ad altri metodi. Tali vantaggi
sono messi in luce dalle applicazioni che necessitano di una rapplresentazione
vettoriale dei dati, e da quelle dove sia necessario che i tempi di
addestramento siano molto ridotti; inoltre tali memorie non commettono alcun
errore se vengono testate con patterns utilizza ti in fase di addestramento.
Il metodo classico usa il contribuuto di tutti i patterns addestrati, Un test
patten è definito da:
![]()
dove
rappresenta
l’informazine della fase associata ad ogni variabile del test di pattern,
mentre
rappresenta il livello
pesato di confidenza.
per ottenere una
risposta associata al test di pattern, occore un’operazione di decodifica
effettuata con la matrice
. Questa operazione consiste nel moltiplicare ogni variabile
con il suo
corrispondente neurone nella memoria.
La risposta è data da
![]()
dove c è il coefficiente di normalizzazione e rappresenta il contributo di
per ogni test pattern
ed è dato da
![]()
Ogni risposta generata è rappresentata dalla somma di vettori complessi in relazione al contributo di ogni variabile di ogni simbolo addestratodei confronti del test pattern presentato. Tale risposta è data da
![]()
che può essere scritta come
![]()
L’espressione precedente mostra una sequenza di contributi dati dagli elementi
di ogni train pattern ad una specifica risposta r. Questa espressione può
essere riscritta nella forma compatta così:
![]()
dove
e
sono i contributi alla
risposta dati rispettivamente dal modulo pesato e dalla fase di ogni pattern
addestrato, confrontato con lo stimolo di test. Così la coppia train-test più
vicina costituisce l’attrattore dominante ed influenza la risposta più degli
altri patterns. In altre parole, più l’orientazione del train pattern coincide
con lo stimolo di test, più influenza ha nell’orientazione della risposta
finale.
Ogni singolo contributo può essere scritto nella forma:
![]()
Evidenziando separatamente, dall’equazione precedente, modulo e fase, si
ottiene:
![]()

Il metodo classico di decodifica viene riassunto nella seguente figura:

Figura 1d: rappresentazione dello
spazio di train e di test
La figura di sinistra rappresenta la configurazione del train test, mentre quella a destra indica il modo in cui viene associato in risposta per ogni coppia di train test, e come la somma normalizzata di questa risposta dà l’associazione finale.
La risposta nel
dominio reale viene calcolata utilizzando la funzione inversa della sigmoide:
1.6 Dinamic time warping
Il problema dell’Automatic Speech Recognition (ASR) può essere
schematizzato come la decodifica delle informazioni contenute in un segnale
vocale, e la loro trascrizione in un insieme di caratteri.
A seconda delle condizioni di lavoro la complessità del problema varia
notevolmente: i principali fattori da tenere in considerazione sono:
- il numero dei
parlatori
- tipo di parlato (parole isolate, parlato continuo, parlato spontaneo)
- dimensione del vocabolario
- complessità del linguaggio
- condizioni ambientali e qualità del segnale vocale
Un sistema di riconoscimento del parlato opera in due fasi:
- una
fase di training, durante la quale il sistema acquisisce i pattern di
riferimento rappresentativi dei suoni associati alle varie parole costituenti
il vocabolario.
- una fase di riconoscimento, durante la quale un pattern di ingresso
sconosciuto viene identificato basandosi sull’insieme dei riferimenti. Il
processo è costituito essenzialmente da tre passi:
Un pattern corrisponde ad una parola ed è composto da una sequenza di vettori acustici. La maggior difficoltà nell’applicazione all’ASR delle tecniche di pattern recognition deriva dal fatto che occorre comparare sequenze di vettori di lunghezze diverse, in quanto diverse occorrenze della stessa parola, anche pronunciate dallo stesso parlatore, differiscono tra di loro in durata e rate. Siccome queste distorsioni sono in generale non lineari, è necessario progettare efficienti metodi per effettuare una comparazione affidabile.
Siano X e Y due
speech pattern isolati, ad esempio due parole, composte da una sequenza di
vettori
e
rispettivamente la
distorsione tra X ed Y, che indicheremo con d(i,j).
Il non-linear time warping dei pattern X ed Y può essere rappresentato come un
percorso
nel piano (i,j)
definito dalle due sequenze di vettori X ed Y.
La distorsione tra X ed Y lungo il percorso P è data dalla formula:
dove
è un opportuno
coefficiente ed
un fattore di
normalizzazione.
Lo scopo è trovare il percorso che minimizzi
tra tutti i possibili
percorsi in modo da avere una
distorsione.
![]()
Questo problema di minimizzazione può essere risolto usando tecniche che si ispirano
direttamente alla programmazione dinamica.

Figura 1e: Percorso di normalizzazione.
1.7 Algoritmo di programmazione dinamica
La programmazione dinamica è stata largamente usata per risolvere i
problemi di ottimizzazione;
per tenere conto degli aspetti fisici del problema e per limitare il numero di
percorsi (warping path) è stato necessario imporre i seguenti vincoli:
- utterance
endpoints: gli endpoints sono i limiti
temporali entro i quali deve prendere posto la normalizzazione. Si vuole che il
percorso sia tale che P( 1 ) = ( 1 , 1
) e
P( K ) = ( I , J ) .
- monotonocità: questo vincolo si riferisce all’ordine temporale fissato dei
vettori successivi in uno speech pattern. Per mantenere questo ordine è
necessario imporre una condizione di monotonicità che implica che il percorso
P( K ) non può avere una pendenza negativa.
- continuità locale: si vuole
minimizzare la perdita di informazione locale necessaria per l’identificazione
di un utterance. Tale vincolo può essere convenientemente formalizzato in
termini di passi permessi lungo il percorso.
- pendenza del
percorso: sono state testate svariate funzioni euristiche per esprimere il
coefficiente
. Quella scelta è stata
.
Il coefficiente di
normalizzazione
viene solitamente
scelto in modo che le distorsioni siano indipendenti dalle durate dei pattern X
ed Y. Ad esempio , relativamente alla
scelta,
può essere rappresentato
come
.
Per risolvere il problema dell’ottimizzazione relativo al calcolo della distorsione tra i pattern X ed Y, la formula di ricorsione locale usata è :
dove
è la distanza accumulata lungo il percorso ottimale
dall’origine (1,1) fino al punto (i,j).
Da notare come l’espressione di g(i,j) tenga conto del coefficiente
.
Capitolo 2 : Teoria ed algoritmi
Il riconoscimento vocale effettuato dal programma Spear prevede l'utilizzo di un training set contenente i vari fonemi delle parole da individuare. La lunghezza del training set dipende quindi essenzialmente dal numero dei fonemi, nonchè dal numero dei soggetti addestrati.
E' chiaro che, col crescere di questi due fattori fondamentali, le dimensioni del file aumentano drasticamente e con esse anche il tempo impiegato dal programma per riconoscere una parola.
Gli algoritmi che sono alla base del programma (Lloyd e K-means) cercano di ridurre notevolmente tali parametri, cercando di non perdere le informazioni necessarie al riconoscimento.
Se, cioè, un singolo fonema e' contraddistinto da k punti in un N-spazio, mediante l'algoritmo si cerca di portare tali punti ad un valore più piccolo di diversi ordini di grandezza (es. k/100).
Compito dei due algoritmi e' quindi minimizzare l'errore che si compie in questa riduzione.
Il principale problema affrontato e' stata la realizzazione di un modulo flessibile che consentisse al programma di funzionare anche in seguito a cambiamenti nel file di training, come ad esempio una riduzione di classi (fonemi) o del numero dei parametri che le contraddistinguono. Mi sono inoltre proposto di rendere scalabile il fattore di riduzione delle classi.
I due algoritmi utilizzati sono molto simili, e praticamente differiscono per il numero di passi in cui vengono eseguiti. Infatti, mentre l'algoritmo di Lloyd converge, quello dei K-Means prevede un numero massimo di iterazioni.
L'algoritmo di Lloyd parte dalla definizione casuale dei vettori finali, che verranno spostati nei passi successivi. In realtà, la definizione di tali vettori non e' del tutto casuale, ma viene fatta in modo da avere già in partenza un numero di punti sufficienti per ogni classe.
In seguito si passa a definire il Voronoi set (VS), un'area dell' N-spazio che fa riferimento ad un solo vettore. In pratica, si scandiscono tutti i vettori del set di partenza e per essi si cerca il “vincitore", quello, cioè, più vicino.
Il VS e' rappresentato da tutti i vettori più vicini ad uno di riferimento. Fatto questo per ogni classe si può passare a ricalcolare la posizione dei vari vettori.
Ognuno di questi viene calcolato come la somma di tutti i vettori del suo VS, diviso il loro numero.
E' dimostrato che l'algoritmo converge, e questo avviene quando nessuno dei vettori viene più spostato.
L'algoritmo dei K-Means prevede, invece, la cosiddetta on-line update, cioè , invece di calcolare il VS, ogni vettore viene spostato singolarmente.
Questo algoritmo termina dopo un numero di iterazioni che e' possibile scegliere.
2.1 Algoritmo di
LLOYD
L’algoritmo di Lloyd (conosciuto anche con il nome LBG) lavora muovendo ripetitivamente tutti i valori di riferimento alla media del loro Voronoi Set.
Questo è fatto per minimizzare l’errore di distorsione:

dovuto al fatto che ogni vettore di riferimento w si posiziona come centroide di un insieme di punti. Questo fa si che alcuni punti che farebbero riferimento allo stesso vettore (e quindi a quella specifica classe) finiscono per fare riferimento ad altri.
Se “A” è l’insieme dei punti di riferimento, mentre D è l’insieme del training set di partenza, l’algoritmo procede come di seguito:
1. Si inizializza l’insieme A=C1,C2,…..,Cn che contiene N unità con vettori di riferimento w scelti a caso dall’insieme D di partenza.
2. Si calcola per ogni vettore w il suo Voronoi Set R.
3. Si muove ogni vettore w alla media del suo Voronoi Set R.

4. Se al passo 3 almeno uno dei vettori w si è mosso
si ritorna al passo 2.
5. Fine dell’algoritmo.
I passi 2 e 3 sono chiamati Lloyd iteration e garantiscono che l’errore di distorsione sia decrementato o almeno lasciato inalterato. E’ dimostrabile che l’algoritmo converge in un numero finito di iterazioni.

Figura 2.1a: spostamento dei vettori di riferimento
2.2 Algoritmo
K-MEANS
In alcuni casi l’insieme
di partenza D è talmente grande che praticare l’LBG è impossibile.
In questo caso conviene utilizzare
l’algoritmo dei K-Means.
Non è prevista la convergenza, è necessario pertanto impostare un numero massimo di iterazioni. Inoltre, come già detto, non è necessario calcolare il Voronoi Set.
L’algoritmo procede come di seguito.
1. Si inizializza l’insieme A=C1,C2,….Cn che contiene
N unità con i vettori di riferimento w scelti a caso dall’insieme D di
partenza.
2. Si considera il segnale di ingresso
preso dal set D.
3. Si determina il vincitore s cioè il punto di
riferimento più vicino a ![]()
![]()
4. Si sposta il vettore di riferimento ws del vincitore s.
![]()
5. Finchè non si è raggiunto il numero massimo di
passi si continua con il passo 2.
Nell’algoritmo compare il
parametro
detto “learning rate”,
che determina lo spostamento di ws. Questo parametro può essere reso costante
oppure decrescente, come nel caso del KM decrescente come 1/t dove t
rappresenta il numero del passo dell’algoritmo.
Ovviamente, poiché non ci si ferma quando l’algoritmo converge (cosa non prevista), un numero non sufficiente di passi potrebbe dare risultati non adeguati, così come un numero troppo elevato potrebbe far eseguire calcoli superflui.
L’errore che si commette utilizzando questo algoritmo è comunque maggiore di quello ottenuto attraverso l’utilizzo di Lloyd.
2.2 Diagrammi di VORONOI
Si è implementato l’algoritmo che permette di generare il diagramma di Voronoi che è così definito:
Def: Un diagramma di Voronoi calcolato su un numero di semi di un piano euclideo P = (p1 , p2 , p3 , …. ) permette di dividere il piano assegnando a ciascun punto il seme più vicino.
Una regione di Voronoi ( anche detta cella di Voronoi ) raggruppa tutti i punti di un piano assegnati ad un medesimo seme. In termini matematici possiamo scrivere:
V(pi) = { x: |pi - x|
<= |pj- x| For all j != i}
dove
V(pi) è la cella di Voronoi.

Figura 2.2b: celle di Voronoi.
Il principio base è il seguente: per ciascun seme del piano
determinare la linea formata dai punti equidistanti tra il seme e gli atri semi ed unire i semipiani che si creano.
Le immagini seguenti mostrano come opera l’algoritmo:

Figura 2.2c: ordinare tutti i punti in secondo x ascendente.

Figura 2.2d: Dai primi due semi si
genera il più semplice diagramma di Voronoi.

Figura 2.2e: Generazione ed inserimento di una nuova linea bisettrice derivante dalla considerazione del terzo punto e del primo.

Figura 2.2f: individuazione delle intersezioni tra le rette e creazione di una nuova retta bisettrice dell’angolo formato dalle prime due rette.

Figura 2.2g: termine
dell’algoritmo.
Il costo computazionale O di questo algoritmo è:
-
caso migliore ![]()
-
caso peggiore ![]()
-
caso medio ![]()
Capitolo 3 : Ottimizzazione
Per rendere ulteriormente più veloce l’esecuzione del programma Spear o gli algoritmi Lloyd e K-Means sono stati realizzati 2 metodi di riduzione che agiscono rispettivamente prima e dopo aver eseguito gli algoritmi Lloyd e K-means.
Il metodo agisce eliminando quei punti di ciascuna classe che risultino essere più vicini a quelli di un’altra rispetto alla loro.
Le immagini seguenti mostrano indicativamente come opera il criterio:
Figura 3a: Insieme di partenza.

Figura 3b: I punti neri sono stati disattivati.

Figura 3c: Punti rimasti.
Per individuare quali punti devono essere disattivati si
considera ogni punto di ciascuna classe e si calcola la distanza tra il punto e
tutti gli altri.
Per ciascun punto si sommano le distanze appena calcolate
rispetto alla medesima classe di appartenenza e alle altre e si divide per il
numero totale dei punti contenuti nella classe.
Infine si confrontano i valori ottenuti: se la distanza tra
il punto e tutti i punti della propria classe di appartenenza , diviso il numero
di punti della classe, è minore delle distanze tra il punto e i punti di
ciascun’altra classe, diviso il numero di punti totali di ogni classe, allora
il punto viene mantenuto. In caso contrario viene disattivato.
Si può operare attraverso i passi seguenti:
Per ogni punto
considerato:

dove:
= distanza
= classe del punto
considerato
= punti totali per la classe del punto considerato
= punto per
ogni classe
= tutte le classi (da
0 ad nc dove nc = totale classi)
= numero totale di
punti per la classe cl1
Se
allora il punto è
mantenuto.
Questo metodo consente ,nella maggior parte dei casi, di ridurre
notevolmente il numero dei punti e/o dei campioni (mediamente del 50%) e di
rendere molto più definite le classi.
Capitolo 4 : I programmi
Il programma “lk” nasce dalla modifica di un codice base già esistente privo di
interfaccia grafica che effettuava una riduzione di vettori tramite l’uso degli
algoritmi di Lloyd e dei K-means.
Le modifiche effettuate riguardano la
costruzione di un’interfaccia grafica
per Windows, ma anche la possibilità di effettuare ulteriori riduzioni sui dati
di ingresso attraverso l’implementazione nuove metodologie.
Il programma principale realizzato prevede la possibilità di aprire un file in ingresso contenente i dati e di visualizzarli in una finestra. La visualizzazione è bidimensionale, ma è possibile scegliere quali dimensioni vengano mostrate nella finestra: le dimensioni corrispondono ai parametri, che per il sistema di acquisizione PLP da noi usato sono 6.
I dati in ingresso vengono visualizzati come
dei cerchi pieni colorati: il colore ne indica la classe di appartenenza. E’
inoltre possibile selezionare la grandezza dei cerchi visualizzati ( per
ottimizzarne la visualizzazione a seconda del numero e della disposizione degli
stessi).
Per quanto riguarda la riduzione dei dati attraverso gli algoritmi Lloyd e
K-Means è possibile selezionare il fattore di riduzione. Questo valore,
indicato con il nome “fatrid”, è per default pari a 50 e rappresenta il numero
per cui si vuole scalare il set di partenza. Se, ad esempio, si ha un insieme
di 1000 e si sceglie di utilizzare 100 come fattore di riduzione, alla fine si
avranno 100 punti. Il programma prevede comunque che per ogni classe vi sia
almeno un punto.
Un altro parametro modificabile è il numero di iterazioni (passi) compiuti nel
caso della riduzione tramite K-Means : infatti questo algoritmo non converge ed
è necessario che l’utente fissi il numero di passi da eseguire.
Selezionando dal menu “execute” la voce “modo” è possibile selezionare il tipo di riduzione:
|
X à V |
Non effettua alcuna riduzione. |
|
X à V à V* |
Riduce il numero dei campioni dopo aver calcolato gli algoritmi. |
|
X à X* à V |
Riduce il numero dei punti su cui calcolare gli algoritmi. |
Se si vuole visualizzare il diagramma di Voronoi calcolato sui campioni, ovvero sui punti finali calcolati in precedenza attraverso gli algoritmi Lloyd e K-Means è necessario selezionare “Voronoi” dalla tendina “execute”. E’ possibile anche definirne i seguenti parametri:
- passo : precisione con cui viene disegnato il diagramma sullo schermo. Piu’ il passo è piccolo maggiore è il tempo di esecuzione, che però è totalmente indipendente dalla complessità del diagramma che si visualizza.
- modalità colori : permette di scegliere tra due set diversi di colori e può essere utile per avere maggiore visibilità in alcune situazioni.
- assi : visualizza tutti gli assi tra i tutti i campioni rappresentati (utile nella fase di test).
- intersez : individua le intersezioni tra i vari assi (utile nella fase di test).
- campioni : permette di visualizzare o di nascondere i campioni che danno luogo al diagramma.
- classe : permette di specificare la classe di cui si vuole visualizzare il diagramma di Voronoi.
Attraverso il menu “View” è possibile specificare i seguenti parametri:
- Asse x : specifica quale dimensione rappresentare come asse x nella finestra.
- Asse y: specifica quale dimensione rappresentare come asse x nella finestra.
- Dim punti : specifica la dimensione con cui i punti vengono visualizzati.
- Dim campioni : specifica la dimensione con cui i campioni vengono visualizzati.
4.1 Soluzioni
principali e funzioni del programma
VISUALIZZAZIONE
Nel corso della realizzazione del programma principale sono emersi dei problemi per i quali sono state trovate soluzioni.
A esempio è utile poter visualizzare nella finestra del programma tutti i dati che vengono elaborati , anche se non si conosce a priori che valori assumano.
E’ necessario effettuare una stima del valore minimo e massimo che raggiunge il set di dati da elaborare, considerando invece che i campioni provenienti da successive riduzione rimangano sempre all’interno di tali valori. Tali valori permettono di calcolare alcuni coefficienti che verranno moltiplicati per ogni punto in modo da averne una rappresentazione fedele sempre nel campo visibile della finestra del programma, lasciando lo spazio per la “barra di stato”.

![]()

![]()
Per ogni punto che dovrà essere rappresentato sarà necessario moltiplicarlo per il coefficiente moltiplicativo e sommare l’offset.

ALLOCAZIONE MEMORIA
Un altro problema è la creazione delle matrici multidimensionali: infatti è impossibile conoscere a priori il numero di classi, parametri e punti che dovranno essere letti ed elaborati. E’ necessario che le matrici vengano costruite in maniera dinamica, anche per ottimizzare l’utilizzo della memoria da parte del programma.
Un esempio molto semplice è il seguente:
bool ***att; // viene dichiarata all’inizio del codice (se variabile globale)
Viene lanciata una volta soltanto la procedura che crea la matrice quando si sono determinate le dimensioni che dovrà avere.
void creaatt() // crea la matrice per la attivazione / disattivazione dei punti
{
att = new bool**[NUMCLASS];
int s = 0;
int z = 0;
while (s<NUMCLASS)
{
att[s]
= new bool*[thetal[s]];
while
(z<thetal[s])
{
att[s][z]
= new bool[NUMPAR];
z = z+1;
}
z = 0;
s = s+1;
}
}
In questo modo, più complicato di
un dimensionamento statico, ma più performante, si alloca solo la memoria che
verrà effettivamente utilizzata.
PROGRESSBAR
Talvolta le elaborazioni, a causa della lentezza del calcolatore o della considerevole mole dei dati, si prolungano nel tempo anche per qualche minuto.
Per fornire all’utente una stima di quanto tempo dovrà ancora trascorrere per terminare l’operazione è stata aggiunta una progressbar, ovvero una barra formata da 10 segmenti la cui accensione in progressione indica l’avanzamento dei calcoli.
La progressbar è
realizzata tramite una procedura che viene chiamata ad esempio all’interno di
un ciclo For nel quale vengono eseguiti
tutti i calcoli, caso molto frequente per questo programma.
La procedura:
void progressbar(int par , int tot)
Stampa a video la progressbar e deve ricevere come parametri 2 interi che rappresentano il massimo valore possibile (tipicamente il termine del ciclo) ed il valore corrente.
STATUSBAR
La barra di stato, situata nella parte bassa della finestra, è uno spazio in cui
vengono annotati tutti i settaggi principali e le operazioni eseguite in modo
tale da informare l’utente sul significato di quanto viene visualizzato nella
finestra.
Ad esempio vengono indicate le dimensioni x ed y rappresentate, quale algoritmo è stato utilizzato o quale classe è correntemente visualizzata tramite Voronoi.
SALVATAGGIO
Il programma prevede che l’utente possa salvare i risultati ottenuti ad esempio per poterli elaborare attraverso altri programmi come Spear.
Poiché spesso ci si dimentica di salvare gli ultimi dati, è possibile che il programma effettui un salvataggio automatico ogni volta che vengono modificati. Per sfruttare questa comoda opzione basta attivarla dal menu “File”.
4.2 Programmi accessori
Sono stati realizzati anche 2 altri programmi di supporto:
Il primo
programma, scritto in qbasic, è molto semplice ed è stato utilizzato unicamente
come semplice riscontro e come ulteriore visualizzatore. Il programma non
compie alcuna elaborazione, ma tramite la lettura del file contenete i dati
sorgenti e del file contente i dati elaborati permette di visualizzare i dati
contestualmente in una finestra. E’ stato scelto questo linguaggio per la
semplicità e per velocità di programmazione , purtroppo non è particolarmente
performante, ma non dovendo effettuare alcun calcolo di rilievo i tempi di
esecuzione si mantengono contenuti.
Il secondo programma offre la possibilità di visionare i dati, dopo averli
elaborati tramite Lloyd e k-means, in 3 dimensioni.
Tale visualizzazione tridimensionale prevede anche una rotazione modificabile secondo i diversi assi tale da poter vedere contemporaneamente il massimo dei parametri possibili confondendoli il meno possibile.
Capitolo 5 : I risultati
I risultati seguenti comprendono la maggior parte dei casi di
funzionamento corrispondenti a differenti files di dati in ingresso ed alle
principali elaborazioni possibili su questi.
Nelle immagini seguenti ( a,b,c,d,e,f ) vengono rappresentate elaborazioni su
una mole modesta di dati tramite k-means e Lloyd con differenti parametri.

Figura 5a: Lloyd
fatrid = 50 modo XàV

Figura
5b: k-means fatrid = 50 modo XàV

Figura
5c: k-means fatrid = 10 modo XàV

Figura
5d: k-means fatrid = 10 modo XàVàV*
Figura
5e: k-means fatrid = 10 modo XàX*àV

Figura 5f: Voronoi di k-means fatrid = 10 modo XàV
Nelle
immagini seguenti ( g,h,i,l ) vengono mostrate le elaborazioni di files di
ingresso contenenti un vasto set di dati.

Figura
5g: k-means fatrid = 100 modo
XàV

Figura
5h: k-means fatrid = 100 modo XàVàV*

Figura
5i: k-means fatrid = 100 modo XàX*àV

Figura 5l: Voronoi di k-means fatrid = 100 modo XàV

Figura 5m: Voronoi di k-means fatrid = 100 modo XàVàV*

Figura 5n: Voronoi di k-means fatrid = 100 modo XàX*àV
5.1 Risultati
ottenuti tramite l’uso di Spear
I risultati hanno evidenziato esiti
piuttosto positivi, a fronte di un margine di errore contenuto si è avuto un
notevole incremento della velocità di computazione del programma Spear,
soprattutto per quelle classi i cui punti sono molto numerosi.
Le prove sono state effettuate testando voci
maschili e femminili applicando gli algoritmi Lloyd e K-Means con fattore di
riduzione 10 e 100 utilizzando anche le modalità , X à V , X à V à V* e X à X* à V descritte
precedentemente.
Per effettuare le prove è stato
utilizzato un database di registrazioni composto da un certo numero di parole
pronunciate da numerosi parlatori, maschi e femmine, in varie sessioni.
Per ogni parlatore ho utilizzato due diversi file di training: uno contenente
una sola sessione di prova, l’altro tutte e cinque.
le parole da riconoscere sono state
scelte secondo il seguente criterio. 2 per la sessione corrente, 2 per lo
stesso parlatore , ma con una sessione diversa, 2 per un altro parlatore dello
stesso sesso ed infine 2 per un parlatore di sesso diverso.
La grande maggioranza delle parole
riconosciute dai file interi sono state riconosciute anche dai files ridotti.
Generalmente si è potuto osservare
una buona percentuale di riconoscimento (tra il 50 % e il 70 %) nel caso di
parlatori addestrati ed un sostanziale miglioramento nel caso di parlatori non
addestrati. Questo miglioramento è stato tanto più visibile, tanto più grande è
stato il file di training. In tutte le prove effettuate l’algoritmo Lloyd di è
dimostrato più efficiente di quello effettuato tramite quello dei K-Means.
Per quanto riguarda le riduzioni
ulteriori ,ottenute attraverso la decimazione dei punti di partenza (X à X* à V ) o di quelli rimasti
dopo l’esecuzione degli algoritmi di Lloyd e dei K-means (X à V à V* ) è risultato che il secondo metodo è più
performante del primo nella maggior parte delle prove effettuate.
In alcuni casi, come mostrano le
figure 5h e 5i, il modo X à V à V* causa una riduzione eccessiva delle
dimensioni del file di training, con conseguente perdita di informazione;
tuttavia in altri casi questo metodo risulta comunque performante.
Di seguito sono riportate le
tabelle relative alle prove effettuate. Ogni file di training è affiancato
dalle sue versioni ridotte. La colonna R ci dice se la parola è stata
riconosciuta.
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 83.5 |
S 68.5 |
|
Ancos01 |
2#3 |
S 100 |
S 78.8 |
S 59 |
|
Ancos02 |
0#1 |
S 60 |
S 60 |
S 38.6 |
|
Ancos02 |
2#3 |
S 70.4 |
S 70.4 |
S 70.4 |
|
Lucas01 |
5#3 |
S 52 |
S 50 |
S 54.6 |
|
Lucas01 |
9#4 |
S 47 |
S 47 |
S 39.4 |
|
Cabos03 |
6#1 |
N 33.7 |
N 36.6 |
S 31.1 |
|
Cabos03 |
0#3 |
N 26.4 |
S 22.9 |
S 18.4 |
Tabella 5.1: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con Lloyd modo X à V.

Grafico 5.1: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con Lloyd modo X à V.
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 57.5 |
N 30.1 |
|
Ancos01 |
2#3 |
S 100 |
S 65 |
S 28 |
|
Ancos02 |
0#1 |
S 60 |
S 54.6 |
N 28 |
|
Ancos02 |
2#3 |
S 70.4 |
S 58.7 |
S 62.1 |
|
Lucas01 |
5#3 |
S 52
|
S 50.2 |
S 42.5 |
|
Lucas01 |
9#4 |
S 47 |
S 39.3 |
S 29 |
|
Cabos03 |
6#1 |
N 33.7 |
N 24.5 |
S 20.9 |
|
Cabos03 |
0#3 |
N 26.4 |
N 16.6 |
N 14.2 |
Tabella 5.2: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con Lloyd modo X à V à V* .

Grafico 5.2: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con Lloyd modo X à V à V* .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 73.9 |
S 68.4 |
|
Ancos01 |
2#3 |
S 100 |
S 72.3 |
S 52.8 |
|
Ancos02 |
0#1 |
S 60 |
S 57.3 |
S 61.3 |
|
Ancos02 |
2#3 |
S 70.4 |
S 66.1 |
S 65.2 |
|
Lucas01 |
5#3 |
S 52 |
S 45.9 |
S 49.1 |
|
Lucas01 |
9#4 |
S 47 |
S 45 |
S 35.9 |
|
Cabos03 |
6#1 |
N 33.7 |
N 32.7 |
S 28.5 |
|
Cabos03 |
0#3 |
N 26.4 |
S 18.3 |
S 16.5 |
Tabella 5.3: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con Lloyd modo X à X* à V .

Grafico 5.3: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con Lloyd modo X à X* à V .
|
|
|
Ancoalls |
Ancoalls.10 |
Ancoalls.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 80.8 |
S 68.4 |
|
Ancos01 |
2#3 |
S 100 |
S 78.8 |
S 59 |
|
Ancos02 |
0#1 |
S 100 |
S 70.6 |
S 54.6 |
|
Ancos02 |
2#3 |
S 100 |
S 70.4 |
S 70.4 |
|
Lucas01 |
5#3 |
S 52 |
S 50 |
S 54.6 |
|
Lucas01 |
9#4 |
S 44 |
S 47 |
S 39.4 |
|
Cabos03 |
6#1 |
N 44 |
N 36.6 |
S 31.1 |
|
Cabos03 |
0#3 |
N 29.8 |
S 22.9 |
S 18.4 |
Tabella 5.4: Riconoscimento di file interni con tutte le sessioni di anco e le sue riduzioni con Lloyd modo X à V .

Grafico 5.4: Riconoscimento di file interni con tutte le sessioni di anco e le sue riduzioni con Lloyd modo X à V .
|
|
|
Ancoalls |
Ancoalls.10 |
Ancoalls.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 60.2 |
N 32.8 |
|
Ancos01 |
2#3 |
S 100 |
S 73.6 |
S 58.3 |
|
Ancos02 |
0#1 |
S 100 |
S 50.6 |
N 29.3 |
|
Ancos02 |
2#3 |
S 100 |
S 67.4 |
S 66 |
|
Lucas01 |
5#3 |
S 52 |
S 41.3 |
S 43.2 |
|
Lucas01 |
9#4 |
S 44 |
N 32.7 |
S 30.8 |
|
Cabos03 |
6#1 |
N 44 |
S 17.1 |
N 22 |
|
Cabos03 |
0#3 |
N 29.8 |
S 28.8 |
N 16.9 |
Tabella 5.5: Riconoscimento di file interni con tutte le sessioni di anco e le sue riduzioni con Lloyd modo X à V à V* .

Grafico 5.5: Riconoscimento di file interni con tutte le sessioni di anco e le sue riduzioni con Lloyd modo X à V à V* .
|
|
|
Ancoalls |
Ancoalls.10 |
Ancoalls.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 72.6 |
S 65.7 |
|
Ancos01 |
2#3 |
S 100 |
S 75.6 |
S 52.3 |
|
Ancos02 |
0#1 |
S 100 |
S 72 |
S 62.6 |
|
Ancos02 |
2#3 |
S 100 |
S 70 |
S 66.2 |
|
Lucas01 |
5#3 |
S 52 |
S 44.1 |
S 50.1 |
|
Lucas01 |
9#4 |
S 44 |
N 30.4 |
S 36.4 |
|
Cabos03 |
6#1 |
N 44 |
S 18.8 |
S 27.9 |
|
Cabos03 |
0#3 |
N 29.8 |
N 20.1 |
N 19.2 |
Tabella 5.6: Riconoscimento di file interni con tutte le sessioni di anco e le sue riduzioni con Lloyd modo X à X* à V .

Grafico 5.6: Riconoscimento di file interni con tutte le sessioni di anco e le sue riduzioni con Lloyd modo X à X* à V .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 79.4 |
S 60.2 |
|
Ancos01 |
2#3 |
S 100 |
S 78.8 |
S 44 |
|
Ancos02 |
0#1 |
S 60 |
S 56 |
S 53.3 |
|
Ancos02 |
2#3 |
S 70.4 |
S 70.4 |
S 44 |
|
Lucas01 |
5#3 |
S 52 |
S 43 |
S 47.7 |
|
Lucas01 |
9#4 |
S 47 |
S 78 |
S 81.7 |
|
Cabos03 |
6#1 |
N 33.7 |
S 36.6 |
N 35.1 |
|
Cabos03 |
0#3 |
N 26.4 |
S 25.3 |
N 13.8 |
Tabella 5.7: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con K-Means modo X à V .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 56.1 |
N 31.5 |
|
Ancos01 |
2#3 |
S 100 |
S 70.2 |
S 34.6 |
|
Ancos02 |
0#1 |
S 60 |
S 52 |
N 28 |
|
Ancos02 |
2#3 |
S 70.4 |
S 62 |
S 40.1 |
|
Lucas01 |
5#3 |
S 52 |
S 39.9 |
S 42.5 |
|
Lucas01 |
9#4 |
S 47 |
S 71.1 |
S 76.4 |
|
Cabos03 |
6#1 |
N 33.7 |
S 25.7 |
S 36.2 |
|
Cabos03 |
0#3 |
N 26.4 |
N 19.9 |
N 10.7 |
Tabella 5.8: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con K-means modo X à V à V* .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 73.9 |
S 60.2 |
|
Ancos01 |
2#3 |
S 100 |
S 75.9 |
S 37.1 |
|
Ancos02 |
0#1 |
S 60 |
S 60 |
S 66.6 |
|
Ancos02 |
2#3 |
S 70.4 |
S 67.3 |
S 40.2 |
|
Lucas01 |
5#3 |
S 52 |
S 38.9 |
S 42.5 |
|
Lucas01 |
9#4 |
S 47 |
S 50.1 |
S 60.7 |
|
Cabos03 |
6#1 |
N 33.7 |
S 32.2 |
N 25.1 |
|
Cabos03 |
0#3 |
N 26.4 |
N 22 |
S 15.2 |
Tabella 5.9: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con K-Means modo X à X* à V .
|
|
|
Ancosalls |
Ancoalls.10 |
Ancoalls.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 73.9 |
S 64.3 |
|
Ancos01 |
2#3 |
S 100 |
S 66.7 |
S 53 |
|
Ancos02 |
0#1 |
S 100 |
S 70.6 |
S 60 |
|
Ancos02 |
2#3 |
S 100 |
S 63 |
S 56 |
|
Lucas01 |
5#3 |
S 52 |
S 55.8 |
S 38.3 |
|
Lucas01 |
9#4 |
S 44 |
S 77.5 |
N 43.6 |
|
Cabos03 |
6#1 |
N 44 |
N 36.4 |
N 35 |
|
Cabos03 |
0#3 |
N 29.8 |
N 39 |
S 32 |
Tabella 5.10: Riconoscimento di file interni con tutte le sessioni di anco e le sue riduzioni con K-Means modo X à V .
|
|
|
Ancosalls |
Ancoalls.10 |
Ancoalls.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 60.2 |
S 60.1 |
|
Ancos01 |
2#3 |
S 100 |
S 64.5 |
S 47.8 |
|
Ancos02 |
0#1 |
S 100 |
S 50.6 |
S 57 |
|
Ancos02 |
2#3 |
S 100 |
S 58.1 |
S 50.5 |
|
Lucas01 |
5#3 |
S 52 |
S 44.2 |
S 32.4 |
|
Lucas01 |
9#4 |
S 44 |
S 50.2 |
S 40 |
|
Cabos03 |
6#1 |
N 44 |
N 34.9 |
N 30.8 |
|
Cabos03 |
0#3 |
N 29.8 |
S 37.7 |
N 24 |
Tabella 5.11: Riconoscimento di file interni con tutte le sessioni di anco e le sue riduzioni con K-Means modo X à V à V* .
|
|
|
Ancosalls |
Ancoalls.10 |
Ancoalls.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 69.8 |
S 64.3 |
|
Ancos01 |
2#3 |
S 100 |
S 64.8 |
S 45.5 |
|
Ancos02 |
0#1 |
S 100 |
S 72 |
S 60 |
|
Ancos02 |
2#3 |
S 100 |
S 59.9 |
S 47.6 |
|
Lucas01 |
5#3 |
S 52 |
S 52.7 |
S 35 |
|
Lucas01 |
9#4 |
S 44 |
S 75.6 |
N 36.1 |
|
Cabos03 |
6#1 |
N 44 |
S 35 |
N 30.3 |
|
Cabos03 |
0#3 |
N 29.8 |
N 34.9 |
S 32.2 |
Tabella 5.12: Riconoscimento di file interni con tutte le sessioni di anco e le sue riduzioni con K-Means modo X à X* à V .
Sono state eseguite
ulteriori prove utilizzando file di training ottenuti dalla prima sessione di
Anco e da tutte le sessioni di Anco e si è valutato il riconoscimento con registrazioni dello stesso parlatore.
Di seguenti risultati è ben visibile che il modo X à X* à
V è molto piu’ performante del modo
X à
V à
V* .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 83.5 |
S 68.4 |
|
Ancos01 |
0#2 |
S 100 |
S 79 |
S 66.6 |
|
Ancos02 |
0#1 |
S 60 |
S 60 |
S 38.6 |
|
Ancos02 |
0#2 |
S 53.9 |
S 68.5 |
S 50.7 |
|
Ancos03 |
0#1 |
S 61.3 |
S 58.6 |
S 53.3 |
|
Ancos03 |
0#1 |
S 56.3 |
S 61.9 |
S 50.7 |
Tabella 5.13: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con Lloyd modo X à V
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 57.5 |
N 30.1 |
|
Ancos01 |
0#2 |
S 100 |
S 56.5 |
N 30.4 |
|
Ancos02 |
0#1 |
S 60 |
S 54.6 |
N 28 |
|
Ancos02 |
0#2 |
S 53.9 |
S 55.5 |
N 31.7 |
|
Ancos03 |
0#1 |
S 61.3 |
N 48 |
N 24 |
|
Ancos03 |
0#1 |
S 56.3 |
S 54.9 |
N 23.9 |
Tabella 5.14: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con Lloyd modo X à V à V* .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 73.9 |
S 68.4 |
|
Ancos01 |
0#2 |
S 100 |
S 75.3 |
S 65.2 |
|
Ancos02 |
0#1 |
S 60 |
S 57.3 |
S 61.3 |
|
Ancos02 |
0#2 |
S 53.9 |
S 63.4 |
S 58.7 |
|
Ancos03 |
0#1 |
S 61.3 |
S 64 |
S 58.6 |
|
Ancos03 |
0#1 |
S 56.3 |
S 52.1 |
S 59.1 |
Tabella 5.15: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con Lloyd modo X à X à V* .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 80.8 |
S 68.4 |
|
Ancos01 |
0#2 |
S 100 |
S 86.9 |
S 71 |
|
Ancos02 |
0#1 |
S 100 |
S 70.6 |
S 54.6 |
|
Ancos02 |
0#2 |
S 100 |
S 74.6 |
S 68.2 |
|
Ancos03 |
0#1 |
S 100 |
S 78.6 |
S 69.3 |
|
Ancos03 |
0#1 |
S 100 |
S 80.2 |
S 61.9 |
Tabella 5.16: Riconoscimento di file interni con tutte le sessioni di anco e le sue riduzioni con Lloyd modo X à V .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
N 60.2 |
N 32.8 |
|
Ancos01 |
0#2 |
S 100 |
N 55 |
N 27.5 |
|
Ancos02 |
0#1 |
S 100 |
N 50.6 |
N 29.3 |
|
Ancos02 |
0#2 |
S 100 |
N 58.7 |
N 33.3 |
|
Ancos03 |
0#1 |
S 100 |
N 52 |
N 21.3 |
|
Ancos03 |
0#1 |
S 100 |
N 57.7 |
N 23.9 |
Tabella 5.17: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con Lloyd modo X à V à V* .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 72.6 |
S 65.7 |
|
Ancos01 |
0#2 |
S 100 |
S 66.6 |
S 69.5 |
|
Ancos02 |
0#1 |
S 100 |
S 72 |
S 62.6 |
|
Ancos02 |
0#2 |
S 100 |
S 66.6 |
S 63.4 |
|
Ancos03 |
0#1 |
S 100 |
S 72 |
S 70.6 |
|
Ancos03 |
0#1 |
S 100 |
S 76 |
S 67.6 |
Tabella 5.18: Riconoscimento di file interni con tutte le sessioni di anco e le sue riduzioni con Lloyd modo X à X à V .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 79.4 |
S 60.2 |
|
Ancos01 |
0#2 |
S 100 |
S 82.6 |
S 59.4 |
|
Ancos02 |
0#1 |
S 60 |
S 56 |
S 53.3 |
|
Ancos02 |
0#2 |
S 53.9 |
S 47.6 |
S 58.7 |
|
Ancos03 |
0#1 |
S 61.3 |
S 56 |
S 58.6 |
|
Ancos03 |
0#1 |
S 56.3 |
S 49.2 |
S 52.1 |
Tabella 5.19: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con K-Means modo X à V
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 56.1 |
N 31.5 |
|
Ancos01 |
0#2 |
S 100 |
S 53.6 |
N 31.8 |
|
Ancos02 |
0#1 |
S 60 |
S 52 |
N 28 |
|
Ancos02 |
0#2 |
S 53.9 |
N 52.3 |
N 28.5 |
|
Ancos03 |
0#1 |
S 61.3 |
N 45.3 |
N 24 |
|
Ancos03 |
0#1 |
S 56.3 |
N 52.1 |
N 21.1 |
Tabella 5.20: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con K-Means modo X à V à V* .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 73.9 |
S 60.2 |
|
Ancos01 |
0#2 |
S 100 |
S 75.3 |
S 68.1 |
|
Ancos02 |
0#1 |
S 60 |
S 60 |
S 66.6 |
|
Ancos02 |
0#2 |
S 53.9 |
S 61.9 |
S 57.1 |
|
Ancos03 |
0#1 |
S 61.3 |
S 64 |
S 64 |
|
Ancos03 |
0#1 |
S 56.3 |
S 49.3 |
S 60.5 |
Tabella 5.21: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con K-Means modo X à X à V* .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 73.9 |
S 68.4 |
|
Ancos01 |
0#2 |
S 100 |
S 79.7 |
S 71 |
|
Ancos02 |
0#1 |
S 100 |
S 70.6 |
S 54.6 |
|
Ancos02 |
0#2 |
S 100 |
S 68.2 |
S 68.2 |
|
Ancos03 |
0#1 |
S 100 |
S 77.3 |
S 69.3 |
|
Ancos03 |
0#1 |
S 100 |
S 69 |
S 61.9 |
Tabella 5.22: Riconoscimento di file interni con tutte le sessioni di anco e le sue riduzioni con Lloyd modo X à V .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
N 60.2 |
N 15 |
|
Ancos01 |
0#2 |
S 100 |
N 55 |
N 8.6 |
|
Ancos02 |
0#1 |
S 100 |
N 50.6 |
N 9.3 |
|
Ancos02 |
0#2 |
S 100 |
N 57.1 |
N 9.5 |
|
Ancos03 |
0#1 |
S 100 |
N 52 |
N 12 |
|
Ancos03 |
0#1 |
S 100 |
N 54.9 |
N 14 |
Tabella 5.23: Riconoscimento di file interni con la sessione 1 di anco e le sue riduzioni con K-Means modo X à V à V* .
|
|
|
Ancos01 |
Ancos01.10 |
Ancos01.100 |
|
Parlatore |
Parola |
R %
|
R %
|
R % |
|
Ancos01 |
0#1 |
S 100 |
S 69.8 |
S 64.3 |
|
Ancos01 |
0#2 |
S 100 |
S 69.5 |
S 69.5 |
|
Ancos02 |
0#1 |
S 100 |
S 72 |
S 60 |
|
Ancos02 |
0#2 |
S 100 |
S 68.2 |
S 65 |
|
Ancos03 |
0#1 |
S 100 |
S 73.3 |
S 68 |
|
Ancos03 |
0#1 |
S 100 |
S 77.4 |
S 69 |
Tabella 5.24: Riconoscimento di file interni con
tutte le sessioni di anco e le sue riduzioni con K-Means modo X à X à
V .
Capitolo 6 : Conclusioni
I risultati ottenuti nelle prove evidenziano la possibilità di ottenere buoni risultati e la velocizzazione del processo di riconoscimento vocale senza perdite significative. Il programma lk richiede buone risorse computazionali, e comunque il tempo richiesto e' abbastanza alto, soprattutto se si utilizzano file molto grandi.
La compressione dei file di training però e' fatta off-line ed il tempo richiesto non influisce sul tempo di riconoscimento.
Il software sviluppato è molto flessibile e versatile poiché permette di decidere sia il tipo di riduzione da effettuare sia l’entità della stessa dando la possibilità all’utente di stimare graficamente i risultati ottenuti.
I numerosi risultati, ottenuti tramite prove di diverso tipo, evidenziano come la riduzione Xà Xà V con una scelta appropriata del fattore di riduzione, permetta di ridurre notevolmente la dimensione del file di training e di conseguenza il tempo di calcolo richiesto dal programma di riconoscimento vocale “Spear”, senza compromettere, nella maggior parte dei casi, il riconoscimento corretto delle parole.
Generalmente la riduzione attraverso l’algoritmo di Lloyd è risultata migliore rispetto a quella effettuata tramite l’algoritmo dei K-Means.
Sebbene i risultati differiscano di poco il costo computazionale richiesto dall’algoritmo di Lloyd è però più gravoso di quello richiesto dall’algoritmo dei K-Means.
Esistono molti altri algoritmi di
quantizzazione vettoriale, un possibile sviluppo futuro in quest'ambito
potrebbe fornire dati e risultati ancora migliori. Gli algoritmi di Lloyd e dei
K-Means hano comunque dimostrato un'ottima affidabilità senza commettere errori
rilevanti nel riconoscimento.
Capitolo 7 : Appendice
// lk.cpp
//
#include
"stdafx.h"
#include
"resource.h"
#include
<windows.h>
#include
<stdio.h>
#include
<math.h>
#include
<stdlib.h>
#include
<fstream.h>
#include
<fstream>
#include
<time.h>
#define
MAX_LOADSTRING 300
#define
IDM_ELLIPSE 1100
#define
IDM_RECTANGLE 1200
#define
IDM_ROUNDRECT 1300
static BOOL param2=FALSE;
HDC hdc;
int wmId, wmEvent;
bool save = false;
long x = 100;
long y = 50;
char lork='k';
int ftrd=100;
bool sw = false;
int lloyddaeseguire=0;
int kmeansdaeseguire=0;
int voronoidaeseguire=0;
double valoremaxx=0.0;
double coeffmoltiplx=0.0;
double offsetx=0.0;
double valoremaxy=0.0;
double coeffmoltiply=0.0;
double offsety=0.0;
double valoreminx=0.0;
double valoreminy=0.0;
int finestrax = 750;
int finestray = 470;
double valoretotale=0.0;
int ftrd1=50;
int iterr=100;
int dimx=0;
int dimy=1;
float dimpunti=(float)1.8;
float dimcampioni=5;
float ***theta;
float ***thetamod;
float ***lly;
bool ***att;
bool ***attc;
int **md;
int thetal[30];
int thetalmod[30];
float vor[300][6];
int acluster=0;
int apunti=0;
int parametri=0;
float vx=0;
float vy=0;
int ytu=0;
int llyl[30];
int NUMCLASS = 0;
int NUMPAR = 0;
float intersx=0;
float intersy=0;
int giu=0;
int done=0;
int vnd=0;
int swp=0;
int vpasso=2;
int vdim=2;
int vrid=0;
int vinters=0;
int vassi=0;
int vcl=0;
int tipoxv=0;
bool luy = false;
bool savenow = false;
int provetta=0;
bool paramwrite = false;
int lop = 0;
PAINTSTRUCT ps;
HWND hWnd;
HBRUSH hbrush;
HPEN hpen;
// Global
Variables:
HINSTANCE hInst; // current instance
TCHAR
szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
int
parametro2var=0;
//
Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT
CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT
CALLBACK About(HWND, UINT, WPARAM, LPARAM);
LRESULT
CALLBACK SaveAs(HWND, UINT, WPARAM, LPARAM);
float
coord_distance
(float a, float b);
void progressbar(int par , int tot);
double valass(double tre)
{
double tre1=0;
if (tre > 0) tre1 = tre;
if (tre == 0) tre1 = tre;
if (tre <0 ) tre1 = double (-1) * tre;
return (tre1);
}
// Disegna un quadrato
void disegnaquadrato(int x,int y,int
a)
{
//Rectangle(hdc,
x,y, x+a,y+a);
Rectangle(hdc,
x-a/2,y-a/2, x+a/2,y+a/2);
}
// Disegna
un ellisse
void disegnaellisse(int x,int y,int
a)
{
//Ellipse(hdc,
x, y, x+a, y+a);
Ellipse(hdc,x-a,y-a,x+a,y+a);
}
// cambia il colore della penna
void colorepenna(int col1)
{
int r,g,b,col,tr;
if (giu == 15) giu =0;
tr=0;
if ((col1 == 14) || (col1 < 14)) col = col1;
if (col1
> 14)
{
while (tr < 1)
{
col1 =
col1 - 15;
col =
col1;
if (col1 < 15) tr = 2;
}
}
if (col==0) {
r=0;
g=0;
b=0;
}
if (col==1) {
r=255;
g=0;
b=0;
}
if (col==2) {
r=255;
g=255;
b=0;
}
if (col==3) {
r=255;
g=0;
b=255;
}
if (col==4) {
r=0;
g=0;
b=255;
}
if (col==5) {
r=128;
g=255;
b=0;
}
if (col==6) {
r=128;
g=0;
b=255;
}
if (col==7) {
r=128;
g=128;
b=128;
}
if (col==8) {
r=128;
g=64;
b=64;
}
if (col==9) {
r=64;
g=128;
b=128;
}
if (col==10) {
r=0;
g=255;
b=255;
}
if (col==11) {
r=100;
g=0;
b=100;
}
if (col==12) {
r=0;
g=100;
b=100;
}
if (col==13) {
r=100;
g=100;
b=0;
}
if (col==14) {
r=220;
g=60;
b=100;
}
DeleteObject(hpen);
hpen =
CreatePen(PS_SOLID, 1, RGB(r, g, b));
SelectObject(hdc,
hpen);
}
// cambia il colore del
pennello
void colorepennello(int col)
{
int r,g,b;
if (col==0) {
r=0;
g=0;
b=0;
}
if (col==1) {
r=255;
g=0;
b=0;
}
if (col==2) {
r=255;
g=255;
b=0;
}
if (col==3) {
r=255;
g=0;
b=255;
}
if (col==4) {
r=0;
g=0;
b=255;
}
if (col==5) {
r=128;
g=255;
b=0;
}
if (col==6) {
r=128;
g=0;
b=255;
}
if (col==7) {
r=128;
g=128;
b=128;
}
if (col==8) {
r=128;
g=64;
b=64;
}
if (col==9) {
r=64;
g=128;
b=128;
}
if (col==10) {
r=0;
g=255;
b=255;
}
if (col==11) {
r=100;
g=0;
b=100;
}
if (col==12) {
r=0;
g=100;
b=100;
}
if (col==13) {
r=100;
g=100;
b=0;
}
if (col==14) {
r=220;
g=60;
b=100;
}
DeleteObject(hbrush);
hbrush
= CreateSolidBrush(RGB(r, g, b));
SelectObject(hdc,
hbrush);
}
float
radicequadrata(float
radq)
{
return
(sqrt(radq));
}
void creaatt() // crea la
matrice per la attivazione / disattivazione dei punti
{
att = new bool**[NUMCLASS];
int s = 0;
int z = 0;
while (s<NUMCLASS)
{
att[s] =
new bool*[thetal[s]];
while (z<thetal[s])
{
att[s][z] = new bool[NUMPAR];
z = z+1;
}
z = 0;
s = s+1;
}
}
void creaattc() // crea la matrice per la attivazione /
disattivazione dei campioni
{
attc = new bool**[NUMCLASS];
int s = 0;
int z = 0;
while (s<NUMCLASS)
{
attc[s] =
new bool*[llyl[s]];
while (z<llyl[s])
{
attc[s][z] = new bool[NUMPAR];
z = z+1;
}
z = 0;
s = s+1;
}
}
void creathetamod() // crea
la matrice per la attivazione / disattivazione dei punti
{
thetamod = new float**[NUMCLASS];
int s = 0;
int z = 0;
while (s<NUMCLASS)
{
thetamod[s] = new float*[thetal[s]];
while (z<thetal[s])
{
thetamod[s][z] = new float[NUMPAR];
z = z+1;
}
z = 0;
s = s+1;
}
}
void disattivacampioni() // disattiva i campioni
{
int s=0;
int z=0;
int s1=0;
int z1=0;
float xw=(float)0.0;
float yw=(float) 0.0;
float xe=(float)0.0;
float ye=(float) 0.0;
float argom=(float) 0.0;
float sommadist = (float) 0.0;
float sommadistpe = (float) 0.0;
float mindistc=(float) 10000000.0;
int classeapp=0;
while (s<NUMCLASS)
{
while (z<llyl[s])
{
mindistc=(float) 1000000000.0;
xw = lly[s][z][dimx];
yw = lly[s][z][dimy];
while (s1<NUMCLASS)
{
sommadist=0;
sommadistpe=0;
while (z1<llyl[s1])
{
xe=lly[s1][z1][dimx];
ye=lly[s1][z1][dimy];
argom = ((xe - xw) * (xe - xw)) + ((ye -
yw)*(ye - yw));
sommadist = sommadist + sqrt(argom);
z1 = z1 + 1;
}
if (llyl[s1] > 0) sommadistpe =
(sommadist / llyl[s1]); // pesa la distanza e il numero dei campioni
if (sommadistpe < mindistc)
{
mindistc = sommadistpe;
classeapp = s1;
}
z1 = 0;
s1 = s1 + 1;
}
attc[s][z][0] = false;
if (classeapp == s) attc[s][z][0] = true;
z = z + 1;
z1=0;
s1=0;
}
progressbar(s,NUMCLASS);
s = s + 1;
z = 0;
}
}
void disattivapunti() // disattiva i punti ---> dalla theta crea
thetamod
{
creathetamod();
int s=0;
int z=0;
int s1=0;
int z1=0;
int z2=0;
float xw=(float)0.0;
float yw=(float) 0.0;
float xe=(float)0.0;
float ye=(float) 0.0;
float argom=(float) 0.0;
float sommadist = (float) 0.0;
float sommadistpe = (float) 0.0;
float mindistc=(float) 10000000.0;
int classeapp=0;
int ci=0;
while (s<NUMCLASS)
{
z2=0;
while (z<thetal[s])
{
mindistc=(float) 1000000000.0;
xw = theta[s][z][dimx];
yw = theta[s][z][dimy];
while (s1<NUMCLASS)
{
sommadist=0;
sommadistpe=0;
while (z1<thetal[s1])
{
xe=theta[s1][z1][dimx];
ye=theta[s1][z1][dimy];
argom = ((xe - xw) * (xe - xw)) + ((ye -
yw)*(ye - yw));
sommadist = sommadist + sqrt(argom);
z1 = z1 + 1;
}
if (thetal[s1] > 0) sommadistpe
= (sommadist / thetal[s1]); // pesa la distanza e il numero dei campioni
if (sommadistpe < mindistc)
{
mindistc = sommadistpe;
classeapp = s1;
}
z1 = 0;
s1 = s1 + 1;
}
att[s][z][0] = false;
if (classeapp == s)
{
att[s][z][0] = true;
while(ci < NUMPAR)
{
thetamod[s][z2][ci]=theta[s][z][ci];
ci=ci+1;
}
ci=0;
z2 = z2 + 1;
}
z = z + 1;
z1=0;
s1=0;
}
z = 0;
thetalmod[s] = z2;
z2=0;
progressbar(s,NUMCLASS);
s = s + 1;
}
s=0;
float
xx=0;
float
yy=0;
z=0; // MODIFICA
ci=0;
while (s<NUMCLASS)
{
thetal[s] = thetalmod[s];
while (z < thetalmod[s])
{
ci =
0;
while (ci<NUMPAR)
{
theta[s][z][ci]
= thetamod[s][z][ci];
ci =
ci + 1;
}
colorepenna(s);
colorepennello(s);
xx = thetamod[s][z][dimx];
yy = thetamod[s][z][dimy];
disegnaellisse
((xx*coeffmoltiplx+offsetx),(yy*coeffmoltiply+offsety),dimpunti);
z = z + 1;
}
z = 0;
s = s + 1;
}
}
char
*
conversione(int value)
{
char *c="";
if (value==0) c = "0";
if (value==1) c = "1";
if (value==2) c = "2";
if (value==3) c = "3";
if (value==4) c = "4";
if (value==5) c = "5";
if (value==6) c = "6";
if (value==7) c = "7";
if (value==8) c = "8";
if (value==9) c = "9";
if (value==10) c = "10";
if (value==25) c = "25";
if (value==50) c = "50";
if (value==75) c = "75";
if (value==100) c = "100";
return(c);
}
void
scriviparametri(RECT
rt)
{
char *testo[20];
int lp=0;
rt.top=finestray-10;
rt.bottom=finestray+5;
if (lop==0) testo[0] = "default";
if (lop==1) testo[0] = "k-means";
if (lop==2) testo[0] = "lloyd ";
if (tipoxv==0) testo[10] = "x -> v ";
if (tipoxv==1) testo[10] = "x -> v -> V";
if (tipoxv==2) testo[10] = "x -> X -> v";
if (voronoidaeseguire==0) testo[11] = " ";
if (voronoidaeseguire==1) testo[11] = "cl =";
testo[1] = "dim x =";
testo [2] =
conversione(dimx+1);
testo[3] = "dim y =";
testo [4] =
conversione(dimy+1);
testo[5] = "ftrd = ";
testo [6] = conversione(ftrd1);
testo[7] = "iter = ";
testo [8] = conversione(iterr);
testo [9] = "modo";
if (voronoidaeseguire==0) testo [12] = " ";
if (voronoidaeseguire==1) testo [12] = conversione(vcl+1);
rt.left=5;
rt.right=770;
DrawText(hdc,
"_______________________________________________________________________________________________________",85
, &rt, DT_CENTER);
rt.left=5;
rt.right=65;
DrawText(hdc, testo[0],strlen(testo[0]) ,
&rt, DT_CENTER);
rt.left=90;
rt.right=140;
DrawText(hdc, testo[1],strlen(testo[1]) ,
&rt, DT_CENTER);
rt.left=140;
rt.right=150;
DrawText(hdc, testo[2],strlen(testo[2]) ,
&rt, DT_CENTER);
rt.left=165;
rt.right=215;
DrawText(hdc, testo[3],strlen(testo[3]) ,
&rt, DT_CENTER);
rt.left=215;
rt.right=225;
DrawText(hdc, testo[4],strlen(testo[4]) ,
&rt, DT_CENTER);
rt.left=230;
rt.right=280;
DrawText(hdc, testo[5],strlen(testo[5]) ,
&rt, DT_CENTER);
rt.left=280;
rt.right=305;
DrawText(hdc, testo[6],strlen(testo[6]) ,
&rt, DT_CENTER);
rt.left=310;
rt.right=365;
DrawText(hdc, testo[7],strlen(testo[7]) ,
&rt, DT_CENTER);
rt.left=365;
rt.right=390;
DrawText(hdc, testo[8],strlen(testo[8]) ,
&rt, DT_CENTER);
rt.left=410;
rt.right=460;
DrawText(hdc, testo[9],strlen(testo[9]) ,
&rt, DT_CENTER);
rt.left=460;
rt.right=535;
DrawText(hdc, testo[10],strlen(testo[10])
, &rt, DT_CENTER);
rt.left=540;
rt.right=590;
DrawText(hdc, testo[11],strlen(testo[11])
, &rt, DT_CENTER);
rt.left=590;
rt.right=610;
DrawText(hdc, testo[12],strlen(testo[12])
, &rt, DT_CENTER);
}
void progressbar(int par , int tot)
{
int gr=0;
double res;
RECT rt;
rt.top=finestray-10;
rt.bottom=finestray+5;
char *testo[1];
//testo[0]="____________";
rt.left=610;
rt.right=650;
DrawText(hdc,
"prog",strlen("prog") , &rt, DT_LEFT);
rt.left=650;
rt.right=770;
//if (tot == 0) return;
res = (par*10) / tot;
gr = (int) res;;
if (gr==0) testo[0]="";
if (gr==1) testo[0]="*";
if (gr==2) testo[0]="**";
if (gr==3) testo[0]="***";
if (gr==4) testo[0]="****";
if (gr==5) testo[0]="*****";
if (gr==6) testo[0]="******";
if (gr==7) testo[0]="*******";
if (gr==8) testo[0]="********";
if (gr==9) testo[0]="*********";
if (gr==10) testo[0]=" ";
DrawText(hdc, testo[0],strlen(testo[0]) ,
&rt, DT_LEFT);
}
float
bisettrice(float
k1 , float k2)
{
float k11 = 0;
float k22 = 0;
float k3 = 0;
k11 = atan(k1);
k22 = atan(k2);
k3 = tan((k2 - k1));
return (k3);
}
int intersezione(int k1, int k2) // passare gli
indici della matrice
{
float k11 = 0;
float k12 = 0;
float k22 = 0;
float x1 = 0;
float x2 = 0;
float y1 = 0;
float y2 = 0;
float x11 = 0;
float x22 = 0;
float y11 = 0;
float y22 = 0;
float tmp = 0;
int k3 = 0;
k11 = ((vor[k2][1] - vor [k1][1]) / (vor
[k1][0] - vor [k2][0])); // valore x di intersezione
if ((k11 < 0) || (k11 > finestrax)) return (0); //
non si interscano nella finestra
k12
= (vor[k2][0]*k11) + vor[k2][1];
if ((k12 < 0) || (k12 > (finestray-10))) return (0); //
non si interscano nella finestra
x1 = vor [k1][2]; // inizio
x2 = vor [k1][4]; // fine
y1 = vor [k1][3];
y2 = vor [k1][5];
x11 = vor [k2][2]; // inizio
x22 = vor [k2][4]; // fine
y11 = vor [k2][3];
y22 = vor
[k2][5];
if (x1 > x2)
{ // ordina i punti dei segmenti
tmp =
x2;
x2 =
x1;
x1 =
tmp;
}
if
(x11
> x22)
{
tmp =
x22;
x22 =
x11;
x11 = tmp;
}
if (y1 > y2)
{
tmp = y2;
y2 = y1;
y1 = tmp;
}
if (y11 > y22)
{
tmp = y22;
y22 = y11;
y11 = tmp;
}
intersx = k11; // punti di
intersezione tra le 2 rette
intersy
= k12;
tmp =
0;
if
((x1
< k11) && (x2 > k11) && (x11 < k11) && (x22
> k11)) tmp = 1;
if
(tmp ==
0) return (0);
tmp = 0;
if ((y1 < k12) && (y2 > k12)
&& (y11 < k12) && (y22 > k12)) tmp = 1;
if
(tmp ==
0) return (0);
intersx = k11; // punti di
intersezione tra le 2 rette
intersy
= k12;
return
(1);
}
void matricecalcolata(float ***lly) //
Ordina la matrice lly !!!!
{
float precedente = 0;
float temporanea = 0;
float precedentey = 0;
float temporaneay = 0;
float xx=0;
float yy=0;
int s = 0;
int z = 0;
int r = 0;
int ci = 0;
float m=0;
float mp=0;
float pq=0;
float px=0;
float py=0;
float pg=0;
float pg1=0;
// dalla dimensione x piccola alla piu' grande
s=0;
z=1; // importante inizializzazione
while (s
< NUMCLASS)
{
while (r < llyl[s])
{
while (z < llyl[s])
{
precedente = lly[s][z-1][dimx];
temporanea = lly[s][z][dimx];
precedentey = lly[s][z-1][dimy];
temporaneay = lly[s][z][dimy];
if (temporanea < precedente)
{
lly[s][z-1][dimx]=temporanea; // scambio x
e y
lly[s][z][dimx]=precedente;
lly[s][z-1][dimy]=temporaneay;
lly[s][z][dimy]=precedentey;
}
z = z+1;
}
z = 1;
r = r +1;
}
r=0;
s = s+1;
}
s=0;
z=0;
float bis=0;
// Qui inizia il calcolo di voronoi **** **** **** **** VORONOI
**** **** **** ****
if (voronoidaeseguire
== 0) return;
z=0;
int xs=0;
int ys=0;
double d = 0.0;
double dd = 0.0;
double dmin=0.0;
int pd=0;
int pdv=0;
int ghg=0;
double nx = 0.0;
double ny = 0.0;
double xr = 0.0;
double yr = 0.0;
s = vcl; // setta la classe da calcolare
if ((tipoxv == 0) || (tipoxv == 2))
{
while (xs < finestrax )
{
while (ys < (finestray-10))
{
z = 0;
pdv = pd;
while (z < llyl[vcl]) // llyl[vcl]
{
ghg = z; // discendente
nx = lly[vcl][ghg][dimx];
ny = lly[vcl][ghg][dimy];
xr = nx * coeffmoltiplx + offsetx;
yr = ny * coeffmoltiply + offsety;
//colorepenna(7);
//disegnaellisse(xr,yr,4);
d = (double) radicequadrata((double)
((xs - xr)*(xs - xr) + (ys - yr)*(ys-yr)));
if ((d < dmin) || (z == 0))
{
dmin = d;
pd = z;
}
z = z + 1;
}
z = 0;
colorepenna(pd+1+swp+vcl);
disegnaellisse(xs,ys,vdim);
if (pdv != pd)
{
colorepenna(0+swp);
disegnaellisse(xs,ys,2);
}
ys = ys + vpasso;
d=0.0;
dmin = 0.0;
}
ys=0;
xs = xs + vpasso;
progressbar(xs,finestrax);
dmin=0.0;
}
}
if ((tipoxv == 1))
{
while (xs < finestrax )
{
while (ys < (finestray-10))
{
z = 0;
pdv = pd;
while (z < llyl[vcl]) // llyl[vcl]
{
ghg = z;
if (attc[vcl][ghg][0] == true)
{
nx = lly[vcl][ghg][dimx];
ny = lly[vcl][ghg][dimy];
xr = nx * coeffmoltiplx + offsetx;
yr = ny * coeffmoltiply + offsety;
d = (double) radicequadrata((double)
((xs - xr)*(xs - xr) + (ys - yr)*(ys-yr)));
if ((d < dmin) || (z == 0))
{
dmin = d;
pd = z;
}
}
z = z + 1;
}
z = 0;
colorepenna(pd+1+swp+vcl);
disegnaellisse(xs,ys,vdim);
if (pdv != pd)
{
colorepenna(0+swp);
disegnaellisse(xs,ys,2);
}
ys = ys + vpasso;
d=0.0;
dmin = 0.0;
}
ys=0;
xs = xs + vpasso;
dmin=0.0;
}
}
if (vrid==1)
{
z=0; // ridisegna i campioni
while (z
< llyl[vcl])
{
if (tipoxv == 1)
{
if ((attc[vcl][z][0]) == true)
{
colorepenna(vcl);
colorepennello(vcl);
xx = lly[vcl][z][dimx];
yy = lly[vcl][z][dimy];
disegnaquadrato
((xx*coeffmoltiplx+offsetx),(yy*coeffmoltiply+offsety),dimcampioni);
}
}
if ((tipoxv == 0) || (tipoxv == 2))
{
colorepenna(vcl);
colorepennello(vcl);
xx = lly[vcl][z][dimx];
yy = lly[vcl][z][dimy];
disegnaquadrato
((xx*coeffmoltiplx+offsetx),(yy*coeffmoltiply+offsety),dimcampioni);
}
z = z + 1;
}
}
z=1;
s=vcl;
int cnt=0;
int itis=0;
int kuj=0;
//while (s < NUMCLASS)
if (vinters==1) {
while (z < llyl[s])
{
if (s==vcl)
{
xx = lly[vcl][z][dimx];
yy = lly[vcl][z][dimy];
vx = lly[vcl][z-1][dimx];
vy = lly[vcl][z-1][dimy];
xx = xx*coeffmoltiplx+offsetx;
yy = yy*coeffmoltiply+offsety;
vx = vx*coeffmoltiplx+offsetx;
vy = vy*coeffmoltiply+offsety;
px = ( xx + vx ) / 2;
py = ( yy + vy ) / 2;
m = ((yy - vy) / (xx - vx)); // retta
Y=mpX + pq
mp = - (1 / m); // coefficiente angolare
della retta
pq =
py - (mp * px); // punto di intersezione della retta
pg =
pq;
pg1 =
finestrax * mp + pq;
colorepenna(1);
if (vassi==1)
{
MoveToEx(hdc,
0 , pg , (LPPOINT) NULL);
LineTo(hdc,
finestrax , pg1 );
}
if (z == 1) // la prima
semiretta è sicuramente non intersecata
{
vor[z-1][0] = mp;
vor[z-1][1] = pq;
vor[z-1][2] = 0;
vor[z-1][3] = pg;
vor[z-1][4] = finestrax;
vor[z-1][5] = pg1;
}
if (z > 1)
{
int cnt1=0;
while (cnt < z)
{
cnt1 = (z-1) - cnt;
itis = intersezione(z-1, cnt1);
colorepenna(6);
colorepennello(6);
if (( itis == 1 ) &&
(vinters==1)) disegnaellisse(intersx-3,intersy-3,2);
if (itis == 0) // il segmento non interseca nessun altro
segmento
{
vor[z-1][0] = mp;
vor[z-1][1] = pq;
vor[z-1][2] = 0;
vor[z-1][3] = pg;
vor[z-1][4] = finestrax;
vor[z-1][5] = pg1;
}
if ((itis ==1 ))
{
kuj=1;
float pqa=0;
float pga=0;
bis = bisettrice(vor[z-1][0],vor[cnt1][0]);
pqa = intersy - (bis * intersx); // punto di intersezione della
retta
pga = finestrax * bis + pqa;
//colorepenna(2);
//MoveToEx(hdc, 0 , pqa , (LPPOINT) NULL);
//LineTo(hdc, finestrax , pga );
}
cnt = cnt + 1;
}
}
}
cnt =
0;
z = z + 1;
}
z = 1;
cnt = 0;
s = s + 1;
}
}
//function
prototypes
time_t
longtime;
float
coord_distance
(float a, float b)
{
return ( (a - b) * (a - b) ) ;
}
float
dist (float
*v1, float *v2)
{
int cont = 0;
float sum = 0;
while (cont<NUMPAR)
{
sum =
sum+coord_distance(v1[cont],v2[cont]);
cont = cont+1;
}
return (sum) ;
}
void
mindist
(float ***theta, float ***lly, int **md, int *thetal,
int *llyl, int nclasse)
{
int cont1 = 0,cont2=0;
float distanza = 9999;
while (cont1<thetal[nclasse])
{
while (cont2<llyl[nclasse])
{
if (dist (theta[nclasse][cont1],
lly[nclasse][cont2]) <distanza)
{
distanza =
dist(theta[nclasse][cont1],lly[nclasse][cont2]);
md[nclasse][cont1] = cont2;
}
cont2 = cont2+1;
}
cont1 = cont1+1;
cont2 = 0;
distanza = 9999;
}
}
void somma (float *v1, float *v2)
{
int cont = 0;
while (cont<NUMPAR)
{
v1[cont] = v1[cont]+v2[cont];
cont = cont+1;
}
}
void
calcola
(float *v1, float *sum, int n)
{
int cont = 0;
while (cont<NUMPAR)
{
v1[cont] = sum[cont]/n;
cont = cont+1;
}
}
void azzerav (float *v)
{
int cont = 0;
while (cont<NUMPAR)
{
v[cont] = 0;
cont = cont+1;
}
}
void
passo (float
***theta, float ***lly, int **md, int *thetal, int *llyl,
int nclasse)
{
printf("."); fflush(stdout);
//BY cout << "."; flush (cout) ;
int cont1 = 0,cont2=0;
float sum[10000];
int n = 0;
mindist (theta, lly, md, thetal, llyl,
nclasse) ;
while (cont1<llyl[nclasse])
{
azzerav (sum) ;
while (cont2<thetal[nclasse])
{
if (md[nclasse][cont2] == cont1)
{
n = n+1;
somma (sum, theta[nclasse][cont2]) ;
}
cont2 = cont2+1;
}
if (n != 0)
{
calcola (lly[nclasse][cont1], sum, n) ;
}
cont2 = 0;
n = 0;
cont1 = cont1+1;
}
}
void
azzeram
(float **m, int numpat)
{
int cont1 = 0,cont2=0;
while (cont1<numpat)
{
while (cont2<NUMPAR)
{
m[cont1][cont2] = 0;
cont2 = cont2+1;
}
cont1 = cont1+1;
cont2 = 0;
}
}
void
copiam
(float **m1, float **m2, int numpat)
{
int cont1 = 0,cont2=0;
while (cont1<numpat)
{
while (cont2<NUMPAR)
{
m1[cont1][cont2] = m2[cont1][cont2];
cont2 = cont2+1;
}
cont1 = cont1+1;
cont2 = 0;
}
}
int confronta (float **m1, float **m2,
int numpat)
{
int cont1 = 0,cont2=0,s=0;
while (cont1<numpat)
{
while (cont2<NUMPAR)
{
if (m1[cont1][cont2] != m2[cont1][cont2])
{
s = s+1;
}
cont2 = cont2+1;
}
cont1 = cont1+1;
cont2 = 0;
}
return (s) ;
}
void
algoritmo
(float ***theta, float ***lly, int **md, int *thetal,
int *llyl, int nclasse)
{
float **interna;
interna = new float*[llyl[nclasse]];
int cont = 0;
while (cont<llyl[nclasse])
{
interna[cont] = new float[NUMPAR];
cont = cont+1;
}
azzeram (interna,
llyl[nclasse]) ;
int confronto = 1;
while (confronto != 0)
{
copiam
(interna, lly[nclasse], llyl[nclasse]) ;
passo (theta,
lly, md, thetal, llyl, nclasse) ;
confronto =
confronta(interna,lly[nclasse],llyl[nclasse]);
}
}
void
lloyd (float
***theta, float ***lly, int **md, int *thetal, int *llyl)
{
int cont = 0;
while (cont<NUMCLASS)
{
algoritmo (theta, lly, md, thetal, llyl,
cont) ;
cont = cont+1;
}
}
void
copiav
(float *v1, float *v2)
{
int cont = 0;
while (cont<NUMPAR)
{
v1[cont] = v2[cont];
cont = cont+1;
}
}
void
crea (float
***theta, float ***lly, int *thetal, int *llyl)
{
int mod = 0;
int cont1 = 0,cont2=0,cont3=0;
while (cont1<NUMCLASS)
{
mod = thetal[cont1]/llyl[cont1];
while (cont2<llyl[cont1])
{
while (cont3<NUMPAR)
{
lly[cont1][cont2][cont3] =
theta[cont1][cont2*mod][cont3];
cont3 = cont3+1;
}
cont2
= cont2+1;
cont3 = 0;
}
cont1 = cont1+1;
cont2 = 0;
cont3 = 0;
}
}
void
creal (int
*thetal, int *llyl, int fatrid)
{
int cont = 0;
int fint = fatrid;
while (cont<NUMCLASS)
{
while ( (thetal[cont]/fint) == 0)
{
fint = fint-1;
}
llyl[cont] = (thetal[cont]/fint);
fint = fatrid;
cont = cont+1;
}
}
void
deltaw
(float *v1, float *v2, float epsilon)
{
int cont = 0;
while (cont<NUMPAR)
{
v1[cont] =
v1[cont]+(epsilon*(v2[cont]-v1[cont]));
cont = cont+1;
}
}
int
pvicino
(float *v, float **km, int kml)
{
int cont = 0;
int fine = 0;
float distanza = 9999;
while (cont<kml)
{
if (dist (v, km[cont]) <distanza)
{
distanza
= dist(v,km[cont]);
fine = cont;
}
cont = cont+1;
}
return (fine) ;
}
void
km (float
***theta, float ***km, int *thetal, int *kml, float
epsilon, int maxiter)
{
int cont1 = 0,cont2=0;
int buff = 0;
while (cont1<NUMCLASS)
{
while (cont2<thetal[cont1])
{
deltaw (km[cont1][pvicino
(theta[cont1][cont2], km[cont1], kml[cont1]) ], theta[cont1][cont2], epsilon) ;
cont2 = cont2+1;
}
buff = buff+1;
if (buff == maxiter)
{
buff = 0;
cont1 = cont1+1;
}
cont2 = 0;
}
}
void
creathetal
(int *thetal, char v[])
{
FILE *pippo;
int cont = 0,ci=0;
//float flo[3];
//float xx,yy,zz;
while (cont<NUMCLASS)
{
pippo = fopen(v,"rb");
float a = 0;
int b = 0;
int buf = 0;
while (!feof (pippo) )
{
fscanf (pippo, "%d", &b) ;
if ( (b - 1)
== cont) buf = buf+1;
ci = 0;
while (ci<NUMPAR)
{
fscanf (pippo, "%f", &a) ;
ci = ci+1;
}
}
fclose
(pippo) ;
thetal[cont] = buf;
buf = 0;
cont = cont+1;
}
}
void
creatheta
(float ***theta, char v[])
{
FILE *pippo;
int cont = 0;
double flo[13];
double xx,yy,xxx,yyy;
int bjt=0;
xxx=0;
yyy=0;
valoremaxx=-1000.0;// utili se il programma viene fatto girare
piu' volte
valoremaxy=-1000.0;
valoreminx=1000.0;
valoreminy=1000.0;
offsetx=0;
offsety=0;
// pezzo di calcolo per la
calibrazione della finestra (coefficienti moltiplicativi ed offset)
while (cont<NUMCLASS)
{
pippo = fopen(v,"rb");
float a = 0;
int b = 0;
int buf = 0,ci=0;
while (!feof (pippo) )
{
fscanf (pippo, "%d", &b) ;
if ( (b - 1)
== cont)
{
ci = 0;
while (ci<(NUMPAR))
{
fscanf (pippo, "%f", &a) ;
// ******************************************
if (ci ==0) flo[0]=a;
if (ci ==1) flo[1]=a;
if (ci ==2) flo[2]=a;
if (ci ==3) flo[3]=a;
if (ci ==4) flo[4]=a;
if (ci ==5) flo[5]=a;
if (ci ==6) flo[6]=a;
if (ci ==7) flo[7]=a;
if (ci ==8) flo[8]=a;
if (ci ==9) flo[9]=a;
if (((ci == (NUMPAR-1))))
{
xx = flo[dimx];
yy = flo[dimy];
if (xx > valoremaxx) valoremaxx=xx;
if (yy > valoremaxy)
valoremaxy=yy;
if (xx < valoreminx)
valoreminx=xx;
if (yy < valoreminy)
valoreminy=yy;
}
ci = ci+1;
}
buf = buf+1;
}
if ( (b - 1)
!= cont)
{
ci = 0;
while (ci < NUMPAR)
{
fscanf (pippo, "%f", &a) ;
ci = ci+1;
}
}
}
fclose
(pippo) ;
buf = 0;
cont = cont+1;
}
cont=0;
//valoremaxx=4;
//valoremaxy=4;
//valoreminx=1;
//valoreminy=-1;
valoretotale=valass(valoremaxx-valoreminx);
coeffmoltiplx = (double) valass(double(double
(finestrax) / (double)valoretotale));
offsetx = - valoreminx;
valoretotale=valass(valoremaxy-valoreminy);
coeffmoltiply = (double) valass(double(double((finestray-10))
/ (double)valoretotale));
offsety= - valoreminy;
//coeffmoltiplx=coeffmoltiplx/2;
offsetx=offsetx*coeffmoltiplx;
offsety=offsety*coeffmoltiply;
// pezzo originale
while (cont<NUMCLASS)
{
pippo = fopen(v,"rb");
float a = 0;
int b = 0;
int buf = 0,ci=0;
while (!feof (pippo) )
{
fscanf (pippo, "%d", &b) ;
if ( (b - 1)
== cont)
{
ci = 0;
while (ci<(NUMPAR))
{
fscanf (pippo, "%f", &a) ;
// ******************************************
if (ci ==0) flo[0]=a;
if (ci ==1) flo[1]=a;
if (ci ==2) flo[2]=a;
if (ci ==3) flo[3]=a;
if (ci ==4) flo[4]=a;
if (ci ==5) flo[5]=a;
if (ci ==6) flo[6]=a;
if (ci ==7) flo[7]=a;
if (ci ==8) flo[8]=a;
if (ci ==9) flo[9]=a;
if ((ci == (NUMPAR-1)))
{
xx = flo[dimx];
yy = flo[dimy];
if ((tipoxv == 0) || (tipoxv == 1))
{
colorepenna(cont);
colorepennello(cont);
disegnaellisse
((xx*coeffmoltiplx+offsetx),(yy*coeffmoltiply+offsety),dimpunti);
}
}
theta[cont][buf][ci] = a;
ci = ci+1;
}
buf = buf+1;
}
if ( (b - 1)
!= cont)
{
ci = 0;
while (ci<NUMPAR)
{
fscanf (pippo, "%f", &a) ;
ci = ci+1;
}
}
}
fclose
(pippo) ;
buf = 0;
cont = cont+1;
}
}
int contaclass (char v[])
{
FILE *pippo;
int fine = 0;
int cont = 0,ci=0;
pippo = fopen(v,"rb");
float a = 0;
int b = 0;
while (!feof (pippo) )
{
fscanf (pippo, "%d", &b) ;
if (b>fine) fine = b;
ci = 0;
while (ci<NUMPAR)
{
fscanf
(pippo, "%f", &a) ;
ci =
ci+1;
}
}
fclose (pippo) ;
cont = cont+1;
return (fine) ;
}
void
creafile
(char vin[], char vout[])
{
FILE *filein;
FILE *fileout;
char ci;
filein = fopen(vin,"rb");
fileout = fopen(vout,"w");
while (!feof (filein) )
{
fscanf
(filein, "%c", &ci) ;
if (ci != '#')
{
fprintf (fileout, "%c", ci) ;
}
if (ci == '#')
{
while (ci != '\n')
{
fscanf (filein, "%c", &ci) ;
}
}
}
fclose (filein) ;
fclose (fileout) ;
}
int contapar (char v[])
{
int nump = 0;
FILE *filein;
filein = fopen(v,"rb");
char ci = 'c';
while (ci != '\n')
{
fscanf
(filein, "%c", &ci) ;
if (ci == '.') nump = nump+1;
}
fclose (filein) ;
return (nump) ;
}
void
calibral
(int *llyl, int *calibl)
{
int cont = 0;
while (cont<NUMCLASS)
{
calibl[cont] = (llyl[cont]+1);
cont = cont+1;
}
}
void
calibra
(float ***theta, float ***lly, float ***calib, int *thetal,
int *llyl, int *calibl)
{
float mint[30][1000][10000];
int a1 = 0,a2=0;
int b1 = 0,b2=0;
float di = 999;
int classe = 999;
int conta = 0;
while (a1<NUMCLASS)
{
while (a2<thetal[a1])
{
di = 999;
while (b1<NUMCLASS)
{
while (b2<llyl[b1])
{
if (dist (theta[a1][a2], lly[b1][b2]) <di)
{
di = dist(theta[a1][a2],lly[b1][b2]);
classe = b1;
}
b2 = b2+1;
}
b2 = 0;
b1 = b1+1;
}
b2 = 0;
b1 = 0;
if (classe != a1)
{
copiav (mint[a1][conta], theta[a1][a2]) ;
if (conta<999) conta = conta+1;
}
classe
= 999;
di =
999;
a2 =
a2+1;
}
b2 = 0;
b1 = 0;
classe = 999;
di = 999;
a2 = 0;
a1 = a1+1;
}
conta = 0;
a1 = 0;
a2 = 0;
float x
= 1;
while (a1<NUMCLASS)
{
while (a2<llyl[a1])
{
copiav (calib[a1][a2], lly[a1][a2]) ;
a2 = a2+1;
}
a2 = 0;
a1 = a1+1;
}
a1 = 0;
a2 = 0;
b1 = 0;
int mint2l[30];
float mint2[30][10000];
while (a1<NUMCLASS)
{
while (a2<NUMPAR)
{
mint2[a1][a2] = 0;
a2 = a2+1;
}
a2 = 0;
a1 = a1+1;
}
a1 = 0;
a2 = 0;
while (a1<NUMCLASS)
{
while (b1<1000&&x != 0)
{
x = mint[a1][b1][0];
while (a2<NUMPAR)
{
mint2[a1][a2] =
mint2[a1][a2]+mint[a1][b1][a2];
a2 = a2+1;
}
a2 = 0;
b1 = b1+1;
}
mint2l[a1] = b1;
b1 = 0;
a2 = 0;
a1 = a1+1;
}
a1 = 0;
a2 = 0;
while (a1<NUMCLASS)
{
while (a2<NUMPAR)
{
mint2[a1][a2] =
(mint2[a1][a2]/mint2l[a1]);
a2 = a2+1;
}
a2 = 0;
a1 = a1+1;
}
a1 = 0;
while (a1<NUMCLASS)
{
copiav
(calib[a1][calibl[a1] - 1], mint2[a1]) ;
a1 = a1+1;
}
}
void
kmeans
(int friduzione, int iter, char vin[], char vout[])
{
float xx,yy,zz=0;
time (&longtime) ;
creafile (vin, vout) ;
NUMPAR = contapar(vout);
NUMCLASS = contaclass(vout);
//float ***theta;
//float ***lly;
int **md;
theta = new float**[NUMCLASS];
int s = 0;
int z = 0;
creathetal (thetal, vout) ;
while (s<NUMCLASS)
{
theta[s] =
new float*[thetal[s]];
while (z<thetal[s])
{
theta[s][z] = new float[NUMPAR];
z = z+1;
}
z = 0;
s = s+1;
}
creatheta (theta, vout) ;
lly = new float**[NUMCLASS];
creal
(thetal, llyl, friduzione) ;
s = 0;
z = 0;
while (s<NUMCLASS)
{
lly[s] =
new float*[llyl[s]];
while (z<llyl[s])
{
lly[s][z] = new float[NUMPAR];
z = z+1;
}
z = 0;
s = s+1;
}
md = new int*[NUMCLASS];
s = 0;
z = 0;
while (s<NUMCLASS)
{
md[s] = new int[thetal[s]];
s = s+1;
}
crea (theta, lly, thetal, llyl) ;
if (tipoxv == 2)
{
creaatt();
disattivapunti();
// disattiva i punti
}
km (theta, lly, thetal, llyl, (float).1,
iter) ; // chiama la procedura di calcolo
FILE *uscita;
uscita =
fopen(vout,"w");
fprintf (uscita, "# VQ
Date : %s", ctime (&longtime) ) ;
FILE *entrata;
entrata =
fopen(vin,"rb");
char ki = 'p';
while (!feof (entrata) )
{
fscanf
(entrata, "%c", &ki) ;
if (ki == '#')
{
while (ki != '\n')
{
fscanf (entrata, "%c", &ki) ;
}
ki = 'p';
while (ki != '\n')
{
// scrive i commenti
iniziali
fscanf (entrata, "%c", &ki) ;
fprintf (uscita, "%c", ki) ;
}
ki = 'p';
while (ki != '\n')
{
fscanf (entrata, "%c", &ki) ;
}
}
}
fclose (entrata) ;
entrata =
fopen(vin,"rb");
char si = 'p';
while (si != '\n')
{
fscanf
(entrata, "%c", &si) ;
}
si = 'p';
while (si != '\n')
{
fscanf
(entrata, "%c", &si) ;
}
si = 'p';
while (si != '\n')
{
fscanf
(entrata, "%c", &si) ;
// scrive
commento
fprintf
(uscita, "%c", si) ;
}
fclose (entrata) ;
s = 0;
z = 0;
int ci = 0;
if (tipoxv
== 1)
{ // ************** ******** *********
creaattc();
disattivacampioni();
}
while (s<NUMCLASS)
{
while (z<llyl[s])
{
//
************************************
numero classe
if ((tipoxv ==0) || (tipoxv == 2))
{
fprintf
(uscita, "%d ", (s + 1) ) ;
}
if (tipoxv == 1)
{
if (attc[s][z][0] == true)
{
fprintf
(uscita, "%d ", (s + 1) ) ;
}
}
ci =
0;
while (ci<NUMPAR)
{
if ((tipoxv ==0) || (tipoxv == 2))
{
fprintf (uscita, "%f ", lly[s][z][ci]) ; // scrive i
numeri
}
if (tipoxv == 1)
{
if (attc[s][z][0] == true)
{
fprintf (uscita, "%f ", lly[s][z][ci]) ; // scrive i
numeri
}
}
if ((ci == 0))
{
xx = lly[s][z][dimx];
yy = lly[s][z][dimy];
//if (voronoidaeseguire==1)
voronoi(xx*coeffmoltiplx+offsetx,yy*coeffmoltiply+offsety,s);
if ((tipoxv ==0) || (tipoxv == 2))
{
colorepenna(s);
colorepennello(s);
disegnaquadrato
((xx*coeffmoltiplx+offsetx),(yy*coeffmoltiply+offsety),dimcampioni);
}
if (tipoxv == 1)
{
if (attc[s][z][0] == true)
{
colorepenna(s);
colorepennello(s);
disegnaquadrato
((xx*coeffmoltiplx+offsetx),(yy*coeffmoltiply+offsety),dimcampioni);
}
}
}
ci = ci+1;
}
if ((tipoxv ==0) || (tipoxv == 2))
{
fprintf
(uscita, "\n") ;
}
if (tipoxv == 1)
{
if (attc[s][z][0] == true)
{
fprintf
(uscita, "\n") ;
}
}
z =
z+1;
}
z = 0;
progressbar(s,NUMCLASS);
s = s+1;
}
//matricecalcolata(lly);
fclose (uscita) ;
/* begin CONFRONTO
printf ("\n\nInizio confronto\n\n") ;
int a1 = 0,a2=0;
int b1 = 0,b2=0;
int conteggio = 0;
float di = 999;
int classe = 999;
while (a1<NUMCLASS)
{
while (a2<thetal[a1])
{
di = 999;
while
(b1<NUMCLASS)
{
while
(b2<llyl[b1])
{
if
(dist (theta[a1][a2], lly[b1][b2]) <di)
{
di
= dist(theta[a1][a2],lly[b1][b2]);
classe
= b1;
}
b2 = b2+1;
}
b2 = 0;
b1 = b1+1;
}
b2 = 0;
b1 = 0;
if (classe != a1) conteggio =
conteggio+1;
classe = 999;
di = 999;
a2 = a2+1;
}
b2 = 0;
b1 = 0;
classe = 999;
di = 999;
a2 = 0;
a1 = a1+1;
}
printf ("\n\nPUNTI ERRATI : %d\n\n", conteggio)
;
*/
}
void lloyd (int friduzione, char vin[], char vout[])
{
time (&longtime) ;
creafile (vin, vout) ;
NUMPAR = contapar(vout);
NUMCLASS = contaclass(vout);
//float ***theta;
//float ***lly;
//int **md;
//int thetal[30];
theta = new float**[NUMCLASS];
int s = 0;
int z = 0;
creathetal (thetal, vout) ;
while (s<NUMCLASS)
{
theta[s] =
new float*[thetal[s]];
while (z<thetal[s])
{
theta[s][z] = new float[NUMPAR];
z = z+1;
}
z = 0;
s = s+1;
}
creatheta (theta, vout) ;
lly = new float**[NUMCLASS];
creal
(thetal, llyl, friduzione) ;
s = 0;
z = 0;
while (s<NUMCLASS)
{
lly[s] =
new float*[llyl[s]];
while (z<llyl[s])
{
lly[s][z] = new float[NUMPAR];
z = z+1;
}
z = 0;
s = s+1;
}
md = new int*[NUMCLASS];
s = 0;
z = 0;
while (s<NUMCLASS)
{
md[s] = new int[thetal[s]];
s = s+1;
}
crea (theta, lly, thetal, llyl) ;
if (tipoxv == 2)
{
luy = true;
creaatt();
disattivapunti(); //
disattiva i punti
}
lloyd (theta, lly, md, thetal,
llyl) ; // calcola lloyd
// (theta, lly, thetal, llyl)
luy = false;
/* BEGIN CALIBRATION
printf ("\n\n Inizio calibrazione \n\n") ;
float ***calib;
int calibl[NUMCLASS];
calibral (llyl, calibl) ;
calib = new float**[NUMCLASS];
s = 0;
z = 0;
while (s<NUMCLASS)
{
calib[s] = new float*[calibl[s]];
while (z<calibl[s])
{
calib[s][z]
= new float[NUMPAR];
z = z+1;
}
z = 0;
s = s+1;
}
calibra (theta, lly, calib, thetal,
llyl, calibl) ;
*/
FILE *uscita;
uscita =
fopen(vout,"w");
fprintf (uscita, "# VQ
Date : %s", ctime (&longtime) ) ;
FILE *entrata;
entrata =
fopen(vin,"rb");
char ki = 'p';
while (!feof (entrata) )
{
fscanf
(entrata, "%c", &ki) ;
if (ki == '#')
{
while (ki != '\n')
{
fscanf (entrata, "%c", &ki) ;
}
ki = 'p';
while (ki != '\n')
{
fscanf (entrata, "%c", &ki) ;
fprintf (uscita, "%c", ki) ;
}
ki = 'p';
while (ki != '\n')
{
fscanf (entrata, "%c", &ki) ;
}
}
}
fclose (entrata) ;
entrata =
fopen(vin,"rb");
char si = 'p';
while (si != '\n')
{
fscanf (entrata, "%c", &si) ;
}
si = 'p';
while (si != '\n')
{
fscanf
(entrata, "%c", &si) ;
}
si = 'p';
while (si != '\n')
{
fscanf
(entrata, "%c", &si) ;
fprintf
(uscita, "%c", si) ;
}
fclose (entrata) ;
s = 0;
z = 0;
int ci = 0;
if (tipoxv
== 1)
{ // ************** ******** *********
creaattc();
disattivacampioni();
}
while (s<NUMCLASS)
{
while (z<llyl[s])
{
if ((tipoxv ==0) || (tipoxv == 2))
{
fprintf
(uscita, "%d ", (s + 1) ) ;
}
if (tipoxv == 1)
{
if (attc[s][z][0] == true)
{
fprintf
(uscita, "%d ", (s + 1) ) ;
}
}
ci =
0;
while (ci<NUMPAR)
{
float xx=0;
float yy=0;
if ((tipoxv ==0) || (tipoxv == 2))
{
fprintf (uscita, "%f ", lly[s][z][ci]) ;
}
if (tipoxv == 1)
{
if (attc[s][z][0] == true)
{
fprintf (uscita, "%f ", lly[s][z][ci]) ;
}
}
if ((ci == 0))
{
xx = lly[s][z][dimx];
yy = lly[s][z][dimy];
//if (voronoidaeseguire==1) voronoi(xx*coeffmoltiplx+offsetx,yy*coeffmoltiply+offsety,s);
if ((tipoxv ==0) || (tipoxv == 2))
{
colorepenna(s);
colorepennello(s);
disegnaquadrato
((xx*coeffmoltiplx+offsetx),(yy*coeffmoltiply+offsety),dimcampioni);
}
if (tipoxv == 1)
{
if (attc[s][z][0] == true)
{
colorepenna(s);
colorepennello(s);
disegnaquadrato
((xx*coeffmoltiplx+offsetx),(yy*coeffmoltiply+offsety),dimcampioni);
}
}
}
ci = ci+1;
}
if ((tipoxv ==0) || (tipoxv == 2))
{
fprintf
(uscita, "\n") ;
}
if (tipoxv == 1)
{
if (attc[s][z][0] == true)
{
fprintf
(uscita, "\n") ;
}
}
z =
z+1;
}
z = 0;
progressbar(s,NUMCLASS);
s = s+1;
}
//matricecalcolata(lly);
fclose (uscita) ;
/* begin CONFRONTO
printf ("\n\nInizio confronto\n\n") ;
int a1 = 0,a2=0;
int b1 = 0,b2=0;
int conteggio = 0;
float di = 999;
int classe = 999;
while (a1<NUMCLASS)
{
while (a2<thetal[a1])
{
di = 999;
while
(b1<NUMCLASS)
{
while
(b2<llyl[b1])
{
if
(dist (theta[a1][a2], lly[b1][b2]) <di)
{
di
= dist(theta[a1][a2],lly[b1][b2]);
classe
= b1;
}
b2
= b2+1;
}
b2
= 0;
b1
= b1+1;
}
b2 = 0;
b1 = 0;
if (classe != a1) conteggio =
conteggio+1;
classe = 999;
di = 999;
a2 = a2+1;
}
b2 = 0;
b1 = 0;
classe = 999;
di = 999;
a2 = 0;
a1 = a1+1;
}
printf ("\n\nPUNTI ERRATI : %d\n\n", conteggio)
;
*/
}
//
Inizio MAIN
void
main1
()
{
if ( (lork == 'k') )
{
//printf("\nComputing");
fflush(stdout);
//BY cout <<
"\nComputing"; flush (cout) ;
lloyd (ftrd , "dati.trn",
"out.out") ;
//printf ("\n\n") ;
}
if ( ( lork= 'l') )
{
//printf ("\nComputing") ;
kmeans (ftrd , 100, "dati.trn",
"out.out") ;
//printf ("\n\n") ;
}
}
void salva(char vin[], char vout[])
{
if (done==0) return;
int s=0;
int z=0;
int ci=0;
FILE *uscita;
uscita =
fopen(vout,"w");
fprintf (uscita, "# VQ
Date : %s", ctime (&longtime) ) ;
FILE *entrata;
entrata = fopen(vin,"rb");
char ki = 'p';
while (!feof (entrata) )
{
fscanf
(entrata, "%c", &ki) ;
if (ki == '#')
{
while (ki != '\n')
{
fscanf (entrata, "%c", &ki) ;
}
ki = 'p';
while (ki != '\n')
{
fscanf (entrata, "%c", &ki) ;
fprintf (uscita, "%c", ki) ;
}
ki = 'p';
while (ki != '\n')
{
fscanf (entrata, "%c", &ki) ;
}
}
}
fclose (entrata) ;
entrata =
fopen(vin,"rb");
char si = 'p';
while (si != '\n')
{
fscanf
(entrata, "%c", &si) ;
}
si = 'p';
while (si != '\n')
{
fscanf
(entrata, "%c", &si) ;
}
si = 'p';
while (si != '\n')
{
fscanf
(entrata, "%c", &si) ;
fprintf
(uscita, "%c", si) ;
}
fclose (entrata) ;
while (s<NUMCLASS)
{
while (z<llyl[s])
{
if ((tipoxv ==0) || (tipoxv == 2))
{
fprintf
(uscita, "%d ", (s + 1) ) ;
}
if (tipoxv == 1)
{
if (attc[s][z][0] == true)
{
fprintf
(uscita, "%d ", (s + 1) ) ;
}
}
ci =
0;
while (ci<NUMPAR)
{
float xx=0;
float yy=0;
if ((tipoxv ==0) || (tipoxv == 2))
{
fprintf (uscita, "%f ", lly[s][z][ci]) ;
}
if (tipoxv == 1)
{
if (attc[s][z][0] == true)
{
fprintf (uscita, "%f ", lly[s][z][ci]) ;
}
}
ci = ci+1;
}
if ((tipoxv ==0) || (tipoxv == 2))
{
fprintf
(uscita, "\n") ;
}
if (tipoxv == 1)
{
if (attc[s][z][0] == true)
{
fprintf
(uscita, "\n") ;
}
}
z = z+1;
}
z = 0;
s = s+1;
}
fclose (uscita) ;
}
int
APIENTRY
WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE,
szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_MERDA,
szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance,
(LPCTSTR)IDC_MERDA);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd,
hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage is only
necessary if you want this code
// to be compatible with Win32 systems prior
to the 'RegisterClassEx'
// function that was added to Windows 95. It
is important to call this function
// so that the application will get 'well
formed' small icons associated
// with it.
//
ATOM
MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_MERDA);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (LPCSTR)IDC_MERDA;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance,
(LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates
main window
//
// COMMENTS:
//
// In this function, we save the instance
handle in a global variable and
// create and display the main program window.
//
BOOL
InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance
handle in our global variable
hWnd = CreateWindow(szWindowClass,
szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL,
NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// PURPOSE:
Processes messages for the main window.
//
// WM_COMMAND -
process the application menu
// WM_PAINT -
Paint the main window
// WM_DESTROY -
post a quit message and return
//
//
LRESULT
CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int iu;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello,
MAX_LOADSTRING);
switch (message)
{
case WM_COMMAND:
wmId
= LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd,
(DLGPROC)About);
//param2 = TRUE;
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case PARAMETRO1:
//DialogBox(hInst, (LPCTSTR)FINESTRAPARAMETRO1, hWnd,
(DLGPROC) fatridfin);
//iu = EndDialog(hWnd,IDC_RADIO1);
ftrd1 = (int) 10;
//iu = InvalidateRgn(hWnd, NULL, 1);
break;
case PARAMETRO2:
ftrd1 = 25;
done=0;
break;
case PARAMETRO3:
ftrd1 = 50;
done=0;
break;
case PARAMETRO4:
ftrd1 = 75;
done=0;
break;
case PARAMETRO5:
ftrd1 = 100;
done=0;
break;
case PARAMETRO11:
iterr = (int) 10;
done=0;
break;
case PARAMETRO12:
iterr = 25;
done=0;
break;
case PARAMETRO13:
iterr = 50;
done=0;
break;
case PARAMETRO14:
iterr = 75;
done=0;
break;
case PARAMETRO15:
iterr = 100;
done=0;
break;
case PARAMETRO21:
dimx = 0;
done = 0;
break;
case PARAMETRO22:
dimx = 1;
done = 0;
break;
case PARAMETRO23:
dimx = 2;
done = 0;
break;
case PARAMETRO24:
dimx = 3;
done = 0;
break;
case PARAMETRO25:
dimx = 4;
done = 0;
break;
case PARAME