Tehnologiile din ziua de astăzi evoluează rapid. În ultimii ani recunoașterea de imagini folosind tehnici de machine learning începe să fie cât mai răspândită, cu rezultate notabile. Aplicația pe care urmează să o prezint va avea un microserviciu bazat pe Java ce va conține un microserviciu de calcul și un microserviciu bazat pe Python, acesta făcând clasificarea și recunoașterea imaginilor.
Aplicația Smart-wallet (Portofel Smart) poate reprezenta un portofel al viitorului care să ne ia din atribuții și care ne poate economisi timp.
Referitor la limbajele de programare tip static-typed (ex. Java), până acum câțiva ani, paradigma OOP (programarea orientată către obiect ) domina piața. Astfel, realitatea este modelată printr-un obiect care poate avea atribute și metode. Referințele sau pointerii pointau către astfel de obiecte aflate în memorie. Programarea funcțională permite lucrul cu funcții anonime (numite și lambda functions) și cu referințe la obiecte tip function (function reference). Avantajele sunt multiple:
Funcții ușor de citit (cu semnătura clară);
Codul este mai ușor de citit (ex: lucrul cu streams);
Compoziția de funcții;
Atributele unui obiect pot fi funcții, în loc de primitive sau obiecte;
Programarea în paralel (eg.parallel streams);
Această schimbare necesită și o modificare în gândirea programatorului obișnuit cu paradigma OOP. Atunci când alte limbaje au introdus programarea funcțională, Java a primit acest update sub forma interfețelor funcționale.
Exemplu:
a. Astfel putem asigna unei variabile (de tip functional interface), o funcție lambda : Function adunare=(a,b)->a+b;
b. function reference operator
List collectorCollection =
productList
.stream()
.map(Product::getName)
.collect(Collectors.toList());
operații cu streams
Map>
collectorMapOfLists =
productList
.stream()
.collect(Collectors
.groupingBy(Product::getPrice));
Clasificarea de imagini poate fi obținută cu ajutorul rețelelor neuronale .
Proiectul folosește o rețea neuronală convoluțională (CNN)**, deoarece aceasta se adaptează foarte bine la acest tip de problemă: clasificarea imaginilor. Vom avea 9- 10 clase de clasificare, de la 0,1,2 … 9 .
La intrare, avem imagini și la ieșire numere. Microserviciul va recunoaște numerele din imagine și le va returna ca numere întregi.
Antrenarea modelului se face după datasetul MNIST.
Exemple de imagini din datasetul MNIST:
Aplicația folosește două microservicii:
Realizează preluarea imaginilor de pe telefon și parsarea lor cu ajutorul microserviciului de recunoaștere imagini.
Aplicația web comunică prin protocol REST. La intrare va avea imagini cu prețul produselor, iar la ieșire vom avea suma produselor cumpărate și balanța finală la smart wallet (portofel inteligent).
Avantajele programării funcționale sunt folosite cu succes.
În programarea OOP am fi avut un obiect care avea două atribute: prețul și operația. Folosim strategy design pattern în stil funcțional pentru a crea un function object care își poate păstra operația și prețul produsului, totul într-o funcție :
public interface FunctionalItem extends
Function {
static FunctionalItem of(ItemDTO item) {
if (Constants.PLUS_OPERATION
.equalsIgnoreCase(item.getOperation())) {
return (x) -> x + parseNumberFromImage(item);
}
return (x) -> x - parseNumberFromImage(item);
}
Dorim să facem o dependință între ConvertorServiceImpl și instanțele din Currency, pentru a forța programatorul, ca de fiecare dată când introduce o monedă nouă, să ofere și funcționalitatea aferentă. Acest scenariu poate fi modelat prin păstrarea unei funcții într-o structură Enum:
public enum Currency {
GBP_TO_EURO(
(ConvertorService convertorService, Double amount) ->
convertorService.convertGBPToEuro(amount)),
...
private BiFunction operation;
Currency(BiFunction operation) {
this.operation = operation;
}
Apelul din serviciu se face astfel:
public double getAmountInEuro(Double
totalAmountFromClient, String currency) {
if (GBP_CURRENCY.equalsIgnoreCase(currency)) {
return Currency.GBP_TO_EURO.getOperation()
.apply(this, totalAmountFromClient);
}
Vom folosi frameworkul Keras, care este on top la TensorFlow(GOOGLE), limbajul de programare utilizat fiind Python.
După ce modulul este antrenat să recunoască imagini, acesta poate fi folosit să producă predicții ale unor poze cu imagini nemaivăzute anterior.
Imaginile de intrare în acest modul necesită scalare, deoarece Datasetul MNIST conține imagini cu cifre scrise de mână la rezoluție mică (28x28). Mai jos putem observa imaginea cu cifra 3 (desenată de noi în Paint/ scris de mână) scalată pentru modulul de recunoaștere.
La ieșirea microserviciului, va rezulta cifra 3.
Astfel putem evidenția puterea mecanismului de recunoaștere a imaginilor: am antrenat un model de rețele neuronale convoluționale cu imagini conținând numere scrise de mână, iar când i-am oferit o imagine nemaivăzută înainte, microserviciul a fost în stare să identifice numărul din imagine.
Mai jos, putem observa modelul rețelei neuronale convoluționale folosite:
Modelul are:
layer de convoluție;
layer de max pooling;
layer de convoluție;
layer de max pooling;
Flattened layer- aplatizare;
Un layer de 1024 de neuroni;
În timpul antrenării, modelul învață diferite patternuri din imaginile de training. Pentru predicție, imaginea de la intrare trece printr-un proces de convoluție. Acesta stabilește o fereastră de 5x5 care parcurge imaginea și caută patternuri cunoscute. Apoi urmează procesul de max pooling care comprimă datele de căutare, iar procesul se repetă pentru următoarele două straturi (layers).
Funcția de activare între straturile de neuroni este "RELU", iar modelul face optimizare de tip "ADAM". Ultimele două layere sunt cu neuroni, iar la sfârșitul acestora va rezulta categoria prezisă de rețeaua neuronală. Această categorie poate fi un text sau un număr. În cazul proiectului smart wallet, ieșirea va fi un număr. După cum se observă și în imaginea de mai sus, pentru imaginea de la intrare, va rezulta cifra 2. Acesta din urma va fi returnat către primul microserviciu de calcul și salvare în baza de date.
Aplicația poate primi imagini cu prețul produsului scris de mână/tipărit, sau cu produsul, sau cu codul său de bare.
Magazinul poate avea o zonă ce poate comunica prin RFID cu telefonul când clientul trece prin acea zonă, plata se poate efectua wireless, fără a mai fi nevoie de case de marcat. (Chitanța poate fi trimisă pe e-mail. Salvăm și pădurea!)
Aplicația poate fi îmbunătățită spre a fi folosită în cadrul unui proces industrial pentru recunoașterea de imagini cu diferite piese din producție, ex:
poate detecta piese OK sau NOK;
poate număra piese, grupuri de piese;
poate verifica corectitudinea marcajelor (printate sau scrise cu laser);
Codul proiectului poate fi găsit pe GIT: