Muutaman viime vuoden aikana matkapuhelinten keskimääräinen suorituskyky on kasvanut merkittävästi. Olipa kyse pelkästään suorittimen hevosvoimasta tai RAM-kapasiteetista, nyt on helpompaa tehdä laskennan vaativia tehtäviä mobiililaitteilla. Vaikka nämä mobiiliteknologiat suuntaavat oikeaan suuntaan, mobiilialustoilla on vielä paljon tehtävää, etenkin lisätyn todellisuuden, virtuaalitodellisuuden ja tekoälyn myötä.
Tietokonenäön suuri haaste on havaita mielenkiintoisia esineitä kuvista. Ihmissilmä ja aivot tekevät poikkeuksellisen hyvää työtä toistamalla tämä koneissa on edelleen unelma. Viime vuosikymmenien aikana on kehitetty lähestymistapoja tämän jäljittelemiseksi koneissa, ja se on parantumassa.
Tässä opetusohjelmassa tutkitaan algoritmia, jota käytetään kuvien läiskien havaitsemiseen. Käytämme toteuttamiseen myös avoimen lähdekoodin kirjaston, OpenCV: n, algoritmia prototyyppi iPhone-sovellus joka käyttää takakameraa kuvien hankkimiseen ja kohteiden havaitsemiseen niistä.
OpenCV on avoimen lähdekoodin kirjasto, joka tarjoaa tärkeimpien tietokonenäön ja koneoppimisalgoritmien toteutuksia. Jos haluat toteuttaa sovelluksen kasvojen havaitsemiseen, korttien pelaamiseen pokeripöydässä tai jopa yksinkertaisen sovelluksen tehosteiden lisäämiseksi mielivaltaiseen kuvaan, OpenCV on loistava valinta.
OpenCV on kirjoitettu C / C ++: lla, ja siinä on käärekirjastot kaikille tärkeimmille alustoille. Tämän ansiosta sen käyttö on erityisen helppoa iOS-ympäristö . Sen käyttäminen tavoite-C: ssä iOS-sovellus , lataa OpenCV iOS Framework viralliselta verkkosivustolta . Varmista, että käytät OpenCV for iOS -sovelluksen versiota 2.4.11 (jonka oletetaan käyttävän tässä artikkelissa), koska viimeisimmällä versiolla 3.0 on joitain yhteensopivuutta rikkovia muutoksia otsikkotiedostojen järjestämisessä. Yksityiskohtaiset tiedot sen asentamisesta dokumentoitu sen verkkosivustolla .
MSER , lyhenne sanoista Maximally Stable Extremal Regions, on yksi monista käytettävissä olevista menetelmistä blob-havaitsemiseen kuvissa. Yksinkertaisesti sanottuna algoritmi tunnistaa vierekkäiset pikselijoukot, joiden ulkoreunapikselien intensiteetit ovat suurempia (tietyllä kynnyksellä) kuin sisäisen pikselin intensiteetit. Tällaisten alueiden sanotaan olevan maksimaalisesti vakaita, jos ne eivät muutu paljon vaihtelevalla voimakkuudella.
Vaikka joukko muita blob havaitsemisalgoritmit olemassa, MSER valittiin täällä, koska sillä on melko kevyt ajonaikainen monimutkaisuus (O log (log (log (n)))), jossa n on kuvan pikselien kokonaismäärä. Algoritmi on myös vankka hämärtää ja skaalata, mikä on edullista käsiteltäessä reaaliaikaisista lähteistä, kuten matkapuhelimen kamerasta, hankittuja kuvia.
Suunnittelemme tämän opetusohjelman tarkoituksiin sovellus tunnistaa ApeeScape-logo. Symbolilla on terävät kulmat, ja se voi saada ajattelemaan, kuinka tehokkaat kulman tunnistusalgoritmit voivat olla ApeeScape-logon havaitsemisessa. Loppujen lopuksi tällaista algoritmia on sekä helppo käyttää että ymmärtää. Vaikka kulmapohjaisilla menetelmillä voi olla suuri onnistumisaste havaita selvästi taustasta erillisiä esineitä (kuten mustia esineitä valkoisella taustalla), ApeeScapen reaaliaikainen havaitseminen on vaikeaa logo tosielämän kuvissa, joissa algoritmi havaitsisi jatkuvasti satoja kulmia.
Jokainen kuvakehys, jonka sovellus hankkii kameran kautta, muunnetaan ensin harmaasävyksi. Harmaasävykuvissa on vain yksi värikanava, mutta logo on kuitenkin näkyvissä. Tämä tekee algoritmille helpomman käsitellä kuvaa ja vähentää merkittävästi algoritmin käsiteltävän datan määrää saadakseen vain vähän tai ei ollenkaan ylimääräistä hyötyä.
Seuraavaksi käytämme OpenCV: n toteutusalgoritmia kaikkien MSER-tiedostojen purkamiseen. Seuraavaksi kukin MSER normalisoidaan muuntamalla sen pienin rajoittava suorakaide neliöksi. Tämä vaihe on tärkeä, koska logo voidaan hankkia eri kulmista ja etäisyyksiltä, mikä lisää perspektiivivääristymien sietokykyä.
Lisäksi jokaiselle MSER: lle lasketaan useita ominaisuuksia:
ApeeScape-logon havaitsemiseksi kuvasta kaikkien MSER-tiedostojen ominaisuuksia verrataan jo opittuihin ApeeScape-logon ominaisuuksiin. Tässä opetusohjelmassa kunkin ominaisuuden suurimmat sallitut erot valittiin empiirisesti.
Lopuksi tulokseksi valitaan vastaavin alue.
OpenCV: n käyttö iOS: stä on helppoa. Jos et ole vielä tehnyt sitä, tässä on lyhyt kuvaus vaiheista, jotka liittyvät Xcooden asettamiseen iOS-sovelluksen luomiseksi ja OpenCV: n käyttämiseksi siinä:
Luo uusi projektinimi ”SuperCool Logo Detector”. Jätä kieleksi Tavoite-C valittu.
Lisää uusi Prefix Header (.pch) -tiedosto ja nimeä se PrefixHeader.pch
Siirry projektin 'SuperCool Logo Detector' koontikohteeseen ja etsi Rakennusasetukset-välilehdeltä 'Etuliiteotsikot' -asetus. Löydät sen LLVM-kieli-osiosta tai voit käyttää hakutoimintoa.
Lisää 'PrefixHeader.pch' Etuliiteotsikot-asetukseen
Tässä vaiheessa, jos et ole asentanut OpenCV iOS: lle 2.4.11, tee se nyt.
Vedä ja pudota ladattu kehys projektiin. Valitse Kohdeasetuksissa linkitetyt kehykset ja kirjastot. (Se tulisi lisätä automaattisesti, mutta parempi olla turvallinen.)
Liitä lisäksi seuraavat kehykset:
Avaa 'PrefixHeader.pch' ja lisää seuraavat 3 riviä:
#ifdef __cplusplus #include #endif”
Muuta automaattisesti luotujen kooditiedostojen laajennukset .m ”-” .mm ”. OpenCV on kirjoitettu C ++: lla ja * .mm: llä sanot, että käytät Objective-C ++: ta.
Tuo ”opencv2 / highgui / cap_ios.h” ViewController.h-tiedostoon ja vaihda ViewController CvVideoCameraDelegate -protokollan mukaiseksi:
#import
Avaa Main.storyboard ja aseta UIImageView alkuperäiseen näkymäohjaimeen.
Tee ulostulo ViewController.mm: lle nimeltä 'imageView'
Luo muuttuja ”CvVideoCamera * camera;” tiedostoissa ViewController.h tai ViewController.mm ja alusta se viittaamalla takakameraan:
camera = [[CvVideoCamera alloc] initWithParentView: _imageView]; camera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionBack; camera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset640x480; camera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait; camera.defaultFPS = 30; camera.grayscaleMode = NO; camera.delegate = self;
Jos rakennat projektin nyt, Xcode varoittaa sinua, ettet ole toteuttanut CvVideoCameraDelegate-prosessin ”processImage” -menetelmää. Toistaiseksi ja yksinkertaisuuden vuoksi hankimme kuvat vain kamerasta ja peitämme ne yksinkertaisella tekstillä:
[camera start];
Nyt, jos suoritat sovelluksen, se pyytää sinulta lupaa käyttää kameraa. Ja sitten sinun pitäisi nähdä video kamerasta.
Lisää 'processImage' -menetelmään seuraavat kaksi riviä:
const char* str = [@'ApeeScape' cStringUsingEncoding: NSUTF8StringEncoding]; cv::putText(image, str, cv::Point(100, 100), CV_FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(0, 0, 255));
Se on melkein se. Nyt sinulla on hyvin yksinkertainen sovellus, joka piirtää tekstin “ApeeScape” kuviin kamerasta. Voimme nyt rakentaa kohdelogomme, joka tunnistaa sovelluksen pois tästä yksinkertaisemmasta. Lyhyesti sanottuna tässä artikkelissa käsitellään vain muutamia koodisegmenttejä, jotka ovat kriittisiä sovelluksen toiminnan ymmärtämisen kannalta. GitHubin koodissa on melko paljon kommentteja selittääkseen, mitä kukin segmentti tekee.
Koska sovelluksella on vain yksi tarkoitus, havaita ApeeScape-logo heti, kun se käynnistetään, MSER-ominaisuudet puretaan annetusta mallikuvasta ja arvot tallennetaan muistiin:
cv::Mat logo = [ImageUtils cvMatFromUIImage: templateImage]; //get gray image cv::Mat gray; cvtColor(logo, gray, CV_BGRA2GRAY); //mser with maximum area is std::vector maxMser = [ImageUtils maxMser: &gray]; //get 4 vertices of the maxMSER minrect cv::RotatedRect rect = cv::minAreaRect(maxMser); cv::Point2f points[4]; rect.points(points); //normalize image cv::Mat M = [GeometryUtil getPerspectiveMatrix: points toSize: rect.size]; cv::Mat normalizedImage = [GeometryUtil normalizeImage: &gray withTranformationMatrix: &M withSize: rect.size.width]; //get maxMser from normalized image std::vector normalizedMser = [ImageUtils maxMser: &normalizedImage]; //remember the template self.logoTemplate = [[MSERManager sharedInstance] extractFeature: &normalizedMser]; //store the feature [self storeTemplate];
Sovelluksessa on vain yksi Start / Stop-painike, ja kaikki tarvittavat tiedot, kuten FPS ja havaittujen MSER-tiedostojen määrä, piirretään automaattisesti kuvaan. Niin kauan kuin sovellusta ei ole pysäytetty, käytetään jokaista kameran kuvakehystä varten seuraavaa processImage-menetelmää:
-(void)processImage:(cv::Mat &)image { cv::Mat gray; cvtColor(image, gray, CV_BGRA2GRAY); std::vector msers; [[MSERManager sharedInstance] detectRegions: gray intoVector: msers]; if (msers.size() == 0) { return; }; std::vector *bestMser = nil; double bestPoint = 10.0; std::for_each(msers.begin(), msers.end(), [&] (std::vector &mser) { MSERFeature *feature = [[MSERManager sharedInstance] extractFeature: &mser]; if(feature != nil) { if([[MLManager sharedInstance] isApeeScapeLogo: feature] ) { double tmp = [[MLManager sharedInstance] distance: feature ]; if ( bestPoint > tmp ) { bestPoint = tmp; bestMser = &mser; } } } }); if (bestMser) { NSLog(@'minDist: %f', bestPoint); cv::Rect bound = cv::boundingRect(*bestMser); cv::rectangle(image, bound, GREEN, 3); } else { cv::rectangle(image, cv::Rect(0, 0, W, H), RED, 3); } // Omitted debug code [FPS draw: image]; }
Tämä menetelmä luo pohjimmiltaan harmaasävykopion alkuperäisestä kuvasta. Se tunnistaa kaikki MSER: t ja poimii niiden merkitykselliset ominaisuudet, pisteyttää kunkin MSER: n samankaltaisuuden mallin kanssa ja valitsee parhaan. Lopuksi se piirtää vihreän rajan parhaan MSER: n ympärille ja peittää kuvan metatiedoilla.
Alla on muutaman tärkeän luokan määritelmät ja niiden menetelmät tässä sovelluksessa. Niiden tarkoitukset on kuvattu kommenteissa.
/* This static class provides perspective transformation function */ @interface GeometryUtil : NSObject /* Return perspective transformation matrix for given points to square with origin [0,0] and with size (size.width, size.width) */ + (cv::Mat) getPerspectiveMatrix: (cv::Point2f[]) points toSize: (cv::Size2f) size; /* Returns new perspecivly transformed image with given size */ + (cv::Mat) normalizeImage: (cv::Mat *) image withTranformationMatrix: (cv::Mat *) M withSize: (float) size; @end
/* Singelton class providing function related to msers */ @interface MSERManager : NSObject + (MSERManager *) sharedInstance; /* Extracts all msers into provided vector */ - (void) detectRegions: (cv::Mat &) gray intoVector: (std::vector &) vector; /* Extracts feature from the mser. For some MSERs feature can be NULL !!! */ - (MSERFeature *) extractFeature: (std::vector *) mser; @end
/* This singleton class wraps object recognition function */ @interface MLManager : NSObject + (MLManager *) sharedInstance; /* Stores feature from the biggest MSER in the templateImage */ - (void) learn: (UIImage *) templateImage; /* Sum of the differences between logo feature and given feature */ - (double) distance: (MSERFeature *) feature; /* Returns true if the given feature is similar to the one learned from the template */ - (BOOL) isApeeScapeLogo: (MSERFeature *) feature; @end
Kun kaikki on kytketty yhteen, tämän sovelluksen avulla sinun pitäisi pystyä käyttämään iOS-laitteesi kameraa tunnistamaan ApeeScape-logo eri kulmista ja suunnista.
Tässä artikkelissa olemme osoittaneet, kuinka helppoa on havaita yksinkertaisia objekteja kuvasta OpenCV: n avulla. Koko koodi on saatavilla GitHubissa . Voit vapaasti haarautua ja lähettää push-pyyntöjä, koska lahjoitukset ovat tervetulleita.
Kuten kaikkien koneoppimisongelmien kohdalla, logotunnistuksen onnistumisastetta tässä sovelluksessa voidaan lisätä käyttämällä erilaisia ominaisuuksia ja erilaista menetelmää objektien luokittelussa. Toivon kuitenkin, että tämä artikkeli auttaa sinua pääsemään alkuun kohteiden havaitsemisessa MSER: n ja yleensä tietokonenäön tekniikoiden sovellusten avulla.