Captcha-tunnistus: menetelmät ja tekniikat. Universal CAPTCHA Python Captcha Recognizerin testaus

Se oli Baltic Science and Engineering Competition -kilpailussa esittämäni työn nimi, joka toi minulle viehättävän roomalaisen paperin sekä upouuden kannettavan tietokoneen.

Työ koostui suurten matkapuhelinoperaattoreiden tekstiviestien lähetysmuodoissa käyttämien CAPTCHA:iden tunnistamisesta ja lähestymistavan tehottomuuden osoittamisesta. Jotta emme loukkaisi kenenkään ylpeyttä, kutsumme näitä operaattoreita allegorisesti: punainen, keltainen, vihreä ja sininen.

Hanke on nimetty virallisesti Sieppaus ja epävirallinen Viallisten turvatoimien rikkominen. Kaikki ottelut ovat satunnaisia.

Kummallista kyllä, kaikki (no, melkein kaikki) nämä CAPTCHA:t osoittautuivat melko heikoiksi. Pienin tulos - 20 % - kuuluu keltaiselle, suurin - 86 % - siniselle. Näin ollen uskon, että "tehottomuuden osoittaminen" on onnistuneesti ratkaistu.

Syyt matkapuhelinoperaattoreiden valintaan ovat triviaaleja. Arvostetulle tiedetuomaristolle kerroin tarinan, että "matkapuhelinoperaattoreilla on tarpeeksi rahaa palkata minkä tahansa pätevyyden omaava ohjelmoija, ja samalla heidän täytyy minimoida roskapostin määrä; Siksi heidän CAPTCHA:nsa pitäisi olla melko voimakas, mikä tutkimukseni osoittaa, ettei näin ole ollenkaan." Itse asiassa kaikki oli paljon yksinkertaisempaa. Halusin saada kokemusta hakkeroinnista tunnistamalla yksinkertaisen CAPTCHA:n ja valitsin punaisen operaattorin CAPTCHA:n uhriksi. Ja sen jälkeen edellä mainittu tarina syntyi jälkikäteen.

Eli lähempänä vartaloa. Minulla ei ole mitään mega-kehittynyttä algoritmia kaikkien neljän CAPTCHA-tyypin tunnistamiseen. sen sijaan kirjoitin 4 erilaista algoritmia kullekin CAPTCHA-tyypille erikseen. Huolimatta siitä, että algoritmit ovat yksityiskohdiltaan erilaisia, ne osoittautuivat yleisesti ottaen hyvin samanlaisiksi.

Kuten monet ennenkin kirjoittajat, jaoin CAPTCHA-tunnistustehtävän kolmeen osatehtävään: esikäsittely (esikäsittely), segmentointi ja tunnistus. Esikäsittelyvaiheessa lähdekuvasta poistetaan erilaisia ​​kohinoita, vääristymiä jne. Segmentoinnissa lähdekuvasta poimitaan yksittäisiä merkkejä ja suoritetaan jälkikäsittelystä (esim. käänteinen kierto). Kun merkkejä tunnistetaan yksitellen, niitä käsittelee esikoulutettu hermoverkko.

Vain esikäsittely erosi merkittävästi. Tämä johtuu siitä, että eri CAPTCHA:t käyttävät erilaisia ​​kuvan vääristymismenetelmiä, ja näiden vääristymien poistamiseen käytettävät algoritmit vaihtelevat suuresti. Segmentoinnissa hyödynnettiin keskeistä ideaa löytää liitettävyyskomponentteja pienillä kelloilla ja pillillä (ne piti tehdä merkittäviksi vain keltaraitaisissa). Tunnistus oli täsmälleen sama kolmella operaattorilla neljästä - jälleen vain keltainen operaattori oli erilainen.

Lopuksi pienet (alle 10px) mustat yhdistetyt alueet maalataan valkoisella:

Joskus (harvoin, mutta tapahtuu) kirje hajoaa useisiin osiin; Tämän valitettavan väärinkäsityksen korjaamiseksi käytän melko yksinkertaista heuristia, joka arvioi, kuuluvatko useat yhdistetyt komponentit samaan symboliin. Tämä pistemäärä riippuu vain kunkin hahmon rajoitusruutujen vaakasuuntaisesta sijainnista ja koosta.

On helppo nähdä, että monet symbolit yhdistettiin yhdeksi yhdistetyksi komponentiksi, ja siksi ne tulisi erottaa. Tässä tulee apuun se, että kuvassa on aina tasan 5 merkkiä. Tämän avulla voit laskea erittäin tarkasti, kuinka monta merkkiä kussakin löydetyssä komponentissa on.

Selvittääksesi tällaisen algoritmin toimintaperiaatteen, sinun on mentävä hieman syvemmälle materiaaliin. Merkitään löydettyjen segmenttien lukumäärä arvolla n ja leveysjoukko ( oikein sanottu, eikö?) kaikista segmenteistä leveyden[n] ulkopuolella. Oletetaan, että jos yllä olevien vaiheiden jälkeen n > 5, kuvaa ei voitu tunnistaa. Harkitse kaikkia mahdollisia luvun 5 laajennuksia positiivisiin kokonaislukuihin. Niitä ei ole paljon - vain 16. Jokainen tällainen laajennus vastaa jotakin mahdollista symbolien järjestelyä löydettyjen yhteyskomponenttien mukaan. On loogista olettaa, että mitä leveämpi tuloksena oleva segmentti, sitä enemmän merkkejä se sisältää. Kaikista viiden dekompositioista valitsemme vain ne, joissa termien lukumäärä on yhtä suuri kuin n. Jaetaan jokainen elementti leveydistä leveydillä - ikään kuin normalisoisimme ne. Teemme samoin kaikilla jäljellä olevilla laajennuksilla - jaamme niiden jokaisen luvun ensimmäisellä summauksella. Ja nyt (huo Tätä silmällä pitäen etsitään lähin euklidinen laajennus viidestä normalisoituihin leveyksiin. Tämä on haluttu tulos.

Muuten, tämän algoritmin yhteydessä keksin toisen mielenkiintoisen tavan etsiä kaikki luvun laajennukset termeiksi, joita en kuitenkaan koskaan toteuttanut, kaivautuen Python-tietorakenteisiin. Lyhyesti sanottuna - se selviää melko selvästi, jos huomaa, että tietynpituisten laajennusten lukumäärä osuu yhteen Pascalin kolmion vastaavan tason kanssa. Olen kuitenkin varma, että tämä algoritmi on ollut tunnettu jo pitkään.

Joten, kun on määritetty kunkin komponentin merkkien määrä, seuraava heuristinen tulee - uskomme, että merkkien väliset erottimet ovat ohuempia kuin itse merkit. Tämän salaisen tiedon hyödyntämiseksi sijoitetaan segmenttiin n-1 erotinta, missä n on merkkien lukumäärä segmentissä, minkä jälkeen lasketaan kuvan projektio alaspäin kunkin erottimen pienessä ympäristössä. Tämän projektion tuloksena saamme tietoa siitä, kuinka monta pikseliä kussakin sarakkeessa kuuluu merkkeihin. Lopuksi jokaisesta projektiosta etsitään minimi ja siirretään erotin sinne, minkä jälkeen pilkotaan kuva näitä erottimia pitkin.

Lopuksi tunnustus. Kuten sanoin, käytän siihen hermoverkkoa. Kouluttaakseni sitä ajelen ensin kaksisataa kuvaa yleisotsikon alla junasetti kahden ensimmäisen vaiheen läpi, jotka on jo kirjoitettu ja virheenkorjattu, minkä seurauksena saan kansion, jossa on suuri määrä siististi leikattuja segmenttejä. Sitten siivoan käsillä roskat (esim. virheellisen segmentoinnin tulokset), minkä jälkeen kokoan tuloksen yhteen kokoon ja annan sen FANNille revittäväksi. Tuloksena saan koulutetun hermoverkon, jota käytetään tunnistamiseen. Tämä suunnitelma epäonnistui vain kerran - mutta siitä lisää myöhemmin.

Tämän seurauksena testisarjassa (ei käytetä harjoitteluun, koodinimi on testisarja) 100 kuvasta tunnistettiin oikein 45. Ei kovin korkea tulos - tietysti sitä voi parantaa esim. esikäsittelyä tarkentamalla tai tunnistamalla uudelleen, mutta suoraan sanottuna olin liian laiska sotkemaan sitä.

Lisäksi käytin algoritmin suorituskyvyn arvioinnissa toista kriteeriä - keskimääräistä virhettä. Se laskettiin seuraavasti. Jokaiselle kuvalle löydettiin Levenshtein-etäisyys algoritmin tästä kuvasta antaman mielipiteen ja oikean vastauksen välillä - minkä jälkeen aritmeettinen keskiarvo otettiin kaikkien kuvien osalta. Tämän tyyppisessä CAPTCHA:ssa keskimääräinen virhe oli 0,75 merkkiä/kuva. Minusta tämä on tarkempi kriteeri kuin vain tunnustusprosentti.

Muuten, melkein kaikkialla (paitsi keltainen operaattori) käytin juuri tällaista mallia - 200 kuvaa junassa, 100 testisarjassa.

Vihreä

Valitsin vihreät seuraavaksi kohteeksi - halusin ottaa jotain vakavampaa kuin vääristymämatriisin valinta.

Edut:

  • 3D tehoste
  • Kierrä ja offset
  • Epätasainen kirkkaus

Virheet:

  • Hahmot ovat huomattavasti taustaa tummempia
  • Suorakulmion yläreuna on selvästi näkyvissä - voidaan käyttää kääntämiseen taaksepäin

Kävi ilmi, että huolimatta siitä, että nämä puutteet näyttävät olevan merkityksettömiä, niiden hyödyntäminen mahdollistaa kaikkien etujen käsittelemisen erittäin tehokkaasti.

Aloitetaan jälleen esikäsittelystä. Ensin arvioidaan sen suorakulmion kiertokulma, jolla symbolit sijaitsevat. Tätä varten käytämme Erode-operaattoria (etsi paikallista minimiä) alkuperäiseen kuvaan, sitten Kynnys valitaksesi suorakulmion jäännökset ja lopuksi inversion. Saamme kauniin valkoisen täplän mustalle taustalle.

Sitten tulee syvä ajatus. Ensimmäinen. Koko suorakulmion kiertokulman arvioimiseksi riittää arvioida sen yläsivun kiertokulma. Toinen. Voit arvioida yläpuolen kiertokulman etsimällä sen sivun suuntaista suoraa. Kolmanneksi. Minkä tahansa suoran kuvaamiseen, paitsi tiukasti pystysuoraan, riittää kaksi parametria - pystysuuntainen siirtymä koordinaattien keskipisteestä ja kaltevuuskulma, ja olemme kiinnostuneita vain toisesta. Neljäs. Suoran linjan löytäminen voidaan ratkaista ei kovin suurella luettelolla - siellä ei ole liian suuria kiertokulmia, emmekä tarvitse erittäin suurta tarkkuutta. Viides. Löytääksesi tarvittavan rivin, voit verrata kutakin riviä arvioon siitä, kuinka lähellä se on haluttua, ja valita sitten maksimi. Kuudes. Tärkein. Arvioiksesi tietyn suoran kaltevuuskulman kuvittele, että kuvaa koskettaa ylhäältä suora viiva, jolla on tällainen kaltevuuskulma. On selvää, että kuvan koosta ja kaltevuuskulmasta voidaan laskea yksiselitteisesti suoran pystysuuntainen siirtymä siten, että se on yksiselitteisesti asetettu. Lisäksi siirrämme tätä suoraa asteittain alaspäin. Jossain vaiheessa se koskettaa valkoista täplää. Muistetaan tämä hetki ja suoran ja pisteen leikkausalue. Muistutan, että suoralla viivalla on 8-kytketty taso, joten yleisön vihaiset huudot, että suoralla on yksi ulottuvuus ja pinta-ala on kaksiulotteinen käsite, eivät sovi tähän. Sitten jonkin aikaa siirrämme tätä suoraa alaspäin, muistaen risteysalueen kussakin vaiheessa, minkä jälkeen laskemme tulokset yhteen. Tämä summa on arvio tietystä kiertokulmasta.

Yhteenvetona edellisestä: etsitään sellaista suoraa viivaa, että kun se liikkuu kuvassa alaspäin, tällä suoralla olevien pikselien kirkkaus kasvaa voimakkaimmin.

Joten kiertokulma löytyy. Mutta ei pidä kiirehtiä heti soveltamaan saatua tietoa. Tosiasia on, että tämä pilaa kuvan yhtenäisyyden, ja tarvitsemme sitä edelleen.

Seuraava askel on erottaa hahmot taustasta. Se, että hahmot ovat paljon taustaa tummempia, auttaa meitä tässä paljon. Varsin looginen askel kehittäjiltä - muuten kuva olisi erittäin vaikea lukea. Kuka ei usko - voi yrittää binaarisoida kuvan itse ja nähdä itse.

Kuitenkin suora lähestymistapa - yritys katkaista merkkejä kynnyksillä - ei toimi tässä. Paras tulos, jonka onnistuin saavuttamaan - t = 140 - näyttää erittäin valitettavalta. Jäljellä on liikaa roskia. Joten minun piti käyttää kiertotapaa. Idea tässä on seuraava. Symbolit ovat yleensä yhteydessä toisiinsa. Lisäksi ne kuuluvat usein kuvan tummimpiin kohtiin. Mutta entä jos yrität levittää täytettä näistä hyvin tummista kohdista ja heittää sitten pois liian pienet täytetyt alueet - ilmeistä roskaa?

Tulos on suoraan sanottuna hämmästyttävä. Useimmissa kuvissa on mahdollista päästä eroon taustasta kokonaan. Kuitenkin tapahtuu, että symboli hajoaa useisiin osiin - tässä tapauksessa yksi kainalosauva segmentoinnissa voi auttaa - mutta siitä lisää myöhemmin.

Lopuksi Laajenna- ja Erode-operaattoreiden yhdistelmä poistaa hahmoihin jääneet pienet reiät, mikä helpottaa tunnistamista.

Segmentointi on tässä paljon yksinkertaisempaa kuin esikäsittely. Ensinnäkin etsimme liitäntäkomponentteja.

Sitten yhdistämme vaakasuunnassa läheiset komponentit (menettely on täsmälleen sama kuin ennen):

Tämä algoritmi antoi meille mahdollisuuden saavuttaa 69 % onnistuneesti tunnistetuista kuvista ja saada keskimääräinen virhe 0,3 merkkiä/kuva.

Sininen

Joten sininen operaattori sai kolmannen tilan "tappioitu". Se oli niin sanotusti hengähdystauko ennen todella suurta kalaa…

On vaikea kirjoittaa tänne mitään, mutta yritän silti:

  • Hahmon kierto on ainoa enemmän tai vähemmän vakava este
  • Taustamelu symboleina
  • Symbolit koskettavat joskus toisiaan

Päinvastoin kuin tämä:

  • Tausta on huomattavasti vaaleampi kuin symbolit
  • Hahmot sopivat hyvin suorakulmioon
  • Hahmojen eri värit helpottavat niiden erottamista toisistaan

Esikäsittely siis. Aloitetaan leikkaamalla tausta. Koska kuva on kolmivärinen, leikkaamme sen kanaviin ja hylkäämme sitten kaikki pisteet, jotka ovat kirkkaampia kuin 116 kaikissa kanavissa. Saamme niin kivan naamion:

Sitten muunnamme kuvan HSV-väriavaruuteen (Wikipedia). Tämä säilyttää symbolien väritiedot ja samalla poistaa gradientin niiden reunoista.

Laitetaan tulokseen aiemmin saatu naamio:

Tämä päättää esiprosessin. Segmentointi on myös melko triviaalia. Aloitetaan, kuten aina, yhteyskomponenteista:

Olisi mahdollista lopettaa tähän, mutta se osoittautuu vain 73%, mikä ei sovi minulle ollenkaan - vain 4% parempi kuin tarkoituksella monimutkaisemman CAPTCHA:n tulos. Joten seuraava askel on kääntää merkit. Tässä on hyödyllistä, että jo mainitsin, että paikalliset hahmot sopivat hyvin suorakulmioon. Ajatuksena on löytää kullekin merkille rajaava suorakulmio ja sitten laskea sen kulmakerroin itse merkin kaltevuus. Tässä rajaava suorakulmio ymmärretään sellaiseksi, että se sisältää ensinnäkin tietyn symbolin kaikki pikselit ja toiseksi sillä on pienin pinta-ala kaikista mahdollisista. Käytän algoritmin valmista toteutusta sellaisen suorakulmion löytämiseen OpenCV:stä (MinAreaRect2).

Tämä algoritmi tunnistaa onnistuneesti 86 % kuvista keskimääräisellä virheellä 0,16 merkkiä/kuva, mikä vahvistaa oletuksen, että tämä CAPTCHA on todellakin yksinkertaisin. Operaattori ei kuitenkaan ole suurin ...

Keltainen

Mielenkiintoisin on tulossa. Niin sanotusti luovan toiminnan apoteoosi 🙂 Tämä CAPTCHA on todellakin vaikein sekä tietokoneelle että valitettavasti ihmiselle.

Edut:

  • Melu pilkkujen ja viivojen muodossa
  • Pyöritä ja skaalaa symboleja
  • Symbolien läheisyys

Virheet:

  • Erittäin rajallinen paletti
  • Kaikki viivat ovat erittäin ohuita.
  • Täplät eivät usein leikkaa symboleja
  • Kaikkien merkkien kiertokulma on suunnilleen sama

Mietin ensimmäistä askelta pitkään. Ensimmäisenä tuli mieleen leikkiä paikallisilla maksimilla (Dilate) pienen melun poistamiseksi. Tämä lähestymistapa johti kuitenkin siihen, että kirjaimista oli jäljellä vähän - vain repeytyneet ääriviivat. Ongelmaa pahensi se, että itse hahmojen rakenne ei ole tasainen - tämä näkyy selvästi suurella suurennuksella. Päästäkseni eroon siitä päätin valita typerimmän tavan - avasin Paintin ja kirjoitin muistiin kaikkien kuvissa olevien värien koodit. Kävi ilmi, että näissä kuvissa on yhteensä neljä erilaista tekstuuria, joista kolmessa on 4 eri väriä ja viimeisessä 3; lisäksi kaikki näiden värien komponentit osoittautuivat 51:n kerrannaisiksi. Seuraavaksi tein väritaulukon, jonka avulla onnistuin pääsemään eroon tekstuurista. Kuitenkin ennen tätä "uudelleenkartoitusta" kirjoitan päälle myös liian vaaleat pikselit, jotka yleensä sijaitsevat merkkien reunoilla - muuten joudun merkitsemään ne kohinaksi ja sitten taistelemaan niitä vastaan, vaikka ne sisältävät vähän tietoa.

Joten tämän muunnoksen jälkeen kuvassa on enintään 6 väriä - 4 symboliväriä (kutsumme niitä perinteisesti harmaaksi, siniseksi, vaaleanvihreäksi ja tummanvihreäksi), valkoiseksi (taustaväri) ja "tuntemattomaksi", mikä osoittaa, että paikalla olevaa pikseliä ei voitu tunnistaa yhteenkään tunnetuista kukista. Nimeä ehdollisesti - koska tällä hetkellä pääsen eroon kolmesta kanavasta ja siirryn tuttuun ja kätevään yksiväriseen kuvaan.

Seuraava askel oli viivojen puhdistaminen kuvasta. Tässä tilanteen pelastaa se, että nämä viivat ovat erittäin ohuita - vain 1 pikseli. Yksinkertainen suodatin ehdottaa itseään: kävele koko kuvan läpi vertaamalla kunkin pikselin väriä sen naapureiden väreihin (pareittain - pysty- ja vaakasuunnassa); jos naapurit vastaavat väriä, mutta eivät vastaa itse pikselin väriä - tee siitä sama kuin naapurit. Käytän hieman kehittyneempää versiota samasta suodattimesta, joka toimii kahdessa vaiheessa. Ensimmäisessä se arvioi naapurit etäisyydellä 2, toisella - etäisyydellä 1. Tämän avulla voit saavuttaa seuraavan vaikutuksen:

Seuraavaksi pääsen eroon suurimmasta osasta tahroista sekä "tuntemattomasta" väristä. Tätä varten etsin ensin kaikki pienet liitetyt alueet (tarkasti alle 15), laitan ne mustavalkoiseen maskiin, minkä jälkeen yhdistän tuloksen "tuntemattoman" värin miehittämiin alueisiin. .

Näiden maskien avulla asetin Inpaint-algoritmin (tai pikemminkin sen toteutuksen OpenCV:ssä). Tämän avulla voit erittäin tehokkaasti puhdistaa suurimman osan roskista kuvasta.

Tämän algoritmin toteutus OpenCV:ssä on kuitenkin suunniteltu toimimaan valokuvien ja videoiden kanssa, eikä se tunnista keinotekoisesti luotuja kuvia, joissa on kohinaa. Sen soveltamisen jälkeen näkyviin tulee liukuvärejä, joita haluaisimme välttää segmentoinnin yksinkertaistamiseksi. Siksi on tarpeen suorittaa lisäkäsittely, nimittäin teroitus. Jokaisen pikselin värille lasken sitä lähimmän värin yllä olevasta taulukosta (muista, että väriä on 5 - yksi kullekin hahmotekstuurille ja valkoinen).

Lopuksi esikäsittelyn viimeinen vaihe on poistaa kaikki jäljellä olevat pienet yhdistetyt alueet. Ne ilmestyvät Inpaint-sovelluksen jälkeen, joten tässä ei ole toistoa.

Siirrytään segmentointiin. Sitä vaikeuttaa suuresti se, että symbolit ovat hyvin lähellä toisiaan. Saattaa käydä niin, että puolet toisesta ei näy yhden symbolin takaa. Siitä tulee todella huono, kun nämä symbolit ovat myös samanvärisiä. Lisäksi roskilla on rooli - voi käydä niin, että alkuperäisessä kuvassa viivat leikkaavat suuren määrän yhdessä paikassa. Tässä tapauksessa aiemmin kuvailemani algoritmi ei pysty pääsemään niistä eroon.

Vietettyäsi viikon tuloksettomissa yrityksissä kirjoittaa segmentointia samalla tavalla kuin aikaisemmissa tapauksissa, luovuin tästä asiasta ja vaihdoin taktiikkaa. Uusi strategiani oli jakaa koko segmentointiprosessi kahteen osaan. Ensimmäisessä arvioidaan symbolien kiertokulma ja suoritetaan kääntäminen taaksepäin. Toisessa kuvassa merkit valitaan uudelleen jo laajennetusta kuvasta. Joten aloitetaan. Aloitetaan, kuten aina, liitäntäkomponenttien etsimisellä.

Sitten sinun on arvioitava kunkin merkin kiertokulma. Jopa Greenpeace-fanioperaattorin kanssa työskennellessäni keksin tälle algoritmin, mutta kirjoitin ja sovelsin sitä vain tänne. Havainnollistaakseni hänen työtään piirrän vertauksen. Kuvittele mäntä liikkuvan kohti mustavalkoista symbolin kuvaa alhaalta ylöspäin. Männän kahva, jolla sitä työnnetään, sijaitsee pystysuorassa, työtaso, jolla sitä työnnetään, on vaakasuora, yhdensuuntainen kuvan alaosan kanssa ja kohtisuorassa kahvaan nähden. Kahva on kiinnitetty alustaan ​​keskeltä ja kiinnityskohdassa on liikkuva liitos, jonka seurauksena lava pääsee pyörimään. Anteeksi terminologit.

Anna kahvan liikkua ylöspäin työntämällä tyynyä sen eteen fysiikan lakien mukaisesti. Oletetaan, että vain symbolin valkoinen kuva on materiaalia ja mäntä kulkee helposti mustan taustan läpi. Sitten mäntä, saavuttanut valkoisen värin, alkaa olla vuorovaikutuksessa sen kanssa, nimittäin kääntyä - edellyttäen, että kahvaan kohdistuu edelleen voima. Hän voi pysähtyä kahdessa tapauksessa: jos hän lepäsi symbolia vasten voiman kohdistamiskohdan molemmilla puolilla tai jos hän lepää symbolia vasten voiman kohdistamispisteen kohdalla. Kaikissa muissa tapauksissa hän voi jatkaa liikkumista. Huomio, huipentuma: oletetaan, että symbolin kiertokulma on männän kaltevuuskulma sillä hetkellä, kun se pysähtyi.

Tämä algoritmi on melko tarkka, mutta ilmeisesti liian suuria tuloksia (yli 27 astetta) en ota huomioon. Muusta löydän aritmeettisen keskiarvon, jonka jälkeen kierrän koko kuvaa miinus tällä kulmalla. Sitten etsin liitäntäkomponentteja uudelleen.

Sitten se muuttuu yhä mielenkiintoisemmaksi. Aiemmissa esimerkeissä aloitin erilaisia ​​manipulaatioita vastaanotettujen segmenttien kanssa, minkä jälkeen lähetin ne neuroverkkoon. Täällä kaikki on toisin. Ensinnäkin, jotta ainakin osittain palautetaan tiedot, jotka kadonneet kuvan jakamisen jälkeen yhdistettyihin komponentteihin, piirrän jokaiseen niistä "taustan" tummanharmaalla (96) - mikä oli leikatun segmentin vieressä, mutta ei pudonnut siihen , jonka jälkeen tasoitan merkkien ääriviivat samalla menettelyllä kuin rivien esikäsittelyssä (etäisyys naapuriin on yksi).

Muodollisesti (ohjelmamoduulien osalta) segmentointi päättyy tähän. Tarkkaan lukijan on täytynyt huomata, ettei missään ollut mainintaa tahmeiden merkkien erottelusta. Kyllä, tämä on totta - välitän ne tunnustusta varten tässä muodossa ja viimeistelen ne paikan päällä.

Syynä on se, että aiemmin kuvattu tahmeiden merkkien erottelutapa (pienimmällä projektiolla) ei toimi täällä - kirjasimen ovat valinneet kirjoittajat erittäin hyvin. Siksi on omaksuttava erilainen, monimutkaisempi lähestymistapa. Tämä lähestymistapa perustuu ajatukseen, että Segmentointiin voidaan käyttää neuroverkkoa.

Aivan alussa kuvailin algoritmin, jonka avulla voit löytää merkkien lukumäärän segmentistä tämän segmentin leveyden ja merkkien kokonaismäärän perusteella. Tässä käytetään samaa algoritmia. Jokaiselle segmentille lasketaan siinä olevien merkkien määrä. Jos se on siellä yksin, mitään ei tarvitse tehdä loppuun, ja tämä segmentti lähetetään heti >>= hermoverkkoon. Jos symboleja on enemmän kuin yksi, potentiaaliset erottimet sijoitetaan segmentin varrelle yhtä etäisyydelle. Sitten jokainen erotin liikkuu pienessä naapurustossa, ja matkan varrella neuroverkon reaktio tämän erottimen ympärillä oleviin merkkeihin lasketaan, minkä jälkeen jää vain valita maksimi (itse asiassa melko tyhmä algoritmi tekee kaiken tämän siellä , mutta periaatteessa kaikki on oikeastaan ​​suunnilleen sama).

Luonnollisesti hermoverkon osallistuminen segmentointiprosessiin (tai esisegmentointiin, jos haluat) sulkee pois mahdollisuuden käyttää jo kuvailemaani neuroverkon koulutusjärjestelmää. Tarkemmin sanottuna se ei salli sinun saada ensimmäistä hermoverkkoa - sitä voidaan käyttää muiden kouluttamiseen. Siksi toimin melko yksinkertaisesti - käytän tavanomaisia ​​segmentointimenetelmiä (projisointi) neuroverkon kouluttamiseen, kun taas sitä käytettäessä yllä oleva algoritmi tulee peliin.

Tässä algoritmissa hermoverkon käyttöön liittyy toinen hienovaraisuus. Aiemmissa esimerkeissä hermoverkkoa koulutettiin esikäsittelyn ja segmentoinnin lähes raakatuloksilla. Täällä se mahdollisti enintään 12 % onnistuneen tunnustuksen saamisen. Se ei todellakaan sopinut minulle. Siksi ennen kuin aloitin seuraavan hermoverkon harjoittelun aikakauden, lisäsin alkuperäisiin kuviin erilaisia ​​vääristymiä, jotka karkeasti simuloivat todellisia: lisää valkoisia / harmaita / mustia pisteitä, harmaita viivoja / ympyröitä / suorakulmioita, pyöritä. Lisäksi lisäsin junasarjan 200 kuvasta 300:aan ja lisäsin ns validset harjoituksen laadun tarkistamiseksi harjoituksen aikana 100 kuvalla. Tämä mahdollisti noin viiden prosentin suorituskyvyn kasvun, ja yhdistettynä neuroverkon segmentoimiseen se antoi juuri sellaisen tuloksen, josta puhuin artikkelin alussa.

Tilastojen toimittaminen on monimutkaista sen vuoksi, mihin päädyin kaksi neuroverkot: yksi antoi suuremman tunnistusprosentin ja toinen - pienemmän virheen. Tässä esittelen ensimmäisen tulokset.

Yhteensä, kuten olen toistuvasti sanonut, testisarjassa oli 100 kuvaa. Näistä 20 tunnistettiin onnistuneesti, 80 epäonnistui, ja virhe oli 1,91 merkkiä per kuva. Huomattavasti huonompi kuin kaikki muut operaattorit, mutta CAPTCHA on sopiva.

Päätelmän sijaan

Kaiken tähän työhön liittyvän julkaisin verkkosivustollani erityisessä keskusteluketjussa, erityisesti: lähdekoodi, Netsukuku). Samalla haluan jotain, mikä ensinnäkin voidaan tehdä vuodessa (ainakin yhdessä), ja toiseksi vaatisi vakavasti korkeaa paikkaa samassa ISEF:ssä. Ehkä voit ehdottaa, mihin suuntaan minun pitäisi liikkua?

Hyvää päivää! Äskettäin "uteliaisilta" vaadittiin joihinkin tarpeisiin captcha Pythonissa. Googlesta katsottu, eikä mitään normaalia ilman Django ei nähnyt. Tuloksena tulin siihen tulokseen, että en kirjoittaisi erillisenä WSGI sovellus, mutta vain CGI käsikirjoitus.

Paketti on valittu toimimaan kuvien kanssa Python Imaging Library. Valitettavasti PIL tarjoaa hieman niukkoja ominaisuuksia verrattuna GD2 PHP:ssä.

Voit ladata paketin Python-versioille 2 ja 3 täältä: http://www.lfd.uci.edu/~gohlke/pythonlibs/

Haluan heti huomauttaa, että sitä käytetään Python 3.1, vaikka uskon sen toimivan myös Python 2.6+ -versiossa.

Ja niin loppujen lopuksi meidän pitäisi saada 5-6 merkin kuvasukupolvi moniväriselle taustalle.

Koska en lähetä arkistoa kaiken valmiina, teemme kaiken käsikirjan mukaan.

Hakemistot ja niiden hierarkia:

cgi-bin
- captcha
- taustat
-fontit
--index.py

Mielestäni tämä tekee selväksi, että cgi-bin-kansio sisältää captcha-kansion, joka sisältää taustat ja kirjasimet, ja itse index.py-komentosarjan.

Nyt tarvitaan taustat. Ajamme "taustat" Googleen. Kuvia ja lataa 15-20 kpl. Ja sinun on tehtävä sellaisia ​​suorakulmioita, joiden koko on 200x60 px muodossa JPEG.

Heitämme kaiken taustat-kansioon.

Nyt fontit. Olemme kiinnostuneita oikea tyyppi fontit (*.ttf). Otamme noin 15 fonttia enemmän käänteitä ja heitämme ne kirjasinkansioon.

Kaikki taustat ovat siellä, fontit ovat siellä, nyt itse index.py.

Print("Sisältötyyppi: kuva/jpeg"); Tulosta(""); tuonti sys, os, re, satunnainen PIL:stä tuonti Image, ImageFont, ImageDraw-luokka captcha(object): def __init__(self): self.string = ""; self.root = os.getcwd(); self.path_backgrounds = self.root+"/backgrounds/"; self.path_fonts = self.root+"/fonts/"; def gen_string(self): merkit = ("a", "b", "d", "e", "f", "g", "h", "j", "m", "n", " q", "r", "t", "u", "y", "A", "B", "D", "E", "F", "G", "H", "J" , "M", "N", "Q", "R", "T", "U", "Y", "1", "2", "3", "4", "5", " 6", "7", "8", "9"); i:lle alueella(random.randint(5, 6)): itse.merkkijono += merkkiä; return self.string; def gen_backgrounds(self): images = ; jos os.path.exists(self.path_backgrounds): f:lle os.listdir(self.path_backgrounds): if os.path.isdir(self.path_backgrounds+"/"+f): jatka; if re.search("\.(jpeg|jpg)$", f, re.IGNORECASE): images.append(self.path_backgrounds+"/"+f); muu: sys.exit(); if len(kuvat) == 0: sys.exit(); palauttaa kuvia; def gen_fonts(self): fontit = ; jos os.path.exists(self.path_fonts): f:lle os.listdir(self.path_fonts): jos os.path.isdir(self.path_fonts+"/"+f): jatka; if re.search("\.(ttf)$", f, re.IGNORECASE): fonts.append(self.path_fonts+"/"+f); muu: sys.exit(); if len(fontit) == 0: sys.exit(); palauttaa fontit; def gen_image(self): merkkijono = self.gen_string(); taustat = self.gen_backgrounds(); fontit = self.gen_fonts(); kuva = Kuva.uusi("RGB", (200,60), "#FFF") piirto = ImageDraw.Draw(image); i:lle alueella(5): background = Image.open(taustat); x = satunnainen randint(0, 160); cp = tausta.rajaus((x, 0, x+40, 60)); image.paste(cp, (i*40, 0)); jos len(merkkijono) == 5: x = satunnainen.randint(25, 30); muuten: x = satunnainen randint(8, 11); merkkijonolle: font = fontit; y = satunnainen randint(5, 25); fontin_koko = random.randint(24, 30); color_dark = "rgb("+str(random.randint(0,150))+","+str(random.randint(0,100))+","+str(random.randint(0,150))+")"; color_font = "rgb("+str(random.randint(50,200))+","+str(random.randint(0,150))+","+str(random.randint(50,200))+")"; ttf = ImageFont.truetype(font, font_size) draw.text((x+1, y+1), char, fill=color_dark, font=ttf) draw.text((x, y), char, fill=color_font, font=ttf) x += random.randint(13, 15) + 18; image.save(sys.stdout, "JPEG") cp = captcha(); cp.gen_image(); #cp.string; merkkijono

Siinä kaikki. Minulla on kuva luotu osoitteessa http://localhost/cgi-bin/captcha/index.py. Seuraavaksi voit lisätä tallennusmekanismin luodulle merkkijonolle ( cp.string) istunnoista tai jostain muualta.

Suurin osa ihmisistä ei tiedä, mutta opinnäytetyöni oli ohjelma tekstin lukemiseen kuvasta. Ajattelin, että jos saisin korkean tunnustuksen, sitä voitaisiin käyttää hakutulosten parantamiseen. Erinomainen neuvonantajani tohtori Gao Junbing ehdotti, että kirjoitan väitöskirjan tästä aiheesta. Lopulta löysin aikaa kirjoittaa tämä artikkeli ja yritän täällä puhua kaikesta, mitä olen oppinut. Jospa jotain tällaista olisi ollut kun aloitin...

Kuten aiemmin sanoin, yritin ottaa tavallisia kuvia Internetistä ja poimia niistä tekstiä hakutulosten parantamiseksi. Suurin osa ideoistani perustui captcha-krakkaustekniikoihin. Kuten kaikki tietävät, captchat ovat niitä ärsyttäviä asioita, kuten "Syötä kuvassa näkyvät kirjaimet" rekisteröinti- tai palautesivuilla.

Captcha on suunniteltu niin, että ihminen voi lukea tekstiä vaivattomasti, kun taas kone ei (hei, reCaptcha!). Käytännössä tämä ei koskaan toiminut, koska melkein jokainen sivustolle lähetetty captcha hakkeroitiin muutaman kuukauden sisällä.

Meni aika hyvin - yli 60% kuvista ratkaistiin onnistuneesti pienestä kokoelmastani. Melko hyvä ottaen huomioon Internetin erilaisten kuvien määrä.

Tutkimuksessani en löytänyt mitään materiaalia, joka auttaisi minua. Kyllä, on artikkeleita, mutta ne sisältävät hyvin yksinkertaisia ​​algoritmeja. Itse asiassa löysin joitakin toimimattomia esimerkkejä PHP:stä ja Perlistä, otin niistä muutaman fragmentin ja sain hyviä tuloksia hyvin yksinkertaiseen captchaan. Mutta mikään niistä ei auttanut minua paljon, koska se oli liian yksinkertaista. Olen yksi niistä ihmisistä, jotka voivat lukea teorian, mutta eivät ymmärrä mitään ilman todellisia esimerkkejä. Ja useimmissa artikkeleissa kirjoitettiin, että he eivät julkaise koodia, koska he pelkäsivät, että sitä käytetään huonoihin tarkoituksiin. Henkilökohtaisesti mielestäni captcha on ajanhukkaa, koska se on melko helppo ohittaa, jos osaat.

Itse asiassa, koska aloittelijoille captcha-hakkerointia osoittavista materiaaleista puuttui, kirjoitin tämän artikkelin.

Aloitetaan. Tässä on luettelo siitä, mitä aion käsitellä tässä artikkelissa:

  • Käytetyt tekniikat
  • Mikä on captcha
  • Kuvantunnistus tekoälyllä
  • koulutus
  • Laittamalla kaikki yhteen
  • Tulokset ja johtopäätökset

Käytetyt tekniikat

Kaikki esimerkit on kirjoitettu Python 2.5:ssä käyttäen PIL-kirjastoa. Pitäisi toimia myös Python 2.6:ssa.

Asenna ne yllä olevassa järjestyksessä ja olet valmis suorittamaan esimerkit.

Vetäytyä

Esimerkeissä koodaan monia arvoja suoraan koodiin. Minulla ei ole tavoitetta luoda universaalia captcha-selvittäjää, vaan vain näyttää kuinka se tehdään.

Captcha, mikä se loppujen lopuksi on?

Periaatteessa captcha on esimerkki yksisuuntaisesta muuntamisesta. Voit helposti ottaa joukon merkkejä ja saada siitä captchaa, mutta et päinvastoin. Toinen hienous on, että sen pitäisi olla helppo ihmisen luettavissa, mutta ei koneen tunnistettavassa. Captchaa voidaan pitää yksinkertaisena "Oletko ihminen?" -testinä. Pohjimmiltaan ne toteutetaan kuvana, jossa on joitain symboleja tai sanoja.

Niitä käytetään estämään roskapostia monilla Internet-sivustoilla. Esimerkiksi captcha löytyy Windows Live ID -rekisteröintisivulta.

Sinulle näytetään kuva, ja jos olet todella henkilö, sinun on kirjoitettava sen teksti erilliseen kenttään. Vaikuttaako hyvältä ajatukselta, joka voi suojata sinua tuhansilta automaattisilta rekisteröinniltä roskapostiksi tai Viagran jakamiselta keskusteluryhmässäsi? Ongelmana on, että tekoäly ja erityisesti kuvantunnistusmenetelmät ovat kokeneet merkittäviä muutoksia ja ovat tulossa erittäin tehokkaiksi tietyillä alueilla. OCR (Optical Character Recognition) on nykyään melko tarkka ja tunnistaa painetun tekstin helposti. Päätettiin lisätä värejä ja viivoja, jotta tietokoneen olisi vaikea työskennellä ilman haittaa käyttäjille. Tämä on eräänlainen kilpavarustelu, ja kuten tavallista, tehokkaampia aseita keksitään mihin tahansa puolustukseen. Parannetun captchan päihittäminen on vaikeampaa, mutta silti mahdollista. Lisäksi kuvan tulee pysyä melko yksinkertaisena, jotta se ei ärsytä tavallisia ihmisiä.

Tämä kuva on esimerkki captchasta, jonka tulkitsemme. Tämä on todellinen captcha, jota isännöidään oikealla sivustolla.

Tämä on melko yksinkertainen captcha, joka koostuu samanvärisistä ja -kokoisista hahmoista valkoisella taustalla, jossa on kohinaa (pikseleitä, värejä, viivoja). Luuletko, että tämä taustamelu tekee sen tunnistamisen vaikeaksi, mutta näytän sinulle, kuinka helppoa se on poistaa. Vaikka tämä ei ole kovin vahva captcha, se on hyvä esimerkki ohjelmallemme.

Kuinka löytää ja poimia tekstiä kuvista

On olemassa monia menetelmiä tekstin sijainnin määrittämiseen kuvassa ja sen poimimiseen. Googlen avulla löydät tuhansia artikkeleita, jotka selittävät uusia tekstihaun menetelmiä ja algoritmeja.

Tässä esimerkissä käytän värinpoistoa. Tämä on melko yksinkertainen tekniikka, jolla sain aika hyviä tuloksia. Tätä tekniikkaa käytin väitöskirjassani.

Esimerkeissämme käytän moniarvoisen kuvan hajottelualgoritmia. Pohjimmiltaan tämä tarkoittaa, että piirrämme ensin kuvan värien histogrammin. Tämä tehdään keräämällä kuvan kaikki pikselit värien mukaan ja laskemalla sitten jokainen ryhmä. Jos katsot testi captchaa, näet kolme pääväriä:

  • Valkoinen tausta)
  • Harmaa (kohina)
  • Punainen (teksti)

Pythonissa tämä näyttää hyvin yksinkertaiselta.

Seuraava koodi avaa kuvan, muuntaa sen GIF-muotoon (helpottaa meitä, koska siinä on vain 255 väriä) ja tulostaa värihistogrammin.

PIL-tuonnista Image im = Image.open("captcha.gif") im = im.convert("P") print im.histogram()

Tuloksena saamme seuraavat:

Tässä näemme kuvan kunkin 255 värin pikselien lukumäärän. Voit nähdä, että valkoinen (255, uusin) on yleisin. Sitä seuraa punainen (teksti). Vahvista tämä kirjoittamalla pieni käsikirjoitus:

PIL-tuonti Kuva operaattorilta import itemgetter im = Image.open("captcha.gif") im = im.convert("P") his = im.histogram() arvot = () i:lle alueella(256) : arvot [i] = hänen[i] kohteelle j,k lajiteltuna(arvot.kohteet(), avain=tuotetekijä(1), käänteinen=tosi)[:10]: tulosta j,k

Ja saamme seuraavat tiedot:

Tämä on luettelo kuvan 10 yleisimmästä väristä. Kuten odotettiin, valkoinen toistuu useimmiten. Sitten tulee harmaa ja punainen.

Kun meillä on nämä tiedot, luomme uusia kuvia näiden väriryhmien perusteella. Jokaiselle yleisimmille väreille luomme uuden binaarikuvan (2 väriä), jossa kyseisen värin pikselit täytetään mustalla ja kaikki muu valkoisella.

Punaisesta on tullut meille kolmanneksi yleisin väri, mikä tarkoittaa, että haluamme tallentaa ryhmän pikseleitä värillä 220. Kokeilun aikana huomasin, että väri 220 on melko lähellä 220:ta, joten tallennamme tämän pikselryhmän nimellä hyvin. Alla oleva koodi avaa captchan, muuntaa sen GIF:ksi, luo uuden samankokoisen kuvan valkoisella taustalla ja toistaa sitten alkuperäisen kuvan yli etsimään haluamaamme väriä. Jos se löytää pikselin, jolla on tarvitsemamme väri, se merkitsee saman pikselin toisessa kuvassa mustalla. Toinen kuva tallennetaan ennen kuin työ on valmis.

PIL-tuonnista Image im = Image.open("captcha.gif") im = im.convert("P") im2 = Image.new("P",im.size,255) im = im.convert("P" ") lämpötila = () x:lle alueella(im.size): y:lle alueella(im.size): pix = im.getpixel((y,x)) temp = pix, jos pix == 220 tai pix == 227: # Näillä numeroilla saadaan im2.putpixel((y,x),0) im2.save("output.gif")

Tämän koodinpätkän suorittaminen antaa meille seuraavan tuloksen.

Kuvasta näet, että onnistuimme poimimaan tekstin taustalta. Voit automatisoida tämän prosessin yhdistämällä ensimmäisen ja toisen komentosarjan.

Kuulen sinun kysyvän: "Entä jos captcha-teksti on kirjoitettu eri väreillä?". Kyllä, tekniikkamme toimii edelleen. Oletetaan, että yleisin väri on taustaväri ja sitten löydät merkkivärit.

Olemme siis toistaiseksi onnistuneet poimimaan tekstin kuvasta. Seuraava vaihe on määrittää, sisältääkö kuva tekstiä. En kirjoita tähän vielä koodia, koska se tekee sen ymmärtämisen vaikeaksi, kun taas algoritmi itsessään on melko yksinkertainen.

Jokaiselle binäärikuvalle: jokaiselle binäärikuvan pikselille: jos pikseli on päällä: jos sen vieressä on jokin aiemmin näkemämme pikseli: lisää samaan joukkoon muu: lisää uuteen joukkoon

Tulosteena sinulla on joukko merkkirajoja. Sitten sinun tarvitsee vain verrata niitä toisiinsa ja katsoa, ​​ovatko ne johdonmukaisia. Jos kyllä, osuit jättipottiin ja tunnistit oikein vierekkäin kulkevat symbolit. Voit myös tarkistaa tuloksena olevien alueiden koon tai yksinkertaisesti luoda uuden kuvan ja näyttää sen (show()-menetelmä kuvassa) varmistaaksesi, että algoritmi on tarkka.

PIL-tuonnista Image im = Image.open("captcha.gif") im = im.convert("P") im2 = Image.new("P",im.size,255) im = im.convert("P" ") lämpötila = () x:lle alueella(im.size): y:lle alueella(im.size): pix = im.getpixel((y,x)) temp = pix, jos pix == 220 tai pix == 227: # näistä numeroista saadaan im2.putpixel((y,x),0) # uusi koodi alkaa tästä inletter = Väärä löytynyt kirjain = Väärä alku = 0 loppu = 0 kirjainta = y:lle alueella (im2.size): # slice poikki x:lle alueella(im2.size): # leikkaa alas pix = im2.getpixel((y,x)) if pix != 255: inletter = True if foundretter == False ja inletter == True: foundretter = Tosi alku = y jos löytynyt kirjain == Tosi ja kirjain == Väärin: löytynyt kirjain = väärä loppu = y kirjaimet.append((alku,loppu)) inletter=Väärät kirjaimet

Tuloksena saimme seuraavan:

[(6, 14), (15, 25), (27, 35), (37, 46), (48, 56), (57, 67)]

Nämä ovat kunkin merkin alun ja lopun vaakasuuntaiset paikat.

AI ja vektoriavaruus kuviontunnistuksessa

Kuvantunnistusta voidaan pitää modernin tekoälyn suurimmana menestyksenä, mikä on mahdollistanut sen soluttautumisen kaikenlaisiin kaupallisiin sovelluksiin. Postinumerot ovat tästä täydellinen esimerkki. Itse asiassa monissa maissa ne luetaan automaattisesti, koska tietokoneen opettaminen tunnistamaan numeroita on melko yksinkertainen tehtävä. Se ei ehkä ole ilmeistä, mutta hahmontunnistusta pidetään tekoälyongelmana, vaikkakin hyvin erikoistuneena ongelmana.

Melkein ensimmäinen asia, johon hahmontunnistuksessa tekoälyyn tutustuessa törmää, ovat hermoverkot. Henkilökohtaisesti en ole koskaan onnistunut hermoverkkojen kanssa hahmontunnistuksessa. Harjoittelen sitä yleensä 3-4 symbolille, jonka jälkeen tarkkuus putoaa niin alas, että se olisi suuruusluokkaa suurempi, jos arvaisin symbolit satunnaisesti. Aluksi tämä aiheutti minulle pientä paniikkia, koska se oli väitöskirjani puuttuva lenkki. Onneksi luin äskettäin artikkelin vektoriavaruuden hakukoneista ja huomasin niiden olevan vaihtoehtoinen menetelmä tietojen luokitteluun. Lopulta ne osoittautuivat parhaaksi valinnaksi, koska.

  1. Ne eivät vaadi laajaa tutkimusta.
  2. Voit lisätä/poistaa virheellisiä tietoja ja nähdä tuloksen välittömästi
  3. Niitä on helpompi ymmärtää ja ohjelmoida
  4. Ne tarjoavat luokiteltuja tuloksia, jotta voit nähdä parhaat X ottelut
  5. Etkö tunnista jotain? Lisää tämä ja tunnistat sen välittömästi, vaikka se olisi täysin erilainen kuin aiemmin nähty.

Ilmaista juustoa ei tietenkään ole olemassa. Suurin haittapuoli on nopeus. Ne voivat olla paljon hitaampia kuin neuroverkot. Mutta uskon, että niiden edut painavat edelleen tämän haitan.

Jos haluat ymmärtää, kuinka vektoriavaruus toimii, suosittelen lukemaan vektoriavaruuden hakukoneteorian. Tämä on paras löytämäni aloittelijalle.

Rakensin kuvantunnistukseni yllä olevan dokumentin pohjalta ja tämä oli ensimmäinen asia, jonka yritin kirjoittaa tuolloin opiskelemaani suosikkikirjaani. Lue tämä asiakirja ja kun ymmärrät sen olemuksen, palaa tänne.

Oletko jo palannut? Okei. Nyt meidän on ohjelmoitava vektoriavaruutemme. Onneksi se ei ole ollenkaan vaikeaa. Aloitetaan.

Tuo matemaattinen luokka VectorVertaa: def magnitudi(itse,konkordanssi): yhteensä = 0 sanalle,count in concordance.iteritems(): yhteensä += count ** 2 return math.sqrt(yhteensä) def-relaatio(itse,yhdenmukaisuus1, konkordanssi2) : relevanssi = 0 topvalue = 0 sanalle, laske konkordanssi1.iteritems(): if concordance2.has_key(word): topvalue += count * concordance2 return topvalue / (self.magnitude(concordance1) * self.magnitude(concordance2))

Tämä on 15-rivinen vektoriavaruuden toteutus Pythonissa. Pohjimmiltaan se vaatii vain 2 sanakirjaa ja palauttaa numeron väliltä 0 ja 1, mikä osoittaa, kuinka ne liittyvät toisiinsa. 0 tarkoittaa, että ne eivät liity toisiinsa, ja 1 tarkoittaa, että ne ovat identtisiä.

koulutus

Seuraavaksi tarvitsemme joukon kuvia, joihin vertaamme symboleitamme. Tarvitsemme harjoitussarjan. Tällä sarjalla voidaan kouluttaa mitä tahansa käyttämäämme tekoälyä (hermoverkot jne.).

Käytetty data voi muuttaa elämää tunnistamisen onnistumisen kannalta. Mitä paremmat tiedot, sitä suurempi mahdollisuus onnistua. Koska aiomme tunnistaa tietyn captchan ja voimme jo poimia siitä merkkejä, miksi et käyttäisi niitä harjoitussarjana?

Tämän tein. Latasin paljon luotuja captchoja ja ohjelmani jakoi ne kirjaimiin. Sitten keräsin vastaanotetut kuvat kokoelmiin (ryhmiin). Useiden yritysten jälkeen minulla oli ainakin yksi esimerkki jokaisesta captchan luomasta merkistä. Lisää esimerkkejä lisää tunnistuksen tarkkuutta, mutta tämä riitti minulle vahvistamaan teoriani.

PIL-tuonnista Kuvan tuonti hashlib tuontiaika im = Image.open("captcha.gif") im2 = Image.new("P",im.size,255) im = im.convert("P") temp = () tulosta im.histogrammi() x:lle alueella(im.size): y:lle alueella(im.size): pix = im.getpixel((y,x)) temp = pix, jos pix == 220 tai pix == 227: # näistä numeroista saadaan im2.putpixel((y,x),0) inletter = Väärä löytynyt kirjain = Väärä alku = 0 loppu = 0 kirjainta = y:lle alueella (im2.size): # slice poikki x:lle in range(im2.size): # slice down pix = im2.getpixel((y,x)) if pix != 255: inletter = True if foundretter == False ja inletter == True: foundretter = True start = y if foundletter == Tosi ja kirjain == Väärä: löytynyt kirjain = Väärä loppu = y letters.append((alku,loppu)) inletter=False # Uusi koodi on täällä. Puramme vain jokaisen kuvan ja tallennamme sen levylle # mikä on toivottavasti yksilöllinen nimi count = 0 kirjaimille: m = hashlib.md5() im3 = im2.crop((kirjain , 0, kirjain,im2.size) ) m.update("%s%s"%(time.time(),count)) im3.save("./%s.gif"%(m.hexdigest())) count += 1

Tämän seurauksena saamme joukon kuvia samassa hakemistossa. Jokaiselle niistä on määritetty yksilöllinen hajautus, jos käsittelet useita captchia.
Tässä on tämän koodin tulos testi captchalle:

Päätät kuinka tallennat nämä kuvat, mutta laitan ne hakemistoihin, joilla on sama nimi kuin kuvassa (merkki tai numero).

Laittamalla kaikki yhteen

Viimeinen askel. Meillä on tekstinpoisto, merkkipoimiminen, tunnistustekniikka ja koulutussarja.

Hankimme captcha-kuvan, poimimme tekstin, hankimme hahmot ja vertaamme niitä sitten harjoitussarjaamme. Voit ladata lopullisen ohjelman harjoitussarjan ja joidenkin captchien kanssa tästä linkistä.

Tässä vain lataamme harjoitussarjan, jotta voimme verrata sitä:

Def buildvector(im): d1 = () count = 0 i:lle im.getdata(): d1 = i count += 1 return d1 v = VectorCompare() iconset = ["0","1","2" "3", "4", "5", "6", "7", "8", "9", "0", "a", "b", "c", "d"," e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q" "r", "s", "t"," u", "v", "w", "x", "y", "z"] kuvasarja = kirjaimelle kuvakejoukossa: img:lle os.listdir (""./iconset/%s/"%(kirjain)): temp = if img != "Thumbs.db": temp.append(buildvector(Image.open("./iconset/%s/%s") % (kirjain,kuva)))) imageset.append((kirjain:temp))

Ja tässä kaikki taika tapahtuu. Määritämme kunkin merkin sijainnin ja testaamme sitä vektoriavaruudellamme. Sitten lajittelemme tulokset ja tulostamme ne.

Lasku = 0 kirjaimille: m = hashlib.md5() im3 = im2.crop((kirjain , 0, kirjain,im2.koko)) arvaus = kuvalle kuvajoukossa: x,y:lle kuvassa.iteritems() : if len(y) != 0: arvaa.append((v.relation(y,buildvector(im3)),x)) arvaa.sort(reverse=True) print "",arvausmäärä += 1

johtopäätöksiä

Nyt meillä on kaikki mitä tarvitsemme ja voimme yrittää käynnistää ihmekoneemme.

Syöttötiedosto on captcha.gif . Odotettu tulos: 7s9t9j

python crack.py

Tässä näemme oletetun symbolin ja sen varmuuden asteen, että se todella on se (0 - 1).

Näyttää siltä, ​​että teimme sen todella!

Itse asiassa testi captchoissa tämä komentosarja antaa onnistuneen tuloksen noin 22 prosentissa tapauksista.

Python crack_test.py Oikeita arvauksia - 11,0 Vääriä arvauksia - 37,0 Prosenttia oikein - 22,9166666667 Prosenttiosuuksia väärin - 77,0833333333

Suurin osa virheellisistä tuloksista johtuu numeron "0" ja kirjaimen "O" virheellisestä tunnistamisesta. Ei ole mitään odottamatonta, koska ihmisetkin usein hämmentävät ne. Meillä on edelleen ongelma hahmojen jakamisessa, mutta tämä voidaan ratkaista yksinkertaisesti tarkistamalla jakamisen tulos ja etsimällä onnellinen media.

Kuitenkin jopa tällaisella ei kovin täydellisellä algoritmilla voimme ratkaista joka viidennen captcha-lauseen aikana, jolloin henkilöllä ei olisi aikaa ratkaista edes yhtä.

Tämän koodin suorittaminen Core 2 Duo E6550:ssä tuottaa seuraavat tulokset:

Todellinen 0m5.750s käyttäjä 0m0.015s sys 0m0.000s

Luettelossamme on 48 captchaa, mikä tarkoittaa, että yhden ratkaiseminen kestää noin 0,12 sekuntia. 22 %:n onnistumisprosenttimme ansiosta voimme ratkaista noin 432 000 captchaa päivässä ja saada 95 040 oikeaa vastausta. Mitä jos käytät monisäikeistystä?

Siinä kaikki. Toivon, että käytät kokemuksiani hyviin tarkoituksiin. Tiedän, että voit käyttää tätä koodia vahingoittaaksesi, mutta tehdäksesi jotain todella vaarallista, sinun on muutettava sitä melko paljon.

Niille, jotka yrittävät suojata itseään captchoilla, voin sanoa, että tämä ei auta sinua paljon, koska ne voidaan ohittaa ohjelmallisesti tai yksinkertaisesti maksaa muille ihmisille niiden ratkaisemisesta manuaalisesti. Harkitse muita suojakeinoja.

Päätin hallita Pythonia hieman, mutta "jos vain ei php" masterointi ei ole mielenkiintoista. Oma intressi on tullut Python captcha automaattinen ratkaisu.

Liike alkoi Habrin postauksella vuodesta 2012 (graafinen kirjasto yleensä vuonna 2009).
Koodi: https://habrahabr.ru/post/149091/

Minulla on 2.7.10 valmiina, ja koodi kirjoitettiin alle 2.5 (jommallakummalla PIL:llä). He kirjoittavat, että 2.7.3:lla se käynnistyy täydellisesti.

PIL rullattu näin
Koodi: #lataa
curl -O -L http://effbot.org/media/downloads/Imaging-1.1.7.tar.gz
# ottaa talteen
tar -xzf Imaging-1.1.7.tar.gz
cd Imaging-1.1.7
# rakentaa ja asentaa
python setup.py build
sudo python setup.py asennus
# tai asenna se vain sinulle ilman järjestelmänvalvojan oikeuksia:
# python setup.py install --user

Sitten toin moduulin tällä tavalla

Koodi: # kirjoita konsoliin
python
#ota käyttöön tulkki, jota komentaa
tuonti PIL
#jos kaikki on kunnossa, paina Ctrl+D poistuaksesi

Käärme ei ole ystävällinen kyrillisten aakkosten kanssa, lisäsi rakenteen tiedoston alkuun (jotta on mahdollista kommentoida käsityötä kyrillisillä kirjaimilla)
Koodi: # -*- koodaus: utf-8 -*-

Tässä itse polkupyörä (en osaa kirjoittaa kierroksia enkä osaa arvioida, joten vaihdoin paljon käsilläni).

Koodi: # -*- koodaus: utf-8 -*-
#tätä paskaa tarvitaan venäläisille hahmoille

PIL-tuontikuvasta

operaattorin tuontituotegetteriltä


im = im.muuntaa("P")
hänen = im.histogrammi()
arvot = ()

i alueella (256):
arvot[i] = hänen[i]

j,k:lle lajiteltu(arvot.kohteet(), avain=tuoteperustaja(1), käänteinen=True)[:15]:
tulosta "tai pix ==",j#,k

# muuttuja j tallentaa kymmenen suosituinta väriä

PIL-tuontikuvasta

im = Image.open("captcha.gif")
im = im.muuntaa("P")

im = im.muuntaa("P")

x alueella (im.size):
y:lle alueella (im.size):
pix = im.getpixel((y,x))
lämpötila = pikseliä
#värejä täällä
im2.putpixel((y,x),0)

im2.save("output.gif")

#täällä kaikki näyttää olevan taas alusta

PIL-tuontikuvasta

im = Image.open("output.gif")
im = im.muuntaa("P")
im2 = Kuva.uusi("P",im.koko,255)

im = im.muuntaa("P")

x alueella (im.size):
y:lle alueella (im.size):
pix = im.getpixel((y,x))
lämpötila = pikseliä
jos pix == 255: # nämä numerot saadaan
im2.putpixel((y,x),0)

# uusi koodi alkaa tästä

inletter = False
foundletter=False
aloitus = 0
loppu = 0


pix = im2.getpixel((y,x))
jos pix != 255:
inletter = Totta
löytökirjain = Totta
aloitus = y


löytynyt kirjain = False
end=y
letters.append((alku,loppu))

Inletter=False
tulostaa kirjaimia

#vikuna tietää

luokka VectorVertaa:
def magnitudi (itse, yhteensopivuus):
yhteensä = 0
sanalle laske koncordance.iteritems():
yhteensä += määrä ** 2
return math.sqrt(yhteensä)

Def-relaatio(itse,yhdenmukaisuus1, konkordanssi2):
relevanssi = 0
suurin arvo = 0
sanaa varten laske konkordanssi1.iteritems():
if concordance2.has_key(sana):
topvalue += count * concordance2
palauttaa huippuarvo / (self.magnitude(concordance1) * self.magnitude(concordance2))

#Merkistö

PIL-tuontikuvasta
tuoda hashlib
tuontiaika

im = Image.open("captcha.gif")
im2 = Kuva.uusi("P",im.koko,255)
im = im.muuntaa("P")

tulosta im.histogrammi()

x alueella (im.size):
y:lle alueella (im.size):
pix = im.getpixel((y,x))
lämpötila = pikseliä
#värejä täällä
jos pix == 187 tai pix == 224 tai pix == 188 tai pix == 223 tai pix == 145 tai pix == 151 tai pix == 181 tai pix == 144 tai pix == 225 tai pix == 182 tai pix == 189 tai pix == 12 tai pix == 17 tai pix == 139 tai pix == 152: # tai pix ==
im2.putpixel((y,x),0)

inletter = False
foundletter=False
aloitus = 0
loppu = 0

y:lle alueella (im2.size): # slice poikki
x:lle alueella(im2.size): # leikkaa alas
pix = im2.getpixel((y,x))
#tässä se oli "ei yhtä suuri kuin 255", eli se oli "ei yhtä suuri kuin valkoinen"
jos pix == 255:
inletter = Totta

Jos löytynyt kirjain == False ja inletter == tosi:
löytökirjain = Totta
aloitus = y

Jos löytynyt kirjain == tosi ja kirjain == false:
löytynyt kirjain = False
end=y
letters.append((alku,loppu))
inletter=False

# Uusi koodi on täällä. Puramme vain jokaisen kuvan ja tallennamme sen levylle
# mikä on toivottavasti ainutlaatuinen nimi

laskenta = 0
kirjaimille kirjaimilla:
m = hashlib.md5()
im3 = im2.crop((kirjain , 0, kirjain,im2.koko))
m.update("%s%s"%(time.time(),count))
im3.save("./%s.gif"%(m.hexdigest()))
laske += 1

Toimintaperiaate on seuraava: luo histogrammi, poista yleisimmät sävyt, tallenna loput uudelleen mustavalkoisina, jaa merkkien rajoja pitkin, vertaa merkkejä näytteisiin.

Alkuperäinen captcha, ilman 10 suosittua sävyä, ilman 15 suosittua sävyä (en jakanut sitä symboleiksi - koska siellä on ei-kokonaislukusymboli).

Alkuperäinen captcha, ilman 15 suosittua sävyä, jaettu 2 merkkiin (likainen).

Yksinkertaisella captchalla on täysin mahdollista lähettää ratkaisija. Tarvitsemme mielenkiintoisia paikkoja yksinkertaisilla captchoilla maaliin ja juoksemiseen.

On olemassa erilaisia ​​​​tapoja ohittaa CAPTCHA, jolla verkkosivustot on suojattu. Ensinnäkin on erikoispalveluita, jotka käyttävät halpaa käsityötä ja tarjoavat kirjaimellisesti ratkaista 1000 captchaa vain 1 dollarilla. Vaihtoehtoisesti voit yrittää kirjoittaa älykkään järjestelmän, joka tiettyjen algoritmien mukaan itse suorittaa tunnistuksen. Jälkimmäinen voidaan nyt toteuttaa erityisellä apuohjelmalla.

Ratkaise CAPTCHA

CAPTCHA-tunnistus on usein ei-triviaali tehtävä. Kuvaan on käytettävä paljon erilaisia ​​suodattimia vääristymien ja häiriöiden poistamiseksi, joilla kehittäjät haluavat vahvistaa suojaa. Usein joudut toteuttamaan hermoverkkoihin perustuvan oppimisjärjestelmän (tämä ei muuten ole niin vaikeaa kuin miltä se saattaa näyttää) saavuttaakseen hyväksyttävän tuloksen automaattiseen captcha-ratkaisuun. Ymmärtääksesi, mistä puhun, on parempi avata arkisto ja lukea upeat artikkelit CAPTCHA Cracking: Theory and Practice. Selvitetään kuinka captchat rikki" ja "Katsotaan ja tunnistetaan. Captcha-suodattimien hakkerointi” numeroista 135 ja 126. Tänään haluan kertoa teille TesserCapin kehityksestä, jota kirjoittaja kutsuu universaaliksi CAPTCHA-ratkaisijaksi. Mielenkiintoisia juttuja joka tapauksessa.

Katso ensin TesserCap

Mitä ohjelman kirjoittaja teki? Hän tarkasteli, kuinka automaattisen CAPTCHA-ratkaisun ongelmaa yleensä lähestytään, ja yritti tiivistää tämän kokemuksen yhteen työkaluun. Kirjoittaja huomasi, että kohinan poistamiseksi kuvasta, eli vaikeimman tehtävän ratkaisemiseksi captchojen tunnistamisessa, käytetään useimmiten samoja suodattimia. Osoittautuu, että jos otat käyttöön kätevän työkalun, jonka avulla voit käyttää suodattimia kuviin ilman monimutkaisia ​​matemaattisia muunnoksia, ja yhdistät sen tekstintunnistusjärjestelmään, voit saada täysin toimivan ohjelman. Tämän itse asiassa teki Gursev Singh Kalra McAfeesta. Miksi se oli tarpeen? Apuohjelman kirjoittaja päätti tällä tavalla tarkistaa, kuinka turvallisia suurten resurssien captchat ovat. Testaukseen valittiin ne Internet-sivustot, jotka ovat tunnetun tilastopalvelun mukaan eniten vierailtuja. Monstereista, kuten Wikipedia, eBay sekä captcha-palveluntarjoaja reCaptcha, tuli ehdokkaita osallistumaan testaukseen. Jos tarkastellaan yleisesti ohjelman toiminnan periaatetta, se on melko yksinkertainen. Alkuperäinen captcha siirtyy kuvan esikäsittelyjärjestelmään, joka puhdistaa captchan kaikista kohinoista ja vääristymistä ja välittää tuloksena olevan kuvan liukuhihnan kautta OCR-järjestelmään, joka yrittää tunnistaa siinä olevan tekstin. TesserCapilla on interaktiivinen graafinen käyttöliittymä ja seuraavat ominaisuudet:
  1. Siinä on yleinen kuvan esikäsittelyjärjestelmä, joka voidaan konfiguroida jokaiselle yksittäiselle captchalle.
  2. Sisältää Tesseract-tunnistusmoottorin, joka poimii tekstiä valmiiksi jäsennellystä ja valmisteltavasta CAPTCHA-kuvasta.
  3. Tukee erilaisten koodausten käyttöä tunnistusjärjestelmässä.
Mielestäni yleinen merkitys on selvä, joten ehdotan, että katsotaan, miltä se näyttää. Apuohjelman monipuolisuus ei voinut muuta kuin johtaa sen käyttöliittymän monimutkaisuuteen, joten ohjelmaikkuna voi joutua pieneen stuporiin. Joten, ennen kuin siirryt suoraan captchojen tunnistamiseen, ehdotan, että käsittelen sen käyttöliittymää ja luontaisia ​​toimintoja.
Kuvan esikäsittely ja poiminta
captcha-teksti

Noin

Emme voineet olla sanomatta ainakin pari sanaa upean TesserCap-apuohjelman tekijästä. Hänen nimensä on Gursev Singh Kalra. Hän on pääkonsultti Foundstone Professional Servicesille, McAfeen osastolle. Gursev on puhunut sellaisissa konferensseissa kuin ToorCon, NullCon ja ClubHack. Hän on TesserCap- ja SSLSmart-työkalujen kirjoittaja. Lisäksi hän kehitti useita työkaluja yrityksen sisäisiin tarpeisiin. Suosikkiohjelmointikielet ovat Ruby, Ruby on Rails ja C#. Hänen Foundstone® Professional Services -divisioona tarjoaa organisaatioille asiantuntijapalveluita ja koulutusta varmistaakseen, että niiden omaisuus on aina ja tehokkaasti suojattu vakavimmilta uhilta. Asiantuntijapalveluiden tiimi koostuu tunnustetuista tietoturvaasiantuntijoista ja -kehittäjistä, joilla on laaja kokemus kansainvälisten yritysten ja valtionhallinnon kanssa työskentelystä.

Käyttöliittymä. Päävälilehti

Ohjelman käynnistämisen jälkeen näemme ikkunan, jossa on kolme välilehteä: Main, Options, Image Preprocessing. Päävälilehti sisältää säätimiä, joita käytetään CAPTCHA-kuvatestin käynnistämiseen ja pysäyttämiseen, testitilastojen luomiseen (kuinka monta on oikein ja kuinka monta ei), navigointiin ja kuvan valitsemiseen esikäsittelyä varten. URL-kentän (ohjausobjekti 1) tulee sisältää tarkka URL-osoite, jota verkkosovellus käyttää captchojen noutamiseen. URL-osoite saadaan seuraavasti: napsauta CAPTCHA-kuvan oikeaa puolta, kopioi tai tarkastele sivun koodia ja poimi URL-osoite kuvatunnisteen ..website/common/rateit/captcha.asp? src-attribuutista. Osoitepalkin vieressä on elementti, joka määrittää testausta varten ladattavien captchojen määrän. Koska sovellus voi näyttää vain 12 kuvaa kerrallaan, se tarjoaa ohjaimia ladattujen captchojen selaamiseen. Näin ollen voimme laajamittaisen testauksen aikana selata ladattuja captchoja ja tarkastella niiden tunnistamisen tuloksia. Start- ja Stop-painikkeet käynnistävät ja lopettavat testauksen, vastaavasti. Testauksen jälkeen sinun on arvioitava kuvantunnistuksen tulokset merkitsemällä jokainen niistä oikeiksi tai virheellisiksi. No, viimeinen, tärkein toiminto on siirtää mikä tahansa kuva esikäsittelyjärjestelmään, jossa asetetaan suodatin, joka poistaa kuvasta kohinaa ja vääristymiä. Jos haluat siirtää kuvan esikäsittelyjärjestelmään, napsauta hiiren oikealla painikkeella haluttua kuvaa ja valitse pikavalikosta Lähetä kuvan esikäsittelyyn.

Käyttöliittymä. Asetukset-välilehti

Asetukset-välilehti sisältää erilaisia ​​säätimiä TesserCapin määrittämiseen. Täällä voit valita OCR-järjestelmän, määrittää verkkovälityspalvelimen asetukset, ottaa käyttöön uudelleenohjauksen ja kuvan esikäsittelyn, lisätä mukautettuja HTTP-otsikoita ja määrittää tunnistusjärjestelmän merkkialueen: numerot, pienet kirjaimet, isot kirjaimet, erikoismerkit. Nyt jokaisesta vaihtoehdosta tarkemmin. Ensinnäkin voit valita OCR-järjestelmän. Oletuksena vain yksi on saatavilla - Tesseract-ORC, joten sinun ei tarvitse vaivautua valinnan kanssa täällä. Toinen erittäin mielenkiintoinen ohjelman ominaisuus on merkkialueen valinta. Otetaan esimerkiksi verkkosivuston captcha - näet, että se ei sisällä yhtä kirjainta, vaan koostuu vain numeroista. Joten miksi tarvitsemme ylimääräisiä merkkejä, jotka vain lisäävät virheellisen tunnistuksen todennäköisyyttä? Mutta entä jos valitset isot kirjaimet? Tunnistaako ohjelma minkä tahansa kielen isoista kirjaimista koostuvan captchan? Ei, hän ei voi. Ohjelma ottaa luettelon tunnistamiseen käytetyistä symboleista \Program Files\Foundstone Free Tools\TesserCap 1.0\tessdata\configs-kansiossa olevista asetustiedostoista. Selitän esimerkin avulla: jos valitsimme Numerics- ja Lower Case -vaihtoehdot, niin ohjelma viittaa pienempinumeroiseen tiedostoon alkaen parametrilla tessedit hiiltyä sallittujen luettelo. Sitä seuraa luettelo merkkejä, joita käytetään ratkaisemaan captcha. Oletusarvoisesti tiedostot sisältävät vain latinalaisten aakkosten kirjaimia, joten kyrilliset aakkoset tunnistaaksesi sinun on korvattava tai täydennettävä merkkiluetteloa. Nyt vähän siitä, mitä varten Http-pyyntöotsikot -kenttä on tarkoitettu. Esimerkiksi jotkut sivustot edellyttävät kirjautumista nähdäksesi captcha. Jotta TesserCap voi käyttää captchaa, ohjelman on välitettävä HTTP-pyynnössä otsikot, kuten Accept, Cookie ja Referrer jne. Käyttämällä verkkovälityspalvelinta (Fiddler, Burp, Charles, WebScarab, Paros jne. ), voit siepata lähetettävät pyyntöotsikot ja kirjoittaa ne Http-pyyntöotsikot -syöttökenttään. Toinen vaihtoehto, joka on varmasti hyödyllinen, on Follow Redirects. Asia on siinä, että TesserCap ei seuraa uudelleenohjauksia oletuksena. Jos testi-URL-osoitteen pitäisi seurata uudelleenohjausta kuvan saamiseksi, sinun on valittava tämä vaihtoehto. No, viimeinen vaihtoehto jää, kuvan esikäsittelymekanismin käyttöönotto / poistaminen käytöstä, jota harkitsemme edelleen. Oletusarvon mukaan kuvan esikäsittely on poistettu käytöstä. Käyttäjät määrittävät ensin kuvan esikäsittelysuodattimet testattavien CAPTCHA-kuvien mukaan ja aktivoivat sitten tämän moduulin. Kaikki CAPTCHA-kuvat, jotka ladataan Ota kuvan esikäsittely -asetuksen käyttöönoton jälkeen, esikäsitellään ja vasta sitten siirretään Tesseract OCR -järjestelmään tekstin poimimista varten.

Käyttöliittymä. Kuvan esikäsittely-välilehti

No, pääsimme mielenkiintoisimpaan välilehteen. Juuri täällä suodattimet on määritetty poistamaan erilaisia ​​​​kohinaa ja epätarkkuutta captchoista, jotka yrittävät monimutkaistaa tunnistusjärjestelmän tehtävää mahdollisimman paljon. Yleissuodattimen asennusprosessi on erittäin yksinkertainen ja koostuu yhdeksästä vaiheesta. Kuvien esikäsittelyn jokaisessa vaiheessa sen muutokset näytetään. Lisäksi sivulla on vahvistuskomponentti, jonka avulla voit arvioida captcha-tunnistuksen oikeellisuutta suodatinta käytettäessä. Tarkastellaan jokaista vaihetta yksityiskohtaisesti. Vaihe 1. Värin käännös Tässä vaiheessa CAPTCHA-kuvien pikselivärit käännetään. Alla oleva koodi näyttää, kuinka tämä tapahtuu: for(jokainen CAPTCHA:n pikseli) ( if (invertRed on tosi) uusi punainen = 255 - nykyinen punainen if (invertBlue on tosi) uusi sininen = 255 - nykyinen sininen jos (invertGreen on tosi ) uusi vihreä = 255 - nykyinen vihreä ) Yhden tai useamman värin kääntäminen avaa usein uusia mahdollisuuksia testattavan CAPTCHA-kuvan validointiin. Vaihe 2. Värinmuutos Tässä vaiheessa voit muuttaa kaikkien kuvan pikselien värikomponentteja. Jokainen numeerinen kenttä voi sisältää 257 (-1 - 255) mahdollista arvoa. Kunkin pikselin RGB-komponenteille suoritetaan seuraavat toiminnot kentän arvosta riippuen:
  1. Jos arvo on -1, vastaava värikomponentti ei muutu.
  2. Jos arvo ei ole yhtä suuri kuin -1, kaikki löydetyt määritetyn värin komponentit (punainen, vihreä tai sininen) muutetaan kenttiin syötetyn arvon mukaan. Arvo 0 poistaa komponentin, arvo 255 asettaa sen maksimiintensiteetin ja niin edelleen.
Vaihe 3: Harmaasävy (harmaasävy) Kolmannessa vaiheessa kaikki kuvat muunnetaan harmaasävykuviksi. Tämä on ainoa vaadittu kuvan muunnosvaihe, jota et voi ohittaa. Valitusta painikkeesta riippuen suoritetaan yksi seuraavista toiminnoista, jotka liittyvät kunkin pikselin värikomponenttiin:
  1. Keskiarvo -> (punainen + vihreä + sininen)/3.
  2. Ihminen -> (0,21 * punainen + 0,71 * vihreä + 0,07 * sininen).
  3. Vähimmäis- ja enimmäisvärikomponenttien keskiarvo -> (minimi (punainen + vihreä + sininen) + maksimi (punainen + vihreä + sininen))/2.
  4. Minimi -> Minimi (punainen + vihreä + sininen).
  5. Maksimi -> Maksimi (punainen + vihreä + sininen).
Riippuen CAPTCHA-värikomponentin intensiteetistä ja jakautumisesta, mikä tahansa näistä suodattimista voi parantaa poimittua kuvaa jatkokäsittelyä varten.
Vaihe 4: Tasoitus ja teroitus Tekstin poistamisen CAPTCHA-kuvista vaikeuttamiseksi niihin lisätään kohinaa yhden tai useamman pikselin pisteinä, vieraina viivoina ja tilavääristyminä. Tasoitettaessa kuvaa satunnainen kohina lisääntyy, minkä poistamiseksi käytetään Bucket- tai Cutoff-suodattimia. Määritä Numerohyväksynnät-kentässä, kuinka monta kertaa haluat käyttää vastaavaa kuvamaskia, ennen kuin siirryt seuraavaan vaiheeseen. Katsotaanpa suodatinkomponentteja tasoitusta ja teroitusta varten. Saatavilla on kahden tyyppisiä kuvamaskeja:
  1. kiinteät naamarit. Oletuksena TesserCapissa on kuusi suosituinta kuvamaskia. Nämä maskit voivat tasoittaa tai terävöittää kuvaa (Laplace-muunnos). Muutokset näkyvät heti maskin valitsemisen jälkeen vastaavilla painikkeilla.
  2. Mukautetut kuvamaskit. Käyttäjä voi myös määrittää mukautettuja kuvankäsittelymaskeja syöttämällä arvoja numerokenttiin ja napsauttamalla Tallenna maski -painiketta. jos kertoimien summa näissä laatikoissa on pienempi kuin nolla, syntyy virhe eikä maskia käytetä. Jos valitset kiinteän maskin, sinun ei tarvitse käyttää Tallenna maski -painiketta.
Vaihe 5. Syötä harmaasävy Tässä kuvankäsittelyn vaiheessa sen pikselit voidaan värjätä useilla harmaan sävyillä. Tämä suodatin näyttää harmaasävyjakauman 20 segmentissä/alueella. Harmaasävypikseleiden prosenttiosuus välillä 0 - 12 on ryhmässä 0, harmaasävypikseleiden prosenttiosuus välillä 13 - 25 on sävyssä 1 ja niin edelleen. Käyttäjä voi valita yhden seuraavista kullekin sävyjä vastaavalle arvoalueelle harmaa:
  1. Jätä ennalleen (Jätä sellaisenaan).
  2. Vaihda valkoiseen (valkoiseen).
  3. Vaihda mustaan ​​(musta).
Näillä asetuksilla voit hallita erilaisia ​​harmaasävyalueita sekä vähentää/poistaa kohinaa muuttamalla harmaasävyt valkoiseksi tai mustaksi. Vaihe 6. Leikkauksen säätö (raja) Tämä suodatin piirtää harmaan tason arvon esiintymistiheyden funktiona ja kehottaa sinua valitsemaan rajan. Lovisuodattimen toiminta näkyy alla pseudokoodina: if (pikselin harmaasävyarvo<= Cutoff) pixel grayscale value = (0 OR 255) ->riippuen valitusta vaihtoehdosta<= или =>: Aseta jokainen pikseli arvolla<=/=>Kynnys arvoon 0. Jäljellä 255) Kaavio näyttää yksityiskohtaisen CAPTCHA-pikseleiden jakautumisen värin mukaan ja auttaa poistamaan kohinaa leikkaamalla harmaasävyarvoja. Vaihe 7: Leikkaaminen Anti-aliasing-, clipping-, bucket- ja muiden suodattimien käytön jälkeen CAPTCHA-kuvissa voi silti olla kohinaa yhden tai useamman pikselin pisteistä, vieraista viivoista ja tilavääristymistä. Trimmaussuodatin toimii näin: jos tietyllä harmaan sävyllä värjättyjen vierekkäisten pikselien määrä on pienempi kuin numerokentän arvo, rajaussuodatin antaa niille arvon 0 (musta) tai 255 (valkoinen) käyttäjän valinta. CAPTCHA analysoidaan sekä vaaka- että pystysuunnassa. Vaihe 8: Reunuksen leveyden muuttaminen Apuohjelman kirjoittajan mukaan TesserCapin alkuperäisen tutkimuksen ja kehityksen aikana hän toistuvasti totesi, että kun CAPTCHA-kuvissa on paksu reunus ja sen väri eroaa CAPTCHA-päätaustasta, jotkin OCR-järjestelmät eivät pysty tunnistamaan tekstiä. Tämä suodatin on tarkoitettu rajaviivojen käsittelyyn ja vaihtamiseen. Numeerisessa kentässä määritetyn leveyden rajaviivat väritetään mustaksi tai valkoiseksi käyttäjän valinnan mukaan. Vaihe 9: Harmaa inversio Tämä suodatin kulkee jokaisen pikselin läpi ja korvaa sen harmaan arvon uudella, kuten alla olevassa pseudokoodissa näkyy. Harmaa inversio suoritetaan kuvan sovittamiseksi OCR-järjestelmän väriasetuksiin. (jokaiselle CAPTCHA:n pikselille) uusi harmaasävyarvo = 255 – nykyinen harmaasävyarvo Vaihe 10: Captcha-tunnistustesti Tämän vaiheen tarkoituksena on välittää esikäsitelty CAPTCHA-kuva OCR-järjestelmään tunnistamista varten. Ratkaise-painike ottaa kuvan harmaan inversiosuodattimen jälkeen, lähettää sen OCR-järjestelmään tekstin poimimiseksi ja näyttää palautetun tekstin graafisessa käyttöliittymässä. Jos tunnistettu teksti vastaa captcha-tekstiä, olemme asettaneet esikäsittelyn suodattimen oikein. Nyt voit siirtyä Asetukset-välilehteen ja ottaa käyttöön esikäsittelyvaihtoehdon (Ota kuvan esikäsittely käyttöön) käsitelläksesi kaikki myöhemmät lähetetyt captchat.

Captchojen tunnistaminen

No, ehkä olemme harkinneet kaikkia tämän apuohjelman vaihtoehtoja, ja nyt olisi mukava testata captchaa vahvuuden suhteen.
Captcha-sivuston analyysin tulos alustavalla
kuvankäsittely. Tulosten perusteella suodatin
ei ollut mahdollista noutaa. Joten käynnistämme apuohjelman ja siirrymme lehden verkkosivuille. Näemme luettelon tuoreista uutisista, siirry ensimmäiseen vastaantulevaan kohtaan ja vieritä kohtaan, johon voit jättää kommenttisi. Joo, kommentin lisääminen ei ole niin helppoa (tietenkin, muuten kaikki olisi jo kauan sitten roskapostitettu) - sinun on syötettävä captcha. No, katsotaan voidaanko se automatisoida. Kopioi kuvan URL-osoite ja liitä se TesserCapin osoitepalkkiin. Ilmoita, että sinun on ladattava 12 captchaa, ja napsauta Käynnistä. Ohjelma latasi kuuliaisesti 12 kuvaa ja yritti tunnistaa ne. Valitettavasti kaikkia captchoja ei joko tunnistettu, kuten niiden alla oleva teksti -Failed- osoittaa, tai ne tunnistettiin väärin. Yleisesti ottaen se ei ole yllättävää, koska ylimääräistä melua ja vääristymiä ei ole poistettu. Näin teemme nyt. Napsauta hiiren kakkospainikkeella yhtä 12 ladatusta kuvasta ja lähetä se Send To Image Preprocessoriin. Tutkittuamme huolellisesti kaikki 12 captchaa, huomaamme, että ne sisältävät vain numeroita, joten siirrymme Asetukset-välilehteen ja osoitamme, että vain numerot tulisi tunnistaa (merkistö = Numerics). Nyt voit siirtyä Kuvan esikäsittely -välilehdelle asettaaksesi suodattimia. Minun on sanottava heti, että pelattuani kolmella ensimmäisellä suodattimella ("Color Inversion", "Color Change", "Grey Gradation") en nähnyt mitään positiivista vaikutusta, joten jätin kaiken sinne oletuksena. Valitsin Smooth Mask 2:n ja asetin kulkujen lukumääräksi yhden. Ohitin Grayscale buckets -suodattimen ja siirryin suoraan leikkausasetuksiin. Valitsin arvon 154 ja osoitin, että pienemmät pikselit tulee asettaa arvoon 0 ja suuremmat 255. Päästäkseni eroon jäljellä olevista pikseleistä otin leikkaus päälle ja muutin reunuksen leveydeksi 10. Ei ollut mitään järkeä sisällyttää viimeistä suodatinta, joten napsautin heti Ratkaise. Captchassa minulla oli numero 714945, mutta ohjelma tunnisti sen numeroksi 711435. Kuten näette, tämä on täysin väärin. Lopulta, vaikka kuinka kovasti yritin, en onnistunut tunnistamaan captchaa normaalisti. Jouduin kokeilemaan pastebin.com:ia, jonka onnistuin tunnistamaan ilman ongelmia. Mutta jos olet ahkerampi ja kärsivällisempi ja onnistut saamaan captchat oikein tunnistettua sivustolta, siirry heti Asetukset-välilehteen ja ota kuvan esikäsittely käyttöön (Ota kuvan esikäsittely käyttöön). Siirry sitten Main-kohtaan ja napsauta Käynnistä-painiketta, lataa uusi osa captchoista, jotka nyt suodattimesi esikäsittelee. Kun ohjelma on päättynyt, merkitse oikein/väärin tunnistetut captchat (Merkitse oikeaksi/Merkitse virheellisiksi -painikkeet). Tästä eteenpäin voit tarkastella yhteenvetona tunnistustilastoja Näytä tilastot -toiminnolla. Yleensä tämä on eräänlainen raportti tietyn CAPTCHA:n turvallisuudesta. Jos sinulla on kysyttävää jonkin ratkaisun valinnasta, niin TesserCapin avulla on täysin mahdollista suorittaa oma testaus.

CAPTCHA-tarkistustulos suosituilla sivustoilla

Verkkosivusto ja tunnustettujen captchien osuus:
  • Wikipedia > 20-30 %
  • Ebay > 20-30%
  • reddit.com > 20-30 %
  • CNBC > 50 %
  • foodnetwork.com > 80-90 %
  • dailymail.co.uk > 30 %
  • megaupload.com > 80 %
  • pastebin.com > 70-80 %
  • Cavernue.com > 80 %

Johtopäätös

CAPTCHA-kuvat ovat yksi tehokkaimmista mekanismeista suojata verkkosovelluksia automaattiselta lomakkeiden täytöltä. Heikot captchat voivat kuitenkin suojata satunnaisia ​​robotteja vastaan ​​eivätkä vastusta kohdennettuja yrityksiä ratkaista ne. Salausalgoritmien lisäksi CAPTCHA-kuvat, jotka on testattu perusteellisesti ja varmistavat korkean tietoturvatason, ovat paras tapa suojautua. Ohjelman laatijan toimittamien tilastojen perusteella valitsin projekteihini reCaptchan ja suosittelen sitä kaikille ystävilleni - se osoittautui kestävimmäksi testatuista. Joka tapauksessa älä unohda, että verkossa on monia palveluita, jotka tarjoavat puoliautomaattisen CAPTCHA-ratkaisun. Erityisen API:n kautta välität kuvan palveluun, joka hetken kuluttua palauttaa ratkaisun. Todellinen ihminen ratkaisee captchan (esimerkiksi Kiinasta) ja saa siitä melkoisen pennin. Suojaa ei enää ole. 🙂