<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Moioli.net</title>
	<atom:link href="http://www.moioli.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.moioli.net</link>
	<description>Il sito di Silvio Moioli, studente e programmatore</description>
	<lastBuildDate>Fri, 27 Apr 2012 11:08:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>30 Aprile: presentazione su idee e tecnologie Apple</title>
		<link>http://www.moioli.net/misto/30-aprile-presentazione-apple/</link>
		<comments>http://www.moioli.net/misto/30-aprile-presentazione-apple/#comments</comments>
		<pubDate>Fri, 27 Apr 2012 11:08:27 +0000</pubDate>
		<dc:creator>Silvio Moioli</dc:creator>
				<category><![CDATA[Il misto]]></category>

		<guid isPermaLink="false">http://www.moioli.net/?p=452</guid>
		<description><![CDATA[Lunedì prossimo 30 Aprile tengo una presentazione presso il gruppo CodeLovers sulle idee &#8220;fuori dal coro&#8221; dietro alcune delle tecnologie Apple. Sarà un incontro molto tecnico, rivolto essenzialmente ai programmatori (della Mela e non). L&#8217;incontro è aperto a tutti e gratuito, alle 21:00 allo Spazio Polaresco di Longuelo. Per maggiori informazioni rimando al blog dei [...]]]></description>
			<content:encoded><![CDATA[<p>Lunedì prossimo 30 Aprile tengo una presentazione presso il gruppo <a href="http://codelovers.it/">CodeLovers</a> sulle <strong>idee &#8220;fuori dal coro&#8221;</strong> dietro alcune delle tecnologie Apple. Sarà un incontro molto tecnico, rivolto essenzialmente ai programmatori (della Mela e non).</p>
<p>L&#8217;incontro è aperto a tutti e gratuito, alle 21:00 allo <a href="http://www.agorapolaresco.com/">Spazio Polaresco di Longuelo</a>.</p>
<p>Per maggiori informazioni rimando al <a href="http://codelovers.it/2012/04/incontro-del-30-aprile-2012-code-different-idee-e-tecniche-dal-software-apple/">blog dei CodeLovers</a>.</p>
<p>A presto!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.moioli.net/misto/30-aprile-presentazione-apple/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Aggirare un CAPTCHA per divertimento e divulgazione – Parte 5</title>
		<link>http://www.moioli.net/progetti/aggirare-captcha-5/</link>
		<comments>http://www.moioli.net/progetti/aggirare-captcha-5/#comments</comments>
		<pubDate>Wed, 09 Feb 2011 06:47:09 +0000</pubDate>
		<dc:creator>Silvio Moioli</dc:creator>
				<category><![CDATA[Progetti]]></category>

		<guid isPermaLink="false">http://www.moioli.net/?p=432</guid>
		<description><![CDATA[Questo è il quinto articolo della serie sui CAPTCHA – meglio tornare al primo se non l’hai già letto. Riassunto delle puntate precedenti Ecco la ricetta per &#8220;leggere&#8221; il CAPTCHA di Vodafone! rimuovere il rumore dal fondo dell&#8217;immagine, per sottrazione con un&#8217;immagine di solo rumore ottenuta comparando molti CAPTCHA; applicare un filtro a soglia per [...]]]></description>
			<content:encoded><![CDATA[<p>Questo è il quinto articolo della serie sui CAPTCHA – meglio tornare al <a href="../progetti/progetti/progetti/aggirare-captcha-1">primo</a> se non l’hai già letto.</p>
<h2>Riassunto delle puntate precedenti</h2>
<p>Ecco la ricetta per &#8220;leggere&#8221; il CAPTCHA di Vodafone!</p>
<ul>
<li><strong>rimuovere il rumore</strong> dal fondo dell&#8217;immagine, per sottrazione con un&#8217;immagine di solo rumore ottenuta comparando molti CAPTCHA;</li>
<li>applicare un <strong>filtro a soglia</strong> per rendere netti i contorni dei caratteri;</li>
<li>opzionalmente, <strong>correggere</strong> le aree bianche o nere troppo piccole e (semi)isolate dal resto;</li>
<li><strong>segmentare</strong> l&#8217;immagine nei vari caratteri, ad esempio con un algoritmo flood fill;</li>
<li><strong>ridimensionare</strong> ogni lettera individuata a 15&#215;15 pixel;</li>
<li>dare in pasto ogni carattere a una <strong>rete neurale</strong> a percettrone propriamente allenata.</li>
</ul>
<p>Ciò detto, quale è l&#8217;accuratezza del sistema?<br />
<span id="more-432"></span></p>
<h2>Risultati</h2>
<p>Ho testato un&#8217;implementazione dell&#8217;algoritmo di cui sopra e i risultati sono stati i seguenti:</p>
<ol>
<li>il CAPTCHA viene decodificato correttamente <strong>al primo tentativo in più del 90% dei casi</strong> su un campione di circa 100 immagini;</li>
<li>come spiegato nella <a href="http://www.moioli.net/progetti/aggirare-captcha-4/">parte 4</a> questo dato si riferisce a prove fatte su un campione di immagini diverse da quelle usate per l&#8217;allenamento della rete neurale (<a href="http://en.wikipedia.org/wiki/Cross-validation_%28statistics%29">cross-validation</a>), quindi <strong>la percentuale del 90% è rappresentativa dell&#8217;accuratezza reale</strong>;</li>
<li>ovviamente, se la decodifica non funziona al primo colpo <strong>si può ritentare</strong>. Visto che basta un solo tentativo a buon fine per rompere la protezione fornita dal CAPTCHA, la probabilità di successo nella pratica è ancora più alta: con <strong>con 3 tentativi si sbaglia su una sola lettura su mille</strong>, e con 6 tentativi una su un milione!</li>
</ol>
<p>Note statistiche: <em>nella ragionevolissima ipotesi che gli esiti delle letture di CAPTCHA siano <a href="http://en.wikipedia.org/wiki/Independence_%28probability_theory%29">indipendenti</a>, segue che i risultati del punto 1 sono sufficienti per affermare che la percentuale di successo è sopra al 90% con <a href="http://en.wikipedia.org/wiki/Statistical_hypothesis_testing">significatività</a> del 99%. Quanto descritto al punto 3 discende dalla stessa ipotesi, in quanto la probabilità P di successo complessiva è data da</em></p>
<p style="text-align: center;"><em>P = 1-[(1-p)(1-p)(1-p)...]</em> n volte</p>
<p style="text-align: left;"><em><br />
dove p è la probabilità di successo del singolo tentativo ed n il numero di tentativi.</em></p>
<h2>Tecniche implementative</h2>
<p><em>Nota Bene: i prossimi paragrafi sono dedicati ai programmatori ed alle persone con esperienza in ambito informatico &#8211; è normale che non risulti di facile comprensione agli altri lettori.</em></p>
<p>Come si possono tradurre in pratica le idee esposte fino a questo punto? Io ho usato questi strumenti:</p>
<ul>
<li>il linguaggio di programmazione <a href="http://www.scala-lang.org/">Scala</a>;</li>
<li>l&#8217;ambiente di sviluppo <a href="http://eclipse.org/">Eclipse</a> con il plugin <a href="http://www.scala-ide.org/">Scala-IDE</a>;</li>
<li>il motore di reti neurali <a href="http://www.heatonresearch.com/encog">Encog</a>;</li>
<li><a href="http://www.gimp.org/">GIMP</a> e (ugh!) <a href="http://www.libreoffice.org/">LibreOffice</a> <a href="http://www.libreoffice.org/features/calc/">Calc</a> per alcune prove e prototipi.</li>
</ul>
<h3>Scala</h3>
<p>Il linguaggio Scala è stato scelto per due ragioni:</p>
<ol>
<li>è <a href="http://www.scala-lang.org/node/104">molto, molto compatibile con Java</a>, permettendo in particolare di utilizzare librerie e classi Java esistenti. Naturalmente questo fa molto comodo per usare Encog, che è scritto proprio in Java!</li>
<li>rispetto a Java ha alcune caratteristiche interessanti, che se ben usate portano produrre a codice, a mio parere, molto <strong>più compatto e leggibile</strong>.</li>
</ol>
<p>Ad esempio, è possibile definire classi i cui <strong>oggetti si usano come i vettori</strong>. Sembra inutile? Si pensi a come semplifica la vita poter scrivere codice come questo in una libreria che fa trattamento di immagini:</p>
<pre>if (image(2, 3) == BLACK)){
    image(2, 3) = WHITE
}</pre>
<p>Sfido qualunque programmatore a <em>non</em> capire il significato! E&#8217; interessante anche notare che, per raggiungere questo risultato, non c&#8217;è bisogno di sintassi astruse, basta infatti definire due metodi particolari, <em>apply</em> ed <em>update</em>, come nell&#8217;esempio che segue:</p>
<pre>class Image(...) {
    def apply(x:Int, y:Int):Int = {
        // ritorna in un intero il colore alla posizione (x,y)
    }
    def update(x:Int, y:Int, color:Int):Unit = {
        // cambia in color il colore del pixel alla posizione (x,y)
    }
}</pre>
<p>Ancora una volta, a mio parere, estremamente leggibile. Ho usato codice di questo tipo per costruire un <a href="http://en.wikipedia.org/wiki/Wrapper_pattern">wrapper</a> attorno a <a href="http://download.oracle.com/javase/6/docs/api/java/awt/Image.html">java.awt.Image</a>, la classe Java per la gestione delle immagini, ottenendo una classe allo stesso tempo potente e semplice, in poche righe di codice.</p>
<p>Un&#8217;altra chicca simile è la possibilità di definire <strong>metodi con nomi strani</strong>, ad esempio <em>+</em>, <em>-</em> oppure <em>|</em>, ridefinendo in pratica gli operatori del linguaggio per classi specifiche. Ho usato questa particolarità per <strong>implementare i filtri delle immagini con una sintassi simile a quella delle <a href="http://en.wikipedia.org/wiki/Unix_shell">shell Unix</a></strong>.</p>
<p>Credo che sia immediato capire il senso di questo codice:</p>
<pre>image = read(new FileInputStream(file))
filteredImage = image | new DesaturateFilter() | new RemovePatternFilter(new FileInputStream("data/pattern.png")) | new ThresholdFilter(170) | ...</pre>
<p>Per poter scrivere la riga di cui sopra basta implementare il metodo <em>|</em> di Image e definire una &#8220;classe astratta&#8221; che rappresenti un filtro:</p>
<pre>class Image(...) {
  def |(filter:ImageFilter):Image = {
    filter.filter(this)
  }
}</pre>
<pre>trait ImageFilter {
  def filter(image:Image):Image
}</pre>
<p>E&#8217; da notare come in Scala è possibile usare semplici <strong>spazi al posto dell&#8217;operatore &#8220;.&#8221;</strong> tipico di Java, e si possano anche <strong>omettere le parentesi</strong> ove non ambiguo, e questo permette di scrivere</p>
<pre>filteredImage = image | filter</pre>
<p>al posto di</p>
<pre>filteredImage = image.|(filter)</pre>
<p>A mio parere, un vero colpo di genio! Scegliendo nomi appropriati per i metodi, infatti, questa caratteristica da sola porta a scrivere codice molto più simile al linguaggio naturale, quindi facile da comprendere, rispetto alle controparti Java. Altri esempi illuminanti:</p>
<pre>count = collection size
heightInPixels = image height
calculator compute inputs</pre>
<p>In questi esempi si sarà notato che sono <strong>omessi anche i terminatori di riga</strong> (&#8220;;&#8221; in Java). Questo è l&#8217;ennesimo piccolo beneficio di Scala: i terminatori si possono omettere ovunque non sia ambiguo. Perchè consumare tasti inutilmente?</p>
<p>Un&#8217;altro aspetto che mi piace molto di Scala è che nonostante sia un linguaggio <a href="http://en.wikipedia.org/wiki/Type_system#Static_typing">staticamente tipato</a> (come Java e a differenza di Groovy, Ruby o Python) <strong>non costringe ad usare sintassi prolissa</strong> per specificare i tipi degli oggetti ovunque. Mi spiego: supponendo di avere un metodo che accetta un oggetto Car e poi lo usa, in Java occorre scrivere qualcosa del tipo:</p>
<pre><strong>Brick</strong> demolish(Car car){
  <strong>Car</strong> myCar = car;
  return myCar.demolish();
}</pre>
<p>In questo esempio, i tipi in grassetto non sono strettamente necessari: è evidente che myCar debba essere di tipo Car (poichè car è di tipo Car), analogamente dal momento che il metodo ritorna sempre e solo il risultato di Car.demolish() è ovvio che il risultato sia un&#8217;istanza di Brick. In Scala, dal momento che tutto questo è superfluo, <strong>può essere omesso</strong>:</p>
<pre>def demolish(car:Car){
  val myCar = car;
  return myCar demolish
}</pre>
<p><strong>Il compilatore controlla tutti i tipi</strong> e completa le definizioni ovunque possibile, il che risparmia un bel po&#8217; di digitazioni inutili (e facili da sbagliare). Ovviamente in caso di ambiguità ci sarà una segnalazione di errore, solo in quel caso sarà necessario specificare i tipi come in Java. L&#8217;aspetto interessante è che si arriva a scritture concise simili a quelle dei linguaggi tipati dinamicamente <strong>senza rinunciare agli utili controlli di coerenza</strong> del compilatore.</p>
<h3>Encog</h3>
<p>L&#8217;uso di Encog di per sè non è particolarmente bizzarro, nel senso che segue esattamente l&#8217;<a href="http://www.heatonresearch.com/javadoc/encog-2.2/index.html">interfaccia Java</a> documentata sul sito ufficiale. Ad esempio, questo è il codice per caricare una rete neurale allenata con l&#8217;Encog Workbench:</p>
<pre>network = new BasicNetworkPersistor().load(new ReadXML(new FileInputStream("model.eg"))).asInstanceOf[BasicNetwork]</pre>
<p>L&#8217;unica cosa degna di nota è l&#8217;ultima parte, asInstanceOf[BasicNetwork], che è l&#8217;equivalente di un cast in Java richiesto dal fatto che BasicNetworkPersistor.load() ritorna un <a href="http://www.heatonresearch.com/javadoc/encog-2.2/org/encog/persist/EncogPersistedObject.html">EncogPersistedObject</a> che è una sopraclasse di <a href="http://www.heatonresearch.com/javadoc/encog-2.2/org/encog/neural/networks/BasicNetwork.html">BasicNetwork</a>. <strong>L&#8217;uso della rete vera e propria è addirittura banale</strong>:</p>
<pre>inputs = new BasicNeuralData(rawInputs toArray)
outputs = network compute inputs</pre>
<p>dove rawInputs non è che una List[Double].</p>
<h2>Ecco il codice!</h2>
<p>Viste le tecniche principali ed alcune curiosità sulla stesura del codice non resta, per chi ha ancora voglia di studiare, che prendere in mano il codice sorgente del programma!</p>
<p style="text-align: center;"><strong>Scarica il <a href="http://www.moioli.net/wp-content/uploads/2011/02/Captcha.zip">Progetto Eclipse per la decodifica dei CAPTCHA</a> (zip, 1MB)</strong></p>
<p>Il progetto contiene:</p>
<ul>
<li>la cartella <em>training</em> che contiene un sufficiente numero di CAPTCHA scaricati e decodificati manualmente per l&#8217;allenamento;</li>
<li>il package <em>net.moioli.moiosms.imagefilters</em> contenente le implementazioni in Scala dei filtri grafici descritti <a href="../progetti/aggirare-captcha-2/">nelle</a> <a href="../progetti/aggirare-captcha-3/">puntate</a> <a href="../progetti/aggirare-captcha-4/">precedenti</a>;</li>
<li>il package <em>net.moioli.moiosms.training</em> contenente:
<ul>
<li>il programma <em>TrainingImagePreparer</em> che prende i CAPTCHA nella cartella <em>training</em>, applica i filtri grafici e li scompone in singole lettere divise per allenamento e validazione;</li>
<li>il programma <em>TrainingCsvGenerator</em> che, prendendo le lettere generate dal programma precedente, crea file <a href="http://en.wikipedia.org/wiki/Comma-separated_values">CSV</a> che possono essere importati in Encog Workbench;</li>
</ul>
</li>
<li><em>data/letters.eg</em>, un esempio di rete Encog già allenata in questo modo e soprattutto</li>
<li><em>OCRTester</em>, <strong>un programma che legge effettivamente i CAPTCHA come descritto in questi articoli!</strong></li>
</ul>
<p>Il modo più semplice per provare tutto questo è:</p>
<ol>
<li>installare l&#8217;ultima versione di <a href="http://eclipse.org/">Eclipse</a> per Java;</li>
<li>installare il plugin <a href="http://www.scala-ide.org/">Scala-IDE</a>, che contiene il compilatore Scala;</li>
<li>decomprimere lo zip;</li>
<li>importare il progetto (menù <em>File</em>, <em>Import&#8230;</em>, <em>General</em>, <em>Existing Project into Workspace</em>);</li>
<li>lanciare uno dei programmi con la voce <em>Run as&#8230; Scala Application</em> dal menù che compare cliccando con il tasto destro sul file corrispondente.</li>
</ol>
<p>Dovreste ritrovarvi con una schermata simile alla seguente:</p>
<p><a href="http://www.moioli.net/wp-content/uploads/2011/02/shot.png"><img class="aligncenter size-medium wp-image-441" title="Schermata di Eclipse con il progetto Captcha" src="http://www.moioli.net/wp-content/uploads/2011/02/shot-300x178.png" alt="" width="300" height="178" /></a></p>
<h2>Conclusioni</h2>
<p>Con questo articolo chiudo la serie sui CAPTCHA iniziata qualche mese fa. So che non è molto rispetto alla fine del progetto MoioSMS ma spero possa essere un adeguato punto di ripartenza per chi volesse ricominciarlo o semplicemente ampliare le proprie conoscenze. Scrivete pure nei commenti opinioni e domande!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.moioli.net/progetti/aggirare-captcha-5/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Aggirare un CAPTCHA per divertimento e divulgazione &#8211; Parte 4</title>
		<link>http://www.moioli.net/progetti/aggirare-captcha-4/</link>
		<comments>http://www.moioli.net/progetti/aggirare-captcha-4/#comments</comments>
		<pubDate>Thu, 30 Sep 2010 20:09:23 +0000</pubDate>
		<dc:creator>Silvio Moioli</dc:creator>
				<category><![CDATA[Progetti]]></category>

		<guid isPermaLink="false">http://www.moioli.net/?p=391</guid>
		<description><![CDATA[Questo è il quarto articolo della serie sui CAPTCHA – meglio tornare al primo se non l’hai già letto. Normalizzazione delle dimensioni delle lettere Come si nota dall&#8217;immagine seguente, nel CAPTCHA di Vodafone solitamente le lettere  sono di dimensioni diverse. Questo è chiaramente un meccanismo per rendere più difficile l&#8217;individuazione delle lettere &#8211; peccato che [...]]]></description>
			<content:encoded><![CDATA[<p>Questo è il quarto articolo della serie sui CAPTCHA – meglio tornare al <a href="../progetti/progetti/aggirare-captcha-1">primo</a> se non l’hai già letto.</p>
<h3>Normalizzazione delle dimensioni delle lettere</h3>
<p>Come si nota dall&#8217;immagine seguente, nel CAPTCHA di Vodafone solitamente <strong>le lettere  sono di dimensioni diverse</strong>.</p>
<p style="text-align: center;"><a href="http://www.moioli.net/wp-content/uploads/2010/09/9NUWH.png"><img class="aligncenter size-full wp-image-392" title="Un CAPTCHA preso dal sito Vodafone, così com'è." src="http://www.moioli.net/wp-content/uploads/2010/09/9NUWH.png" alt="Un CAPTCHA preso dal sito Vodafone, così com'è." width="300" height="50" /></a></p>
<p>Questo è chiaramente un meccanismo per rendere più difficile l&#8217;individuazione delle lettere &#8211; peccato che è anche particolarmente <strong>semplice da aggirare</strong>. Vediamo come.</p>
<p><span id="more-391"></span></p>
<p>Il primo passo è di calcolare il <strong>rettangolo minimo</strong> che contiene ogni lettera. Il procedimento è semplicissimo: basta individuare le coordinate minime e massime per ogni colore. Graficamente è possibile rappresentare il procedimento come segue:</p>
<p><a href="http://www.moioli.net/wp-content/uploads/2010/09/rettangolo-minimo.png"><img class="aligncenter size-full wp-image-393" title="rettangolo minimo" src="http://www.moioli.net/wp-content/uploads/2010/09/rettangolo-minimo.png" alt="" width="610" height="50" /></a>A questo punto, senza neanche troppa fatica, normalizzare le immagini delle singole lettere significa semplicemente ridimensionarle tutte a una stessa grandezza fissata, in questo come 15&#215;15.</p>
<p>Fatto il ridimensionamento, voilà, <strong>le distorsioni delle lettere sono praticamente sparite</strong>!</p>
<p><a href="http://www.moioli.net/wp-content/uploads/2010/09/lettere-ridimensionamento.png"><img class="aligncenter size-full wp-image-394" title="Processo di normalizzazione delle dimensioni delle lettere." src="http://www.moioli.net/wp-content/uploads/2010/09/lettere-ridimensionamento.png" alt="Processo di normalizzazione delle dimensioni delle lettere." width="800" height="270" /></a></p>
<p><em>Il ridimensionamento è una funzione presente in qualunque libreria di manipolazione delle immagini, quindi non entro nemmeno nei dettagli dei possibili algoritmi.</em></p>
<p>Dopo aver rimosso il rumore all&#8217;immagine, segmentato i singoli caratteri ed averli normalizzati, siamo finalmente pronti per il riconoscimento vero e proprio.</p>
<h3>Riconoscimento: prima la teoria&#8230;</h3>
<p>Premessa: mi spiace per il titolo un po&#8217; deprimente, ma proprio non riesco a spiegare questo argomento diversamente! I paragrafi seguenti richiedono un minimo di conoscenze matematiche, in particolare sul concetto di <a href="http://it.wikipedia.org/wiki/Funzione_%28matematica%29" target="_blank">funzione</a>, che è meglio aver compreso prima di gettarsi nella lettura della parte che segue.<em><br />
</em></p>
<p style="text-align: left;">Il problema del riconoscimento si può porre così: possiamo costruire <strong>una funzione matematica f che, dati in input i valori dei pixel che compongono l&#8217;immagine, produca in output la lettera rappresentata</strong>?</p>
<p style="text-align: left;">Dettaglio matematico:<em> in modo un po&#8217; più rigoroso il problema è:</em></p>
<p style="text-align: center;"><em>definire una funzione y=f(x), dove:</em></p>
<p style="text-align: center;"><em>x è un vettore di 225 numeri (corrispondenti a 15&#215;15 pixel) tra 0 (bianco) ed 1 (nero)</em></p>
<p style="text-align: center;"><em>y è un vettore di 34 numeri tra 0 ed 1 (uno per ogni carattere che può comparire nel CAPTCHA) e</em></p>
<p style="text-align: center;"><em>y<sub>i</sub> vale 1 se x rappresenta il carattere i e 0 altrimenti</em></p>
<p style="text-align: center;"><em><br />
</em></p>
<p style="text-align: left;">Se siete arrivati fino a questo punto, dovreste avere una domanda in testa: <strong>come è possibile definire un mostro di funzione come questo?</strong></p>
<p style="text-align: left;">Una possibilità è di spendere qualche mese ragionando su come definire analiticamente la funzione f, cosa non particolarmente comoda, in particolare a causa del gran numero di variabili in ingresso. Una via più conveniente, e decisamente più furba, è usare le <strong>reti neurali</strong>, che possiamo definire molto grossolanamente come &#8220;<strong>funzioni imitatrici</strong>&#8220;.</p>
<p style="text-align: left;">Al di là del nome esotico, <strong>le reti neurali non sono altro che funzioni matematiche</strong>, con la particolarità che <strong>sono in grado di &#8220;imitare&#8221;</strong> (approssimando) altre funzioni. La cosa divertente è che <strong>le funzioni imitate</strong> possono anche essere <strong>ignote</strong>!</p>
<p style="text-align: left;">Nel nostro caso, <strong>possiamo ipotizzare</strong> senza troppa fantasia <strong>che una funzione f esista</strong>; non sapendola scrivere <strong>ci limitiamo ad imitarla con una rete neurale</strong>!</p>
<p style="text-align: left;">Dettaglio matematico:<em> in modo un po&#8217; più preciso, ed in estrema sintesi, una rete neurale è una funzione parametrica che a seconda dei valori assunti dai suoi parametri può approssimare una qualunque altra funzione (non necessariamente nota). Esiste un <a href="http://en.wikipedia.org/wiki/Universal_approximation_theorem" target="_blank">simpatico teorema</a> il quale prova che una particolare classe di reti neurali, le reti a <a href="http://en.wikipedia.org/wiki/Perceptron" target="_blank">percettrone</a> con <a href="http://en.wikipedia.org/wiki/Multilayer_perceptron" target="_blank">strato nascosto</a> singolo, possono approssimare con </em><em>arbitraria precisione </em><em>arbitrarie funzioni, sotto ipotesi molto permissive e certamente verificate qui. Ovviamente, ci concentreremo su questo particolare tipo di rete nel seguito dell&#8217;articolo.<br />
</em></p>
<h3>Incredibile&#8230; Ma funziona!</h3>
<p>Come è possibile che una rete neurale possa approssimare la sfuggente funzione f, che non abbiamo mai visto?</p>
<p>L&#8217;idea è che la rete è in grado di <strong>apprendere da alcuni esempi</strong> che gli vengono forniti.</p>
<p>Si può infatti &#8220;esporre&#8221; un insieme di input ed output preparati a mano ad una rete neurale ed aspettarsi che questa &#8220;impari per esempi&#8221; come funzionare. Una volta <strong>terminato questo allenamento</strong>, la rete dovrebbe essere <strong>in grado di calcolare dei &#8220;buoni output&#8221;</strong> anche a partire da input nuovi.</p>
<p>Sembra incredibile? Eppure <strong>funziona</strong>!</p>
<p>Infatti, non è un caso che attualmente tutti i migliori software <a href="http://en.wikipedia.org/wiki/Optical_character_recognition" target="_blank">OCR</a> facciano esattamente così. Ricordo tra gli altri <a href="http://en.wikipedia.org/wiki/Tesseract_%28software%29" target="_blank">tesseract</a>, il software usato da Google per la scansione dei libri in <a href="http://en.wikipedia.org/wiki/Google_Books" target="_blank">Google Books</a>.</p>
<p style="text-align: left;">
<p>Per l&#8217;allenamento è necessario, innanzitutto, <strong>preparare un bel po&#8217; di caratteri e dividerli per lettera</strong> a mano. In questo modo avremo un certo insieme di coppie input-output da dare in pasto alla rete durante l&#8217;allenamento. Personalmente ci ho messo diverso tempo, il risultato è qualcosa di questo genere:</p>
<p style="text-align: left;"><a href="http://www.moioli.net/wp-content/uploads/2010/09/lettere-catalogate.png"><img class="aligncenter size-full wp-image-398" title="Esempio di lettere catalogate per l'allenamento di una rete neurale" src="http://www.moioli.net/wp-content/uploads/2010/09/lettere-catalogate.png" alt="Esempio di lettere catalogate per l'allenamento di una rete neurale" width="1013" height="609" /></a></p>
<p style="text-align: left;">
<p style="text-align: left;">Poi occorre procurarsi un&#8217;implementazione degli algoritmi delle reti neurali che, in particolare, permetta l&#8217;allenamento. <strong>Esistono ottimi &#8220;motori di reti neurali&#8221; già fatti</strong> che fortunatamente permettono di evitare un bel po&#8217; di complessità numeriche.</p>
<p style="text-align: left;">Nota tecnica: <em>calcolare l&#8217;output di una rete neurale, in particolare di una rete a percettrone con strato singolo nascosto come quelle usate qui, è un gioco da ragazzi, si tratta infatti di poco più di addizioni e prodotti per costanti. L&#8217;allenamento, invece, è un processo ripetititivo abbastanza complesso, soprattutto se si tiene conto delle problematiche di efficienza &#8211; ecco perchè è utile trovare un motore &#8220;chiavi in mano&#8221;.<br />
</em></p>
<p style="text-align: left;">Io ho scelto <a href="http://www.heatonresearch.com/encog" target="_blank">Encog</a>, che ho trovato <strong>veramente ottimo</strong>. Tra le altre cose è <strong>gratuito ed open source</strong>, il che è utile anche per chi volesse approfondire la tematica. Encog ha una bella interfaccia grafica per comporre la rete neurale di interesse, per allenarla e verificarne il funzionamento su dati nuovi senza dover scrivere codice, quindi si adatta bene ai casi in cui è necessaria un po&#8217; di sperimentazione.</p>
<h3 style="text-align: left;">Quanti neuroni allenare?</h3>
<p><a href="http://www.moioli.net/wp-content/uploads/2010/09/homer.jpg"><img class="aligncenter size-full wp-image-416" title="I neuroni di Homer Simpson (pochi)." src="http://www.moioli.net/wp-content/uploads/2010/09/homer.jpg" alt="I neuroni di Homer Simpson (pochi)." width="200" height="198" /></a></p>
<p style="text-align: left;">A questo punto il problema principale è la<strong> scelta del numero di neuroni</strong> che compongono la rete neurale. Come detto la terminologia è un po&#8217; esotica ma non è casuale: nella sua formulazione matematica, infatti, la rete è definita proprio come un&#8217;<strong>interconnessione di unità minime dette neuroni</strong>, e il loro <strong>numero</strong> determina l&#8217;&#8221;<strong>intelligenza</strong>&#8221; della rete stessa!</p>
<p style="text-align: left;">Più precisamente, variare il numero di neuroni in una rete significa controllarne la complessità: <strong>tanti più sono i neuroni tanto più complessa potrà essere la funzione che collettivamente vanno ad emulare</strong>. Il problema è che una rete con molti neuroni, oltre ad essere molto potente, ha anche due svantaggi:</p>
<ol>
<li>richiede <strong>moltissima potenza computazionale per essere allenata</strong>, quindi questa fase potrebbe richiedere ore o giorni, inoltre</li>
<li>rischia di <strong>imparare &#8220;troppo bene&#8221; dagli esempi forniti</strong>, nel senso che dopo l&#8217;apprendimento riconosce perfettamente quelli, ma poi sbaglia completamente con qualunque dato nuovo anche solo leggermente diverso. Questa &#8220;impossibilità di generalizzare&#8221; è detta in gergo <a href="http://en.wikipedia.org/wiki/Overfitting" target="_blank">overfitting</a> ed è naturalmente da evitare.</li>
</ol>
<p style="text-align: left;">Non sapendo cosa far di meglio ho seguito un <strong>approccio sperimentale</strong> variando più volte il numero di neuroni e vedendo quali risultati riuscivo a raggiungere.</p>
<p style="text-align: left;">Nota tecnica: <em>l&#8217;effettiva efficacia di una rete va valutata su un insieme di lettere diverso da quello usato per l&#8217;allenamento, altrimenti si corrono grossi rischi di overfitting. Questa tecnica è generale e viene detta <a href="http://en.wikipedia.org/wiki/Cross-validation_%28statistics%29" target="_blank">cross-validation</a>, ed è supportata da Encog.</em></p>
<p>E&#8217; obbligatorio che ogni rete a percettrone a strato nascosto singolo abbia:</p>
<ul>
<li>un neurone per ogni variabile in input (nel nostro caso, 225),</li>
<li>un neurone per ogni variabile in output (nel nostro caso, 34),</li>
<li>uno o più neuroni ulteriori detti &#8220;nello strato nascosto&#8221;.</li>
</ul>
<p style="text-align: left;">Ovviamente, il punto cruciale è scegliere bene il numero di neuroni in quest&#8217;ultimo punto! Al termine delle mie prove <strong>il numero ottimo sembrava essere 75</strong>, uno per ogni 3 pixel in ingresso, portando quindi il totale a 334 neuroni (una rete di complessità medio-moderata). Stabilito questo si può &#8220;disegnare&#8221; la rete in Encog: qui sotto riporto una schermata del programma che mostra la struttura della rete ed il numero di neuroni.</p>
<p style="text-align: left;"><a href="http://www.moioli.net/wp-content/uploads/2010/09/encog.png"><img class="aligncenter size-full wp-image-399" title="Schermata di Encog di creazione della rete." src="http://www.moioli.net/wp-content/uploads/2010/09/encog.png" alt="Schermata di Encog di creazione della rete." width="568" height="557" /></a></p>
<p style="text-align: left;">Fatto questo si procede all&#8217;allenamento, che è un processo generalmente abbastanza lungo in cui la rete impara dagli esempi <strong>fino a ridurre la percentuale di errori sotto a un certo limite stabilito</strong>. Nella figura seguente, tratta ancora da Encog, si vede l&#8217;andamento dell&#8217;errore durante l&#8217;apprendimento.</p>
<p style="text-align: left;"><a href="http://www.moioli.net/wp-content/uploads/2010/09/allenamento.png"><img class="aligncenter size-full wp-image-418" title="Schermata di Encog durante l'allenamento di una rete neurale." src="http://www.moioli.net/wp-content/uploads/2010/09/allenamento.png" alt="Schermata di Encog durante l'allenamento di una rete neurale." width="640" height="400" /></a></p>
<p style="text-align: left;">Come si può notare la <strong>linea rossa che rappresenta il tasso di errore cala progressivamente</strong> fino a un minimo al quale l&#8217;allenamento si arresta, e la rete è pronta all&#8217;uso!</p>
<p style="text-align: left;">Note tecniche: <em>per i dettagli di funzionamento di Encog rimando <a href="http://www.heatonresearch.com/encog">al sito ufficiale</a>, poichè una spiegazione particolareggiata richiederebbe uno spazio eccessivo. Chiarisco soltanto alcuni punti:</em></p>
<ul>
<li><em>Encog ha bisogno di file <a href="http://en.wikipedia.org/wiki/Comma-separated_values" target="_blank">CSV</a> piuttosto che di immagini per l&#8217;allenamento, la conversione non è descritta perchè tutto sommato banale per chiunque sappia programmare;</em></li>
<li><em>l&#8217;allenamento, in pratica, consiste nella taratura dei parametri della rete neurale in modo che approssimi la funzione voluta;</em></li>
<li><em>esistono più algoritmi per l&#8217;allenamento, molti dei quali sono ancora in stato di attiva ricerca. L&#8217;algoritmo di default di Encog, detto <a href="http://www.heatonresearch.com/dload/ebook/IntroductionToEncogJava.pdf">resilient backpropagation</a>, è molto buono e più che sufficiente per i nostri scopi;</em></li>
<li><em>dall&#8217;interfaccia grafica dell&#8217;Encog Workbench si può esportare codice Java o C# che implementa la rete allenata, a questo punto il codice va integrato con tutte le procedure di trattamento delle immagini viste finora.</em></li>
</ul>
<h3>Prossimi passi<em> </em></h3>
<p>Se siete arrivati fin qui, <strong>complimenti</strong>, la parte dura è passata! Nel prossimo articolo tirerò le somme di quanto visto, farò un minimo di <strong>analisi statistica dei risultati</strong> e pubblicherò qualche spezzone di codice.</p>
<p>Scommetto che stavolta non era tutto così semplice e chiaro, <strong>fatevi sentire nei commenti che rispiego quel che manca oppure è confuso</strong>!</p>
<p><em>A breve pubblicherò la parte 5, se volete restare aggiornati <a href="../progetti/feed/" target="_blank">abbonatevi al feed RSS</a>! </em><em>(a proposito, <a href="http://www.youtube.com/watch?v=nJZVJoTSDyw" target="_blank">cos’è un feed RSS?</a>)</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.moioli.net/progetti/aggirare-captcha-4/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Aggirare un CAPTCHA per divertimento e divulgazione &#8211; Parte 3</title>
		<link>http://www.moioli.net/progetti/aggirare-captcha-3/</link>
		<comments>http://www.moioli.net/progetti/aggirare-captcha-3/#comments</comments>
		<pubDate>Mon, 27 Sep 2010 18:37:54 +0000</pubDate>
		<dc:creator>Silvio Moioli</dc:creator>
				<category><![CDATA[Progetti]]></category>

		<guid isPermaLink="false">http://www.moioli.net/?p=372</guid>
		<description><![CDATA[Questo è il terzo articolo della serie sui CAPTCHA – meglio tornare al primo se non l’hai già letto. Filtraggio e rimozione delle imperfezioni Sistemato il rumore, il compito successivo è quello di separare i caratteri uno dall&#8217;altro. In effetti è abbastanza ovvio: riconoscere una lettera è essenzialmente indipendente dalla sua posizione in un dato [...]]]></description>
			<content:encoded><![CDATA[<p>Questo è il terzo articolo della serie sui CAPTCHA – meglio tornare al <a href="../progetti/aggirare-captcha-1">primo</a> se non l’hai già letto.</p>
<h3>Filtraggio e rimozione delle imperfezioni</h3>
<p>Sistemato il rumore, il compito successivo è quello di <strong>separare i caratteri uno dall&#8217;altro</strong>. In effetti è abbastanza ovvio: riconoscere una lettera è essenzialmente indipendente dalla sua posizione in un dato testo.</p>
<p>Questo passaggio, che all&#8217;uomo risulta naturale, è un po&#8217; più  ostico per le macchine: bisogna pensare a un <strong>modo per distinguere i  contorni</strong> delle lettere, che però <strong>non sempre sono ben definiti</strong>.</p>
<p><span id="more-372"></span></p>
<p>Per <strong>semplificare il problema</strong>, si applica generalmente un <strong>filtro threshold</strong>, ossia &#8220;di soglia&#8221;. Il suo funzionamento è molto semplice: ogni pixel dell&#8217;immagine viene &#8220;riscritto&#8221; in colore bianco se aveva un colore chiaro, al di sotto di una certa soglia, oppure in nero in caso contrario. Credo che un esempio sia molto più facile da capire:</p>
<p><a href="http://www.moioli.net/wp-content/uploads/2010/09/threshold.png"><img class="aligncenter size-full wp-image-373" title="Applicazione di un filtro threshold a un CAPTCHA" src="http://www.moioli.net/wp-content/uploads/2010/09/threshold.png" alt="Applicazione di un filtro threshold a un CAPTCHA" width="610" height="50" /></a></p>
<p>Come si vede, <strong>i contorni sono più netti</strong> dopo il filtraggio, e adesso l&#8217;immagine è praticamente pronta per essere segmentata. Anche se si potrebbe procedere direttamente, ho preferito fare ancora qualche <strong>ulteriore operazione di miglioramento</strong> per eliminare alcune imperfezioni (più propriamente, <a href="http://it.wikipedia.org/wiki/Artefatto_%28segnali%29" target="_blank">artefatti</a>) creati dal filtro precedente. Ne vediamo un esempio nell&#8217;immagine che segue:</p>
<p><a href="http://www.moioli.net/wp-content/uploads/2010/09/imperfezioni.png"><img class="aligncenter size-full wp-image-374" title="Esempi di artefatti sorti dopo l'applicazione del filtro threshold" src="http://www.moioli.net/wp-content/uploads/2010/09/imperfezioni.png" alt="Esempi di artefatti sorti dopo l'applicazione del filtro threshold" width="294" height="178" /></a>Nella &#8220;B&#8221;, come si può notare, c&#8217;è un <strong>punto isolato nero</strong>, mentre nella &#8220;N&#8221; ce n&#8217;è <strong>uno bianco</strong>. In generale, siccome il filtro threshold viene applicato a immagini con una certa variabilità, può capitare che si creino delle piccole aree di colore isolate. Una soluzione per rimuovere questi difetti è <strong>contare</strong>, per ogni punto,<strong> quanti dei punti adiacenti sono bianchi</strong>: se sono la gran maggioranza, ad esempio più di 6 su 9, siamo di fronte a un pixel quasi isolato, e possiamo ricolorarlo in bianco. Discorso analogo si può fare, all&#8217;inverso, per i punti neri. Un&#8217;altra soluzione è quella di calcolare l&#8217;area di ogni parte dell&#8217;immagine con lo stesso colore, ed &#8220;eliminare&#8221; le aree molto piccole, ad esempio sotto i 10 pixel (certamente non rappresentano lettere). Io ho usato entrambi questi approcci, combinati, per rimuovere la maggior parte delle imperfezioni.</p>
<p><a href="http://www.moioli.net/wp-content/uploads/2010/09/imperfezioni-corrette.png"><img class="aligncenter size-full wp-image-375" title="Correzione degli artefatti introdotti dal filtro threshold" src="http://www.moioli.net/wp-content/uploads/2010/09/imperfezioni-corrette.png" alt="Correzione degli artefatti introdotti dal filtro threshold" width="294" height="178" /></a></p>
<h3>Segmentazione dei caratteri</h3>
<p>A questo punto siamo pronti per la segmentazione vera e propria. Nel caso del CAPTCHA di Vodafone, a questo punto, <strong>i caratteri sono ben separati fra di loro</strong> e contigui nei loro tratti, quindi l&#8217;operazione è <strong>particolarmente semplice</strong>. In generale questo è il punto più difficile in assoluto!</p>
<p>L&#8217;algoritmo che ho scritto per separare le lettere usa il &#8220;<strong>flood fill</strong>&#8221; ed è usato nei programmi di grafica per riempire aree dello stesso colore. L&#8217;esempio più noto è lo strumento &#8220;secchiello&#8221; di Microsoft Paint, che permette di riempire di un certo colore porzioni uniformi dell&#8217;immagine.<br />
<a href="http://www.moioli.net/wp-content/uploads/2010/09/paint.png"><img class="aligncenter size-full wp-image-377" title="Schermata del funzionamento di Paint che illustra il flood fill" src="http://www.moioli.net/wp-content/uploads/2010/09/paint.png" alt="Schermata del funzionamento di Paint che illustra il flood fill" width="490" height="410" /></a><br />
Dettagli tecnici: <em>l&#8217;algoritmo percorre l&#8217;immagine da sinistra a destra a varie altezze ed ogniqualvolta incontra un punto nero:<br />
</em></p>
<ol>
<li><em> lo colora,</em></li>
<li><em> colora tutti i punti adiacenti fino a riempire l&#8217;area contigua (ossia la lettera) ed infine</em></li>
<li><em> cambia il colore (in modo che sia diverso per la prossima lettera).</em></li>
</ol>
<p>Altri dettagli sugli algoritmi di flood fill, in particolare sul passo 2, sono reperibili sull&#8217;<a href="http://en.wikipedia.org/wiki/Flood_fill" target="_blank">ottima pagina di Wikipedia</a>.</p>
<p>Il risultato, anche se un po&#8217; carnevalesco, rende perfettamente l&#8217;idea: <strong>le lettere sono separate</strong>.<a href="http://www.moioli.net/wp-content/uploads/2010/09/9NUWH.jpg1.png"><br />
</a></p>
<p><a href="http://www.moioli.net/wp-content/uploads/2010/09/9NUWH.jpg2.png"><img class="aligncenter size-full wp-image-381" title="Un CAPTCHA segmentato" src="http://www.moioli.net/wp-content/uploads/2010/09/9NUWH.jpg2.png" alt="Un CAPTCHA segmentato" width="600" height="100" /></a><br />
A questo punto non resta che individuare, per ogni lettera, il più piccolo rettangolo che contenga tutti i punti dello stesso colore, quindi si possono estrarre le singole lettere.</p>
<p><em>Consiglio agli interessati dell&#8217;argomento una lettura dei manuali di Intelligenza Artificiale, in particolare consiglio caldissimamente il <a href="http://aima.cs.berkeley.edu/" target="_blank">Russel-Norvig</a>, una vera colonna portante della materia.</em></p>
<h3>Prossimi passi<em> </em></h3>
<p>Scomposta l&#8217;immagine in lettere occorrerà <strong>normalizzarle</strong> per dimensione e, soprattutto, <strong>riconoscere i singoli caratteri</strong>, materia della prossima parte di questa serie di articoli. Si tratta della parte concettualmente più difficile, ma anche più interessante!</p>
<p>Tutto chiaro finora?<strong> Vai alla </strong><a href="http://www.moioli.net/progetti/aggirare-captcha-4/">quarta parte</a><strong>!</strong><em> </em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.moioli.net/progetti/aggirare-captcha-3/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Aggirare un CAPTCHA per divertimento e divulgazione &#8211; Parte 2</title>
		<link>http://www.moioli.net/progetti/aggirare-captcha-2/</link>
		<comments>http://www.moioli.net/progetti/aggirare-captcha-2/#comments</comments>
		<pubDate>Sat, 25 Sep 2010 15:06:44 +0000</pubDate>
		<dc:creator>Silvio Moioli</dc:creator>
				<category><![CDATA[Progetti]]></category>

		<guid isPermaLink="false">http://www.moioli.net/?p=332</guid>
		<description><![CDATA[Questo è il secondo articolo della serie sui CAPTCHA &#8211; meglio tornare al primo se non l&#8217;hai già letto. Anatomia di un CAPTCHA: osservare per capire Nell&#8217;immagine seguente trovate un insieme di esempi di sei CAPTCHA presi dal sito vodafone.it. Tanto per iniziare, osserviamo che: il CAPTCHA è sempre formato da cinque caratteri, numeri o [...]]]></description>
			<content:encoded><![CDATA[<p>Questo è il secondo articolo della serie sui CAPTCHA &#8211; meglio tornare al <a href="http://www.moioli.net/progetti/aggirare-captcha-1">primo</a> se non l&#8217;hai già letto.</p>
<h3>Anatomia di un CAPTCHA: osservare per capire</h3>
<p>Nell&#8217;immagine seguente trovate un insieme di esempi di sei CAPTCHA presi dal sito vodafone.it.</p>
<p style="text-align: center;"><a href="http://www.moioli.net/wp-content/uploads/2010/09/captcha.png"><img class="size-full wp-image-333  aligncenter" style="border: 2em solid white;" title="Sei esempi di CAPTCHA da Vodafone.it" src="http://www.moioli.net/wp-content/uploads/2010/09/captcha.png" alt="" width="610" height="170" /></a></p>
<p style="text-align: left;">Tanto per iniziare, osserviamo che:</p>
<ul>
<li> il CAPTCHA è sempre formato da <strong>cinque caratteri</strong>, numeri o lettere. Per evitare ambiguità, alcuni caratteri come lo zero o la &#8220;O&#8221; non compaiono mai;</li>
<li> le <strong>lettere sono distorte</strong>, in particolare sono &#8220;stirate&#8221; verticalmente o orizzontalmente;</li>
<li> c&#8217;è del <strong>rumore di fondo</strong> dietro ogni immagine (<em>apparentemente</em> casuale).</li>
</ul>
<p style="text-align: left;">Proprio l&#8217;ultimo punto rappresenta il punto di partenza ideale per il riconoscimento del CAPTCHA: <strong>se fosse possibile rimuovere il rumore</strong>, almeno in buona parte, <strong>si semplificherebbe parecchio il  riconoscimento</strong>. Come si può fare?</p>
<p style="text-align: left;"><span id="more-332"></span></p>
<h3>Come rimuovere il rumore di fondo</h3>
<p style="text-align: left;">Esistono parecchie tecniche, dette senza troppa fantasia <a href="http://en.wikipedia.org/wiki/Noise_reduction" target="_blank">di riduzione del rumore</a>, che potrebbero essere applicate in linea di principio in questo caso. In realtà non mi tufferò a spiegarle qui perchè <strong>esiste un modo particolarmente semplice</strong> di risolvere il problema senza neanche scomodarle!<br />
Il sistema si basa su un piccolo <strong>difetto nella procedura di generazione</strong> di queste immagini, che i più attenti avranno probabilmente già notato. Guardando bene le immagini, infatti, ci si accorge che <strong>il rumore di fondo non è casuale, ma identico in ogni CAPTCHA!</strong></p>
<p style="text-align: left;">Sovrapponendo le immagini si vede a colpo d&#8217;occhio:<strong><br />
</strong></p>
<p style="text-align: left;"><strong> </strong></p>
<p style="text-align: center;"><a href="http://www.moioli.net/wp-content/uploads/2010/09/captcha-animazione.gif"><img class="size-full wp-image-334 aligncenter" style="border: 2em solid white;" title="Animazione che mostra la sovrapposizione di CAPTCHA" src="http://www.moioli.net/wp-content/uploads/2010/09/captcha-animazione.gif" alt="Animazione che mostra la sovrapposizione di CAPTCHA" width="300" height="50" /></a></p>
<p style="text-align: left;">A questo punto, ragionando per differenza su più di CAPTCHA, è possibile <strong>ricostruire una traccia quasi perfetta dello sfondo</strong> originario. Io ho usato un programmino ad hoc che confronta un centinaio di immagini, con il risultato che si vede sulla destra qui sotto, anche se con un po&#8217; di pazienza si potrebbe fare anche manualmente.</p>
<p style="text-align: center;"><a href="http://www.moioli.net/wp-content/uploads/2010/09/captcha-rumore.png"><img class="size-full wp-image-340 aligncenter" style="border: 2em solid white;" title="Illustrazione dell'estrazione dello sfondo da più CAPTCHA" src="http://www.moioli.net/wp-content/uploads/2010/09/captcha-rumore.png" alt="Illustrazione dell'estrazione dello sfondo da più CAPTCHA" width="640" height="170" /></a></p>
<p>Dettagli tecnici per gli appassionati:<em> l&#8217;algoritmo, per ogni pixel, calcola la moda della sfumatura di grigio sull&#8217;insieme di immagini in esame. Il concetto è che il valore che si ripete più frequentemente sarà probabilmente quello dello sfondo; c&#8217;è poi una piccola correzione per escludere i valori troppo vicini al nero, che con ogni probabilità appartengono alle lettere.</em></p>
<p>Una volta nota l&#8217;immagine con il fondo del rumore, basta una &#8220;<strong>sottrazione per immagini</strong>&#8221; per ottenere un&#8217;immagine &#8220;pulita&#8221;, come nell&#8217;esempio seguente:</p>
<p style="text-align: center;"><a href="http://www.moioli.net/wp-content/uploads/2010/09/captcha-sottrazione.png"><img class="size-full wp-image-341 aligncenter" style="border: 2em solid white;" title="Sottrazione dello sfondo da un CAPTCHA" src="http://www.moioli.net/wp-content/uploads/2010/09/captcha-sottrazione.png" alt="Sottrazione dello sfondo da un CAPTCHA" width="300" height="240" /></a></p>
<p>Altro dettaglio tecnico: <em>la sottrazione non viene effettuata per i pixel molto vicini al nero nell&#8217;immagine da ripulire, in quanto con ogni probabilità appartengono alle lettere.</em></p>
<h3>Prossimi passi<em> </em></h3>
<p>Arrivati a questo punto abbiamo un&#8217;immagine abbastanza buona. Il prossimo problema sarà quello di <strong>dividere i caratteri l&#8217;uno dall&#8217;altro</strong> (per leggerli individualmente, proprio come fanno le persone), e sarà affrontato nella <a href="http://www.moioli.net/misto/aggirare-captcha-3/">terza parte di questa serie</a>.</p>
<p>Tutto chiaro finora?<strong> Aspetto i vostri commenti!</strong><em><br />
</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.moioli.net/progetti/aggirare-captcha-2/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Aggirare un CAPTCHA per divertimento e divulgazione &#8211; Parte 1</title>
		<link>http://www.moioli.net/progetti/aggirare-captcha-1/</link>
		<comments>http://www.moioli.net/progetti/aggirare-captcha-1/#comments</comments>
		<pubDate>Sat, 25 Sep 2010 15:06:30 +0000</pubDate>
		<dc:creator>Silvio Moioli</dc:creator>
				<category><![CDATA[Progetti]]></category>

		<guid isPermaLink="false">http://www.moioli.net/?p=321</guid>
		<description><![CDATA[Cos&#8217;è un CAPTCHA e perchè si usa? Qualunque utente Internet di questi tempi si imbatte di tanto in tanto in un CAPTCHA, ossia in un controllo dell&#8217;&#8221;umanità&#8221; di chi sta alla tastiera, come il seguente: Spesso mi viene chiesto: a cosa servono? La ragione per cui moltissimi siti si dotano di CAPTCHA è la possibilità [...]]]></description>
			<content:encoded><![CDATA[<h3>Cos&#8217;è un CAPTCHA e perchè si usa?</h3>
<p>Qualunque utente Internet di questi tempi si imbatte di tanto in tanto in un CAPTCHA, ossia in un controllo dell&#8217;&#8221;umanità&#8221; di chi sta alla tastiera, come il seguente:</p>
<p style="text-align: center;"><a href="http://www.moioli.net/wp-content/uploads/2010/09/Captcha.jpg"><img class="size-full wp-image-322  aligncenter" title="Esempio di CAPTCHA" src="http://www.moioli.net/wp-content/uploads/2010/09/Captcha.jpg" alt="Esempio di CAPTCHA" width="290" height="80" /></a></p>
<p style="text-align: left;">Spesso mi viene chiesto: <strong>a cosa servono?</strong><br />
La ragione per cui moltissimi siti si dotano di CAPTCHA è la possibilità <strong>discriminare gli utenti veri da programmi automatici</strong> che potrebbero usare il sito in maniera non consona (ad esempio <strong>aprendo le sue pagine a ripetizione per danneggiarlo</strong>).</p>
<p>L&#8217;idea di questo fastidioso dispositivo è che <strong>si possa distinguere un umano da una macchina</strong> tramite un compito che sia:</p>
<ul>
<li> <strong>facile per un uomo</strong> ma</li>
<li> difficile, o meglio <strong>impossibile per un computer</strong></li>
</ul>
<p style="text-align: left;">&#8230;proprio come leggere lettere distorte e senza senso! Si può infatti immaginare che un computer, non essendo intelligente, non sia in grado di leggere qualcosa di imperfetto. <strong>Ma è proprio vero?</strong></p>
<p style="text-align: left;"><span id="more-321"></span></p>
<h3>Si possono aggirare i CAPTCHA?</h3>
<p style="text-align: left;">Apparentemente, i CAPTCHA funzionano bene. In realtà, la distinzione tra ciò che una macchina può o non può fare rispetto all&#8217;uomo spesso non è così netta, ed è così anche per il riconoscimento ottico di oggetti come le lettere.<br />
Esiste infatti un un intero ambito di ricerca, l&#8217;Intelligenza Artificiale, che si occupa proprio di &#8220;avvicinare&#8221; le capacità delle macchine a quelle dell&#8217;uomo. Tra gli altri interessanti ambiti dell&#8217;Intelligenza Artificiale c&#8217;è una disciplina detta <a href="http://it.wikipedia.org/wiki/Optical_character_recognition" target="_blank">OCR</a> o Riconoscimento Ottico dei Caratteri che ha prodotto utili tecniche applicabili anche a questo problema.</p>
<p>Si può, allora, <strong>creare un programma basato sul&#8217;Intelligenza Artificiale per &#8220;leggere&#8221; un CAPTCHA</strong>, vanificando quindi il suo scopo?</p>
<p>Nella maggior parte dei casi, la risposta è un risonante <strong>SI&#8217;</strong>!<br />
<em>(ovviamente, a patto di dedicare un po&#8217; d&#8217;impegno e di studio!)<br />
</em><br />
Cercherò di sostenere questa tesi <strong>spiegando nel dettaglio come &#8220;battere&#8221; un CAPTCHA</strong> abbastanza semplice, quello usato dal sito di <a href="http://www.vodafone.it" target="_blank">Vodafone Italia</a> per gli SMS &#8211; con <strong>oltre il 90% di accuratezza al primo tentativo</strong>!</p>
<p>Chiaramente ogni CAPTCHA è un caso a sè, ma alcune idee fondamentali che illustrerò sono applicabili in generale. Nella prossima serie di articoli spiegherò l&#8217;anatomia di questo particolare CAPTCHA e di come sia riuscito a scrivere un programma che lo &#8220;legge&#8221;.</p>
<h3>Vodafone Italia: siete in ascolto?</h3>
<p style="text-align: left;">Aggiungo infine una nota doverosa: con questi articoli <strong>non voglio incitare il lettore ad aggirare le difese dei siti</strong> che conosce, il mio <strong>obiettivo</strong> è puramente di <strong>divulgazione</strong> dell&#8217;argomento e di <strong>sensibilizzazione</strong> sulle tematiche di sicurezza informatica. Saluto quindi <em>calorosamente</em> il personale Vodafone Italia, che ha tutta la mia simpatia (anche per l&#8217;<em>ottimo trattamento</em> che mi ha riservato durante il colloquio di lavoro): il vostro CAPTCHA era soltanto un esempio calzante, <strong>non ce l&#8217;ho con voi</strong>!</p>
<h3 style="text-align: left;">Prossimi passi</h3>
<p>Nella <a href="http://www.moioli.net/progetti/aggirare-captcha-2">seconda parte</a> di questa serie di articoli mostrerò in dettaglio il CAPTCHA di <a href="http://www.vodafone.it" target="_blank">vodafone.it</a> ed introdurrò la tematica della riduzione del rumore, il primo passo essenziale per la lettura. Spiegherò successivamente tutti i passaggi fino ad all&#8217;interpretazione completa dell&#8217;immagine. Al termine della serie pubblicherò anche alcuni frammenti di codice Scala e Java che ho implementato e mettono in pratica le idee presentate.</p>
<p>Buona lettura!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.moioli.net/progetti/aggirare-captcha-1/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Fine di MoioSMS</title>
		<link>http://www.moioli.net/progetti/fine-di-moiosms/</link>
		<comments>http://www.moioli.net/progetti/fine-di-moiosms/#comments</comments>
		<pubDate>Sat, 25 Sep 2010 15:06:13 +0000</pubDate>
		<dc:creator>Silvio Moioli</dc:creator>
				<category><![CDATA[Progetti]]></category>

		<guid isPermaLink="false">http://www.moioli.net/?p=315</guid>
		<description><![CDATA[Cari amici e utenti di MoioSMS, sono molto spiaciuto, oggi, di dichiarare la fine ufficiale del programma e del forum. Mi spiace soprattutto per tutti quelli che mi hanno contattato in questi mesi e a cui ho risposto parlando del futuro &#8211; putroppo sono arrivato a un punto in cui neanche nella miglior futuro possibile [...]]]></description>
			<content:encoded><![CDATA[<p><em>Cari amici e utenti di MoioSMS</em>,</p>
<p>sono molto spiaciuto, oggi, di dichiarare la fine ufficiale del programma e del forum. Mi spiace soprattutto per tutti quelli che mi hanno contattato in questi mesi e a cui ho risposto parlando del futuro &#8211; putroppo sono arrivato a un punto in cui <strong>neanche nella miglior futuro possibile riuscirei più a seguire tutti i progetti</strong> che ho aperto.</p>
<p><span id="more-315"></span></p>
<p>Sono soggetto a una <em>crisi cronica di tempo libero</em> &#8211; neanche le ferie del mese di Agosto sono state sufficienti a dare un po&#8217; di respiro ai progetti, come MoioSMS, che da troppo tempo aspettano di essere aggiornati. L&#8217;errore è stato probabilmente di intraprenderne troppi: dovendo ora tirare le somme, a malincuore, sono costretto a tagliare da qualche parte.</p>
<p>Ho a lungo sperato di cavarmela con qualche trucco &#8211; la <a href="http://www.moioli.net/progetti/la-strada-che-porta-a-moiosms-3/">versione 3</a> avrebbe dovuto risparmiarmi diverse ore di sviluppo per la manutenzione, ad esempio &#8211; ma dalla piega che hanno preso le ultime settimane mi rendo conto che è inutile continuare a rimandare.</p>
<p>Spero che qualche sviluppatore ben intenzionato possa continuare a portare avanti quel che resta di MoioSMS, con un altro nome e un&#8217;altra squadra, ma magari con la stessa passione. Se ci siete, fatevi sentire nei commenti!</p>
<p>Un saluto,</p>
<p><a href="http://www.moioli.net/wp-content/uploads/2010/09/firma.png"><img class="size-full wp-image-316 alignnone" title="Firma di Silvio" src="http://www.moioli.net/wp-content/uploads/2010/09/firma.png" alt="Silvio" width="245" height="168" /></a></p>
<p>PS: spero di riuscire a portare avanti <em>almeno</em> gli articoli qui  su moioli.net. Tanto per cominciare oggi pubblico la <a href="http://www.moioli.net/progetti/aggirare-captcha-1">prima parte di un  articolo sui CAPTCHA</a> e su come possano essere aggirati &#8211; spero sia di  ispirazione per gli sviluppatori che leggono queste righe!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.moioli.net/progetti/fine-di-moiosms/feed/</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
		<item>
		<title>La strada che porta a MoioSMS 3</title>
		<link>http://www.moioli.net/progetti/la-strada-che-porta-a-moiosms-3/</link>
		<comments>http://www.moioli.net/progetti/la-strada-che-porta-a-moiosms-3/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 15:16:08 +0000</pubDate>
		<dc:creator>Silvio Moioli</dc:creator>
				<category><![CDATA[Progetti]]></category>

		<guid isPermaLink="false">http://www.moioli.net/?p=306</guid>
		<description><![CDATA[Nonostante le migliori intenzioni, dopo un periodo iniziale non sono riuscito a portare a termine la nuova versione di MoioSMS ed ho dovuto abbandonare il progetto per carenza di tempo a disposizione. Lascio l&#8217;articolo qui per chi lo volesse leggere, ma le informazioni riportate sono essenzialmente obsolete. Come anticipato a qualcuno sul forum, è mia [...]]]></description>
			<content:encoded><![CDATA[<p><em>Nonostante le migliori intenzioni, dopo un periodo iniziale non sono riuscito a portare a termine la nuova versione di MoioSMS ed ho dovuto <a href="http://www.moioli.net/progetti/fine-di-moiosms/">abbandonare il progetto per carenza di tempo a disposizione</a>.</em></p>
<p>Lascio l&#8217;articolo qui per chi lo volesse leggere, ma le informazioni riportate sono essenzialmente obsolete.</p>
<p><span id="more-306"></span></p>
<p>Come anticipato a qualcuno sul <a href="http://www.moioli.net/forum/">forum</a>, è mia intenzione <strong>rinnovare radicalmente MoioSMS</strong>. La prossima versione di MoioSMS, la numero 3, si baserà su una piattaforma del tutto diversa e, nelle speranze di chi scrive, occorrerà <strong>meno tempo per mantenerla aggiornata</strong> &#8211; una condizione essenziale perchè un progetto come questo, che è fatto nel tempo libero, possa sopravvivere. Cercherò anche, come sempre, di rendere il programma più <strong>semplice</strong> e <strong>funzionale</strong> per l&#8217;utente.</p>
<p>Questo articolo spiega le ragioni della mia decisione ed ha un taglio decisamente tecnico &#8211; spero che gli altri sviluppatori dicano la loro nei commenti.</p>
<h3>Motivazioni del cambiamento</h3>
<p>La ragione di una così drastica decisione è dovuta a più fattori, il principale è che ritengo Python una piattaforma <strong>non più soddisfacente per le esigenze</strong> di questo progetto. Nonostante sia perfetto per l&#8217;uso in Linux, ambiente dove il progetto è nato, non è così semplice mantenere una buona compatibilità anche con gli altri Sistemi Operativi (ad esempio, lo stato di manutenzione ed aggiornamento di <a href="http://www.py2exe.org/">py2exe</a> e <a href="http://svn.pythonmac.org/py2app/py2app/trunk/doc/index.html">py2app</a> lascia parecchio a desiderare).</p>
<p>Un punto dolente sono le librerie grafiche che anni fa scelsi per l&#8217;interfaccia utente, le famose <a href="http://www.wxwidgets.org/">WxWidgets</a>, che nel tempo hanno mostrato una lunga serie di limiti, errori non risolti, carenze di documentazione e <strong>poca uniformità</strong> tra Windows, Mac e Linux.</p>
<p>Altro punto debole è il sistema di decodifica delle immagini CAPTCHA, più che <strong>macchinoso</strong>, <strong>inefficiente</strong> e dipendente da una serie di altri programmi. D&#8217;altra parte, Python non dispone a mio parere di un&#8217;implementazione sufficientemente buona delle reti neurali, gli oggetti matematici che si usano a questo scopo, quindi non è facile passare ad algoritmi migliori. Il fatto di usare programmi esterni, inoltre, ha dato origine a una serie di grattacapi su come rendere il programma autocontenuto, il che ha sollevato nuovi problemi con firewall ed antivirus in Windows.</p>
<p>I problemi di Python non si fermano qui: un&#8217;esigenza da troppo tempo trascurata è quella di ristrutturare l&#8217;applicazione in modo da funzionare su più thread di esecuzione, per evitare di bloccare l&#8217;interfaccia durante l&#8217;invio dei messaggi. Anche qui, il supporto di Python alla programmazione concorrente è <strong>rudimentale</strong>, soprattutto in ottica di indipendenza dalla piattaforma (questo è cambiato recentemente con librerie come <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=230001">Twisted</a>, che però usa processi anzichè thread, una soluzione a mio parere sub-ottimale).</p>
<h3>Nuove idee</h3>
<p>Ho passato parecchio tempo prima di trovare, capire e scegliere la tecnologia giusta per superare questi problemi. La scelta è infine ricaduta sul linguaggio <a href="http://www.scala-lang.org/">Scala</a>, che fa uso della <a href="http://en.wikipedia.org/wiki/Java_platform">piattaforma Java</a>. I vantaggi che mette a disposizione sono notevoli:</p>
<ul>
<li><a href="http://www.scala-lang.org/node/25">permette di scrivere codice compatto</a>, similmente a Python e a differenza di Java, pur restando un linguaggio <a href="http://en.wikipedia.org/wiki/Static_typing#Static_typing">tipato staticamente</a>, il che aiuta lo sviluppatore a trovare difetti nel codice prima della sua pubblicazione;</li>
<li>ha integrata una libreria per il multitheading basata sul <a href="http://en.wikipedia.org/wiki/Actor_model">modello ad attori</a>, che ritengo essere <strong>decisamente buono</strong> (l&#8217;ho usato, tra le altre cose, nella mia <a href="http://www.moioli.net/uni/video-di-laurea/">tesi di secondo livello</a> in quanto fornito direttamente in <a href="http://doc.trolltech.com/4.6/threads-qobject.html#signals-and-slots-across-threads">Qt</a> come estensione del meccanismo <a href="http://en.wikipedia.org/wiki/Signals_and_slots">signals&amp;slots</a>);</li>
<li>essendo basato sulla piattaforma Java:
<ul>
<li>è <strong>meglio predisposto</strong>, rispetto a Python, per lo sviluppo su più piattaforme (vedi il <a href="http://en.wikipedia.org/wiki/Write_once,_run_anywhere">concetto WORA</a>: anche se non è vero in termini assoluti lo è in buona parte). Non ho dubbi, ad esempio, sul fatto che si possano realizzare interfacce più portabili in Swing piuttosto che WxWidgets per esperienze passate;</li>
<li>permette di accedere a un <strong>numero esorbitante di librerie,</strong> anche di alta qualità, già esistenti per Java, in particolare l&#8217;ottima <a href="http://www.heatonresearch.com/encog">libreria Encog per le reti neurali</a>;</li>
<li>permette di ottenere eseguibili (Jar) più compatti rispetto agli exe/app attuali ed effettivamente eseguibili con un doppio click su tutte le piattaforme &#8211; al patto al più di installare un JRE su Windows qualora non sia già presente, cosa comunque <a href="http://jsmooth.sourceforge.net/">facilmente aggirabile</a>. Inoltre con poca fatica si possono ottenere Jar completamente autocontenuti, integrando la libreria per l&#8217;accesso http, la libreria per le reti neurali, i dati statici necessari e così via.</li>
</ul>
</li>
</ul>
<h3>Cosa resta da fare</h3>
<p>Le motivazioni che ho esposto non piovono dal cielo, in quanto prima di sbilanciarmi <strong>ho già preparato una versione (molto) preliminare di MoioSMS</strong> che riesce a mandare messaggi da Vodafone con un algoritmo apposito di decodifica dei CAPTCHA che arriva a un quasi-incredibile <strong>92% di accuratezza</strong>. Nel prossimo periodo scriverò qui sul sito alcuni articoli che spiegheranno come il sistema funziona.</p>
<p>Nel frattempo punto a rilasciare una prima versione utilizzabile di MoioSMS 3. Per evitare di aspettare altri anni dapprincipio non ci saranno molti dei siti inizialmente supportati e molte funzionalità dovranno essere aggiunte in seguito, ma fin da subito dovrebbero vedersi i frutti della nuova architettura:</p>
<ul>
<li>un eseguibile autocontenuto, compatto e comune a tutte le piattaforme, con molti meno problemi di dipendenze;</li>
<li>la spedizione degli SMS in un thread separato;</li>
<li>decodifica dei CAPTCHA (inizialmente, di Vodafone) estremamente più veloce ma soprattutto</li>
<li>un tempo di risposta ai problemi degli utenti inferiore.</li>
</ul>
<h3>Agli altri sviluppatori</h3>
<p>Innanzitutto, grazie per tutto quello che avete fatto in questi mesi. Temo che qualcuno di voi non sarà contento di leggere queste righe &#8211; l&#8217;abbandono di Python sarà un divorzio doloroso, e forse non strettamente necessario, ma <strong>spero che condividiate le mie ragioni</strong> e che continuiate ad operare nella comunità di MoioSMS. E&#8217; mia intenzione coinvolgervi maggiormente rispetto al passato, ovviamente se siete disponibili, iniziando da una discussione sulle idee in questo articolo.</p>
<p>A presto!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.moioli.net/progetti/la-strada-che-porta-a-moiosms-3/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>Video della laurea triennale</title>
		<link>http://www.moioli.net/uni/video-della-laurea-triennale/</link>
		<comments>http://www.moioli.net/uni/video-della-laurea-triennale/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 17:55:48 +0000</pubDate>
		<dc:creator>Silvio Moioli</dc:creator>
				<category><![CDATA[Università]]></category>

		<guid isPermaLink="false">http://www.moioli.net/?p=293</guid>
		<description><![CDATA[Anche se è passato un po&#8217; di tempo credo che l&#8217;argomento delle interfacce utente zoomabili, o ZUI, sia ancora interessante, quindi ripropongo qui il video della mia discussione della laurea triennale, in cui espongo un prototipo di questo tipo di software. E&#8217; più facile da vedere che da spiegare, quindi buona visione! Video di laurea [...]]]></description>
			<content:encoded><![CDATA[<p>Anche se è passato un po&#8217; di tempo credo che l&#8217;argomento delle <strong>interfacce utente zoomabili</strong>, o <a href="http://en.wikipedia.org/wiki/Zooming_user_interface">ZUI</a>, sia ancora interessante, quindi ripropongo qui il video della mia discussione della laurea triennale, in cui espongo un prototipo di questo tipo di software.</p>
<p>E&#8217; più facile da vedere che da spiegare, quindi buona visione!</p>
<p><a href="http://www.moioli.net/wp-content/uploads/2010/02/presentazione-primo-livello.jpg"><img class="aligncenter size-medium wp-image-301" title="Presentazione della laurea di primo livello" src="http://www.moioli.net/wp-content/uploads/2010/02/presentazione-primo-livello-300x174.jpg" alt="" width="300" height="174" /></a></p>
<ul>
<li><a href="http://vimeo.com/8630438">Video di laurea su Vimeo</a> per la visione diretta;</li>
<li><a href="http://vimeo.com/download/video:13967573?v=2&amp;e=1267124066&amp;h=bf333189c493fb9f8e2020778463c599&amp;uh=caf214cea2932ed152b4904f80e92e5c">Video di laurea in versione mp4</a> per il download (68 MB).</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.moioli.net/uni/video-della-laurea-triennale/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Nuovo provider: Unbit.it</title>
		<link>http://www.moioli.net/misto/nuovo-provider-unbit-it/</link>
		<comments>http://www.moioli.net/misto/nuovo-provider-unbit-it/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 21:20:39 +0000</pubDate>
		<dc:creator>Silvio Moioli</dc:creator>
				<category><![CDATA[Il misto]]></category>

		<guid isPermaLink="false">http://www.moioli.net/?p=285</guid>
		<description><![CDATA[Da ieri questo sito ha cambiato provider da Aruba.it ad Unbit.it. Come sempre in questi casi è prevedibile qualche sobbalzo o qualche piccolo malfunzionamento: per il momento l&#8217;esperienza è ottima ma se riscontrate errori o problemi del sito fatemi sapere all&#8217;indirizzo silvio at moioli punto net.]]></description>
			<content:encoded><![CDATA[<p><img src="file:///Users/silvio/Desktop/logo_unbit_header.jpg" alt="" /></p>
<p><a href="http://www.moioli.net/wp-content/uploads/2010/01/logo_unbit_header.jpg"><img class="aligncenter size-full wp-image-288" title="logo_unbit_header" src="http://www.moioli.net/wp-content/uploads/2010/01/logo_unbit_header.jpg" alt="" width="245" height="90" /></a></p>
<p>Da ieri questo sito ha cambiato provider da Aruba.it ad Unbit.it.</p>
<p>Come sempre in questi casi è prevedibile qualche sobbalzo o qualche piccolo malfunzionamento: per il momento l&#8217;esperienza è ottima ma se riscontrate errori o problemi del sito fatemi sapere all&#8217;indirizzo silvio at moioli punto net.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.moioli.net/misto/nuovo-provider-unbit-it/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

