Za razvoj aplikacije smo uporabili programsko orodje SICK AppStudio, kjer se ob kreiranju novega projekta samodejno ustvarijo mapepages,parameters, resources in scripts, kar poskrbi za strukturiran razvoj. Struktura projekta je vidna na sliki 4.3. V mapi pages so datoteke, ki služijo kot prednji del (angl. front-end) aplikacije. V njej so datoteke s končnicama .html in .css, s katerimi lahko oblikujemo videz končnega produkta. Programsko orodje nam
Diplomska naloga 21
Slika 4.1: Prikaz povezav na industrijski računalnik SICK SIM4000.
pri oblikovanju prednjega dela omogoča delo z gradniki s funkcijo vlečenja (angl. drag-and-drop) gradnikov v polje in povezavo gradnikov z zalednim delom (angl. back-end) aplikacije, kar je prikazano na sliki 4.2. Na podlagi gradnikov se v ozadju generira HTML koda, ki se jo lahko poljubno ureja.
Spodaj prikazana datoteka z gradniki main.html je glavna stran aplikacije, kjer so implementirane skoraj vse glavne funkcionalne zahteve. Poleg tega se v mapi nahajata še datoteki Nastavitve.html, ki je namenjena upravljanju nastavitev kamere, in primerjava.html, ki znotraj aplikacije odpre spletno stran, kjer so prikazani zapisi prejšnjih meritev.
V mapi scripts imamo glavne datoteke, potrebne za delovanje zalednega dela aplikacije, ki so spisane v programskem jezikuLua. Datotekafunkcije.
luavsebuje funkcije, napisane po meri za lažje pisanje algoritmov, ki vklju-čujejo matematične operacije, delo s tabelami, pretvarjanje tabel v format JSON ter grafičen prikaz besedila in ostalih elementov na sliki. Ker Lua ni
Slika 4.2: Videz gradnikov v datoteki main.html.
najbolj prijazen programski jezik za delo s podatki v JSON formatu, je vklju-čena datoteka json.lua, ki omogoča obdelavo podatkov v tem formatu. V HTTPClientSample.Lua so napisani protokoli in funkcije za izvoz podatkov v podatkovno bazo prek zahtevka POST. V datoteki kamera.lua so napi-sane skripte za nastavitev kamere, kot tudi njeno delovanje. Vse omenjene datoteke so vključene v glavno datotekosvigelj_termo.lua, ki je izvršljiva datoteka in hkrati tudi osrčje aplikacije. V njej so napisani sami algoritmi za obdelavo slik, delo s slikami, uvažanjem in izvažanjem, prižiganjem in ugašanjem kamere ipd.
Mapa resources vsebuje datoteko cacert.pem, v kateri so navedeni naj-pogostejši strežniški certifikati, izvoženi iz brskalnika Mozilla Firefox [1], kar omogoča zapis meritev v podatkovno bazo prek protokola https. Ostane še mapaparameters z datotekoparametri.cid.xml, kjer so shranjeni parame-tri s privzetimi vrednostmi, kot so mejna vrednost pri binarizaciji, meritve površine področja in definicija raztezka.
Pri diplomskem delu smo, kot je bilo omenjeno prej, uporabili kamero FLIR A615 in za njo spisali skripto, ki omogoča zagon kamere in njeno upo-rabo v aplikaciji. Najprej smo računalniku SIM4000 povedali, na kateri ether-net priključek je kamera priklopljena z ukazom powerOE = Connector.Power.create(’POE3’)in ji nastavili IP naslovCAM1_
Diplomska naloga 23
Slika 4.3: Videz strukture delovne mape.
IP=’192.168.100.251’. Kamera se seveda ne zažene takoj, temveč za za-gon potrebuje nekaj časa. Ugotovili smo, da je optimalno, da zaustavimo izvajanje skripte za 5 sekund, da se med tem časom kamera popolnoma
zažene in pripravi za delovanje. Nato smo kameri z ukazom configK1 = Image.Provider.RemoteCamera.GigEVisionConfig.create()dali navodilo, da naj dela v SICK AppSpace okolju in naj zajeto sliko predstavi na gradniku oziroma pregledovalnikuViewer2D. Nastavitev kamere lahko vidimo v izseku 4.1. -- local CAM1_IP = ’192.168.100.251’
CAM1_IP = change
Za filter slike smo uporabili sivinski filter (angl. grayscale). Za funk-cijo vklop in izklop kamere smo uporabili kratek pogojni stavek v funkciji connect(), ki se izvede, ko uporabnik klikne na gumb „Kamera“, ki ka-mero, odvisno od stanja, vklopi ali izključi in tudi primerno obarva kazalnik Kamera_status glede na to, ali je kamera vklopljena ali izklopljena. Nena-zadnje smo dodali še funkcijo handleNewImage(), ki pošlje informacije slike iz kamere v funkcije za obdelavo slik in omogoča predstavitev slike na glavni strani aplikacije. Slednje lahko vidimo v spodnjem izseku 4.2.
Diplomska naloga 25
Izsek 4.2: Vklop kamere in izklop ter predstavitev slike iz kamere.
Zaradi omejenega časa z opremo smo vnaprej posneli nekaj slik in v
aplikaciji omogočili testni način, ki omogoča uporabo brez priključene ka-mere. Kot vidimo na sliki 4.4 smo dodali gumbe: „Upload“, ki omogoča nalaganje slik na lokalni pomnilnik računalnika SIM4000; „Download“, ki omogoča prenos slik iz SIM4000 na računalnik; in „Delete“, ki izbriše iz-brano sliko ter spustni meni za izbiro slik za prenos, implementiran s funkcijo getPublicFiles(), katero gradnikDropDown1 ob zagonu aplikacije pokliče.
Funkcija rekurzivno poišče vse slikovne datoteke v mapi in gradniku, kot je prikazano v izseku 4.3, in vrne niz v formatu JSON. Gradnik podan niz raz-členi v posamezne opcije v spustnem meniju, ki ob izbiri tudi prikažejo sliko na pregledovalniku Viewer2D. Aplikacija vsebuje tudi gumb „Shrani sliko“, ki iz kamere zajeto sliko, prikazano na pregledovalniku, shrani na lokalni pomnilnik računalnika SIM4000. Vse slike so shranjene v mapi public v bitmap formatu.
dropdown = dropdown .. ’,’
end
dropdown = dropdown .. ’{"label":"’ .. v .. ’", "value":"’ .. v .. ’"}’
end
dropdown = dropdown .. ’]’
return dropdown end
Izsek 4.3: Funkcija za prikaz vseh slikovnih datotek v spustnem meniju.
Pri obdelavi slike smo posneto sliko s kamero najprej pretvorili v sivin-sko z ukazom image:toGray(), da jo lahko binariziramo. Binarizacija slike je postopek pretvorbe sivinske slike, ki vsebuje 256 različnih odtenkov sive
Diplomska naloga 27
Slika 4.4: Gumbi in spustni meni za upravljanje s slikovnimi datotekami.
v sliko, ki vsebuje le dve barvi, črno in belo. Deluje tako, da vse slikovne elemente z intenzivnostjo nad neko mejno vrednostjo (angl. threshold) spre-meni v črno, medtem ko ostale sprespre-meni v belo, kar omogoča, da se znebimo nepotrebnega šuma na sliki in ostalih motečih elementov. Rezultat binariza-cije je v našem primeru jasen izvleček 12-ih navojev na sliki z belim ozadjem.
Primerjavo lahko vidimo na spodnji primerjavi na sliki 4.5, kjer so navoji jasno izpostavljeni in obarvani s črno barvo na belem ozadju. Ugotovili smo, da je v našem primeru najbolj optimalna mejna vrednost 82, vendar smo v aplikaciji uporabniku dodali možnost, da s pomočjo drsnika mejno vre-dnost poljubno spreminja. Binarizacija je pomemben del naše aplikacije in smo jo uporabili pri obeh algoritmih za iskanje središč. Za binariziranje smo uporabili ukaz imageGray.binarize(mejnaVrednost).
Pri algoritmu za zaznavanju področij (angl. blob detection) smo najprej nastavili minimalne in maksimalne privzete vrednosti parametrov površine in raztezka področij, ki določata, katera področja ustrezajo tem parametrom in katera ne, nato pa jih ustrezno izloči. V samem uporabniškem vmesniku je dodana možnost, da si uporabnik parametre poljubno nastavi, kot je pri-kazano na sliki 4.6. Ker ima končni uporabnik možnost spreminjanja mejne vrednosti binarizacije, parametrov površine in raztezka, smo se odločili, da bomo podatke o koordinatah središč področij hranili v dveh tabelah, in sicer currCenters, ki hrani podatke o središčih s trenutno nastavljenimi
parame-(a) vhodna slika (b) sivinska slika
(c) binarizirana slika
Slika 4.5: Primerjava sivinske slike z binarizirano sliko.
Slika 4.6: Nastavitve parametrov v aplikaciji.
Diplomska naloga 29 tri, inprevCenters, ki hrani podatke o središčih s prej nastavljenimi parame-tri za lažjo primerjavo med spremembami. Po binarizaciji slike smo s pomo-čjo funkcije local blobs = objectRegion:findConnected(20, 3000) na binarizirani sliki izvlekli vse objekte, ki imajo več kot 20 črnih slikovnih ele-mentov skupaj in jih shranili v tabelo področij,blobs. Funkcija prejme mini-malno število in maksimini-malno število slikovnih elementov, ki se držijo skupaj, in posamezna najdena območja, ki ustrezajo parametrom shrani v tabelo, v n ašem primerublobs. Nastavili smo filtra površine: areaMininareaMaxter raztezka: elongationMininelongationMaxs funkcijoImage.PixelRegion.
Filter.create()ter ju uporabili nad tabelo področij, kar izloči vse objekte v tabeli, ki ne ustrezajo nastavljenim parametrom. Knjižnico PixelRegion uporabimo, ko želimo delati s slikovnimi elementi direktno na sliki in pred-stavlja zbirko več slikovnih elementov na sliki, ki jo običajno uporabimo v kombinaciji s samo sliko. V izseku 4.4 je prikazan del funkcije FindBoard-Screws()pridobivanja koordinat središč področij v tabeliblobs. Z zanko se najprej sprehodimo čez celotno tabelo objektov in od posameznega področja s funkcijo Image.PixelRegion.getArea(blobs, image). Funkcija prejme tabelo področij (blobs) in pripadajočo sliko (image) ter vrne površino tega področja. Posledično s funkcijo Image.PixelRegion.getCenterOfGravity (blobs[i], image)pridobimo točko težišča posameznega področja. Oboje nato shranimo v tabelicurrCentersinscrewAreas. Ob koncu je potreben še grafični izris področij in koordinat na gradnikuViewer, prikazan na sliki 4.7.
Tu smo realizirali in uporabili funkcijoprikaziKoordinato(center, text, barva, imgID), ki prikaže želene podatke na pregledovalniku. V sklopu funkcijeFindBoardScrews() smo dodali še prikaz prejšnjih vrednosti, ki de-luje tako, da ob vsaki spremembi parametrov ponovno pokliče funkcijo in prekopira objekte iz tabelecurrCenters v prevCenters.
for i = 1, #blobs do
local posamezni = blobs[i]:getArea(image)
local centerArea = blobs[i]:getCenterOfGravity(image) local box = blobs[i]:getBoundingBoxOriented(image) local center, width, height, rotation =
box:getRectangleParameters() currCenters[i] = centerArea screwAreas[i] = posamezni
viewer:addPixelRegion(blobs[i], regionDecoration, nil, imageID) prikaziKoordinato(centerArea, ’(x: ’ ..
round(centerArea:getX(), 3) ..’ y: ’ ..
round(centerArea:getY(), 3) .. ’ Area: ’ .. posamezni,
’GREEN’, imgID) end
Izsek 4.4: Zanka za pridobivanje koordinat in njihov izris.
Drugi uporabljen algoritem za iskanje središč je Houghova transformacija kroga (angl. Circle Hough Transform). Namen Houghove transformacije je poiskati iskano premico, krog, parabolo ali kakršno koli drugo obliko v sliki na podlagi binarizirane slike robov. V našem primeru iščemo krog, tako da smo uporabili Houghovo transformacijo kroga. V sliki robov slikovni elementi pogosto ne ležijo točno na krožnici ali pa nekateri slikovni elementi manjkajo. Houghovo transformacijo lahko uporabimo za iskanje teh krogov, kjer posamezen krog predstavimo s spodnjo enačbo 4.1.
r2 = (x−a)2+ (y−b)2 (4.1) V enačbiainbpredstavljata koordinate središča kroga,rpredstavlja polmer kroga, xin ypredstavljata točko na krožnici [14]. Postopek iskanja posame-znega kroga je sledeč:
Najprej najdemo na sliki vse robove, kar pomeni, da nad binarizirano sliko uporabimo operator za zaznavanje robov, v našem primeru smo uporabili
Diplomska naloga 31
Slika 4.7: Grafični izris področij in koordinat.
Cannyjev detektor robov, ki velja za matematično najbolj optimalnega in odpornega na šum. Algoritem poišče robove tam, kjer se intenziteta sivin najbolj spremeni. Algoritem uporablja dva praga – visokega T1 in nizkega T2 oziroma zapisano kot klic funkcije: Image.canny(imageBin, T1, T2).
Vsak slikovni element z jakostjo nad pragom T1 je označen kot močen robni slikovni element, slikovni element z jakostjo med pragovoma je označen kot šibek robni slikovni element. Vsi slikovni elementi z jakostjo pod pragom T2 so zavrženi. Rezultat po apliciranem algoritmu je slika robov, ki z visoko verjetnostjo sovpadajo z robovi na vhodni binarizirani sliki. Nad vsakim robnim slikovnim elementom se nariše krožnica z želenim polmerom r, kjer je robni slikovni element središče kroga, okoli celotnega roba, dokler ne pri-demo na isto mesto. Da smo to dosegli, smo uporabili funkcijo HoughAcc = Image.houghTransformCircle(edgeImg, r, w, h), kjer r predstavlja ra-dij, w, h predstavljata višino in širino vhodne slike robov edgeImg. Rezultat je akumulatorsko polje, vidno na sliki 4.8, kjer smo za lažji prikaz uporabili tri točke iz slike robov na levi in videz akumulatorskega polja z določenim središčem na desni. Na desnem grafu lahko vidimo tri točke, ki predstavljajo središče krožnic na robnih slikovnih elementih (črtkana krožnica). Ob sti-čišču vseh treh črtkanih krožnic lahko z veliko verjetnostjo zagotovimo, da predstavlja središče, označeno z modro.
Ker krožnice v našem primeru niso popolne krivulje, smo v akumulator-skem polju določili lokalne maksimume s funkcijo, ki so v našem primeru točke na akumulatorju, kjer je največje število stičišč akumuliranih krožnic oziroma kjer je jakost slikovnih elementov na akumulatorju najvišja. Tu smo uporabili funkcijolocExt=Image.findLocalExtrema(houghAcc,’MAX’
,_neighborhoodSize,_contrastThreshold), ki prejme za vhodno sliko aku-mulatorsko polje houghAcc. S parametrom ’MAX’ sporočimo, da v akumu-latorskem polju iščemo lokalne maksimume. Vključena sta še dva opcij-ska argumenta, in sicer _neighborhoodSize in _contrastThreshod. Pri prvem lahko nastavimo minimalno število slikovnih elementov, ki spadajo pod isti krog. Če je to število prenizko, na sliki dobimo več krogov, kot
Diplomska naloga 33
Slika 4.8: Primer določanja središča kroga z uporabo Houghove transforma-cije kroga [17].
bi si jih želeli, saj se ti ne bi izrisovali na primernih mestih. Za naš pri-mer smo ugotovili, da je optimalno število 15 slikovnih elementov. Zadnji parameter v funkciji pa predstavlja mejno vrednost kontrasta, ki loči ekstre-mne slikovne elemente od nepomembnih. V našem primeru smo ugotovili, da je optimalna mejna vrednost 80. Lokalni maksimumi predstavljajo naj-boljše kandidate za središča krožnic na vhodni sliki. Narišemo jih s funkcijo Image.houghTransformExtremaToCircles(locExt, r), ki za vsak lokalni maksimum nariše krog z radijemr.
Algoritem Houghove transformacije kroga, viden v izseku 4.5, lahko za naš primer povzamemo s psevdokodo v šestih korakih:
1. Najdi robove na sliki s Cannyjevim detektorjem robov 2. Za vsako področje
3. Za vsako točko na robu
4. Nariši krožnico s središčem v tej točki na robu s polmerom r 5. Poišči lokalni maksimum v akumulatorskem polju
6. Najdene parametre (r, a, b), ki ustrezajo lokalnim maksimumom, pre-slikaj nazaj na izvirno sliko
--@FindBoardScrewsHTC():
function FindBoardScrewsHTC()
local edgeImg = imageBin:canny(300, 100) local radius = (math.sqrt(avgArea / math.pi)) local w, h = edgeImg:getSize()
local houghAcc = edgeImg:houghTransformCircle(radius, w, h) viewer2:addImage(edgeImg)
houghAcc:multiplyConstantInplace(255 / houghAcc:getMax()) local locExt = houghAcc:findLocalExtrema(’MAX’, 15, 80)
local circles = houghAcc:houghTransformExtremaToCircles(locExt, radius)
// izris krogov in predstavitev na pregledovalniku viewer2
for i = 1, #circles do
Izsek 4.5: Algoritem Houghove transformacije kroga.
Kot lahko vidimo na sliki 4.9, se akumulatorsko polje ustvari z risanjem krožnic na vsakem belem slikovnem elementu, prikazanem na sliki robov, kjer smo uporabili povprečen polmer vseh 12 krogov. Iz najsvetlejših točk se nato v akumulatorskem polju na podlagi lokalnih maksimumov določijo središča krogov, ki so prikazani na sliki 4.9 c).
Za shranjevanje podatkov o obdelanih slikah v podatkovno bazo smo uporabili MongoDB in Node.js. Najprej smo v SICK AppStudio napisali skripto HTTPClientSample.Lua, ki vsebuje funkcije za pošiljanje in branje
Diplomska naloga 35
(a) Cannyjev detektor robov
(b) akumulatorsko polje (c) izris najdenih krogov na vhodni sliki robov
Slika 4.9: Houghova transformacija kroga.
http in https zahtevkov GET, namenjene izpisu podatkov iz spletne strani, ter POST, ki so namenjene pošiljanju podatkov na spletno stran. Podatki, ki se pošiljajo, so v formatu JSON. V spodnjem izseku 4.5 lahko vidimo način pošiljanja zahtevka POST. V našem primeru hranimo podatke v treh bazah, in sicer:
• api/captures, kjer se hranijo podatki obdelanih slik z metodo zazna-vanja področij;
• api/houghCaptures, kjer se hranijo podatki obdelanih slik z metodo Houghove transformacije kroga;
• api/bothCaptures, kjer se hranijo podatki obeh metod in njuna pri-merjava.
Izsek 4.6: prikaz pošiljanja zahtevka POSTv jeziku Lua.
Funkcija prejme URL spletne strani, v našem primeru recimo https:
//localhost/api/bothCaptures ter niz v obliki JSON, ki ga želimo izvo-ziti v podatkovno bazo, katerega struktura je vidna na sliki 4.10. V funkciji se nato preveri, če je HTTP klient uspešno kreiran. Nastaviti smo morali request:setContentType, da sporoči spletni strani obliko zahtevka, ki ga
Diplomska naloga 37
Slika 4.10: Videz oblike baze houghCaptures v obliki JSON.
bo prejela, in sicer application/json. Kot privzeto je namreč vsebina na-stavljena tako, da dobi navadno besedilo v HTML obliki text/html. Nasta-viti je bilo potrebno še metodo pošiljanja, kar je v našem primeru POST, in podatke poslati z ukazom client:execute(request).
Za izračun razlik določanja središč po obeh metodah iskanja smo za vsako točko uporabili Pitagorov izrek za izračun razdalje dveh različnih točk v koordinatnem sistemu, prikazan v enačbi 4.2.
d=q(x2−x1)2 + (y2−y1)2 (4.2) V enačbi d prestavlja razdaljo med točkama, x2 in y2 predstavljata ko-ordinate točke središča, ki sta določeni po metodi Houghove transformacije kroga, x1 iny1 pa predstavljata koordinate točke središča, ki sta določeni po
metodi iskanja področij.
Uporabnik ima v aplikaciji tudi možnost vpogleda v bazo ter izbris za-pisov iz nje, kot je prikazano na spodnji sliki 4.11. Za prikaz spletne strani znotraj naše aplikacije smo uporabili HTML ukaziframe. Ob kliku na gumb
„Izbriši“ se pošlje zahtevekDELETEna spletno stran skupaj z enolično oznako zapisa (ID), na primer DELETE https://localhost/api/bothCaptures/
61accdd8fcc147882153e639 in se zahtevek iz baze pobriše.
Slika 4.11: Prikaz podatkov, zapisanih v bazi bothCaptures.