{"id":132,"date":"2011-05-17T09:39:00","date_gmt":"2011-05-17T07:39:00","guid":{"rendered":"http:\/\/www.sululab.com\/blog\/2011\/05\/17\/processing-geco-peloso-furry-gecko\/"},"modified":"2022-04-20T18:49:29","modified_gmt":"2022-04-20T16:49:29","slug":"processing-geco-peloso-furry-gecko","status":"publish","type":"post","link":"https:\/\/www.sululab.com\/blog\/2011\/05\/17\/processing-geco-peloso-furry-gecko\/","title":{"rendered":"Processing. Geco peloso &#8211; Furry gecko"},"content":{"rendered":"<div><iframe loading=\"lazy\" src=\"http:\/\/player.vimeo.com\/video\/24173433?title=0&amp;byline=0&amp;portrait=0\" width=\"500\" height=\"375\" frameborder=\"0\"><\/iframe><\/div>\n<div>English version below.<\/div>\n<div><a href=\"http:\/\/www.sululab.com\/download\/gecko.rar\">Download dello sketch<\/a><\/p>\n<\/div>\n<div>\n<div>Una delle caratteristiche pi\u00f9 interessanti di Processing \u00e8 il fatto di avere delle funzioni predefinite per lavorare con le immagini.<\/div>\n<div>Per il loro utilizzo si pu\u00f2 consultare l&#8217;help interno all&#8217;ambiente di sviluppo (Help-&gt; Reference).<\/div>\n<div><\/div>\n<div>Volevo realizzare un effetto che agisse sui bordi del soggetto di un&#8217;immagine, quindi ne ho scelta una in cui il bordo fosse abbastanza definito:<\/div>\n<\/div>\n<p><a href=\"http:\/\/4.bp.blogspot.com\/-9EWX1fGfDV4\/TdI1E_vwjoI\/AAAAAAAAAm0\/0N9cGbJJN0w\/s1600\/DSC05842.JPG\"><img decoding=\"async\" alt=\"\" border=\"0\" id=\"BLOGGER_PHOTO_ID_5607602845977185922\" src=\"http:\/\/4.bp.blogspot.com\/-9EWX1fGfDV4\/TdI1E_vwjoI\/AAAAAAAAAm0\/0N9cGbJJN0w\/s320\/DSC05842.JPG\" style=\"cursor: hand; cursor: pointer; height: 240px; margin: 0 10px 10px 0; width: 320px;\"><\/a><\/p>\n<div>\n<div>\n<div>Per prima cosa bisogna caricare l&#8217;immagine nel nostro progetto attraverso il men\u00f9 Sketch -&gt; Add file&#8230;, questo crea una cartella &#8220;data&#8221; in cui viene copiata l&#8217;immagine da utilizzare.<\/div>\n<div>A questo punto bisogna individuare il bordo del soggetto. La parte di codice che ci interessa \u00e8 la seguente (da inserire nel blocco &#8220;draw()&#8221;):<\/div>\n<div>\n<pre style=\"color:#039\">b = loadImage(\"DSC05842.JPG\");\nimage(b, 0, 0, width, height);\nfilter(THRESHOLD, 0.4);<\/pre>\n<\/div>\n<div>Applichiamo un filtro all&#8217;immagine, attraverso una chiamata, &#8220;filter(THRESHOLD, 0.4)&#8221;, alla funzione filter, con primo parametro impostato su &#8220;THRESHOLD&#8221;, che individua appunto i contorni degli oggetti nella foto, trasformando l&#8217;immagine in bianco e nero. Giocando un po&#8217; con il secondo parametro (che va da 0 a 1, default 0.5) possiamo migliorare la resa per la nostra fotografia. Il risultato \u00e8 questo:<\/div>\n<\/div>\n<div><a href=\"http:\/\/1.bp.blogspot.com\/-6yrJUzNrE20\/TdI1x9q9fvI\/AAAAAAAAAm8\/n5AxBBjj1fg\/s1600\/geco_thre.jpg\"><img decoding=\"async\" alt=\"\" border=\"0\" id=\"BLOGGER_PHOTO_ID_5607603618514304754\" src=\"http:\/\/1.bp.blogspot.com\/-6yrJUzNrE20\/TdI1x9q9fvI\/AAAAAAAAAm8\/n5AxBBjj1fg\/s320\/geco_thre.jpg\" style=\"cursor: hand; cursor: pointer; height: 257px; margin: 0 10px 10px 0; width: 320px;\"><\/a><\/p>\n<div>\n<pre style=\"color:#039\">loadPixels();\nfor (int i = 0; i &lt; width * height - 1; i++) {\nif (pixels[i] != pixels[i + 1]){\nbordo[i] = 1;\n}else{\nbordo[i] = 0;\n}\n}\nupdatePixels();<\/pre>\n<p>E&#8217; importante capire come Processing tratta le informazioni contenute nel file: attraverso l&#8217;istruzione loadPixels(), i dati relativi ai pixel dell&#8217;immagine vengono caricati nell&#8217;array Pixels[], i cui elementi contengono il valore del colore di ogni singolo pixel.<\/p>\n<p>L&#8217;immagine viene &#8220;affettata&#8221;, nel senso della larghezza, in linee spesse 1px, quindi tutte le linee vengono poste una dietro l&#8217;altra, a formarne una unica. Se, ad esempio, avessimo un&#8217;immagine composta da 5&#215;3 pixel, questa verrebbe trattata cos\u00ec:<\/p>\n<p><a href=\"http:\/\/2.bp.blogspot.com\/-oX7OtrlEnvM\/TdI3MC1Bx3I\/AAAAAAAAAnE\/zKEQIX8Q4TA\/s1600\/geco.gif\"><img decoding=\"async\" alt=\"\" border=\"0\" id=\"BLOGGER_PHOTO_ID_5607605166086932338\" src=\"http:\/\/2.bp.blogspot.com\/-oX7OtrlEnvM\/TdI3MC1Bx3I\/AAAAAAAAAnE\/zKEQIX8Q4TA\/s320\/geco.gif\" style=\"cursor: hand; cursor: pointer; height: 148px; margin: 0 10px 10px 0; width: 320px;\"><\/a><\/p>\n<div>Nel nostro caso, avendo usato la funzione threshold, i valori memorizzati saranno solo due: quello del bianco e quello del nero.<\/p>\n<p>Adesso vogliamo semplificare il vettore in modo da avere degli &#8220;1&#8221; lungo i bordi e &#8220;0&#8221; in tutto gli altri punti. Per farlo scansioniamo il vettore Pixels[] attraverso un ciclio &#8220;for&#8221; e, quando troviamo due valori diversi per due pixel consecutivi, cosa che indica la presenza del bordo, memorizziamo nell&#8217;elemento corrispondente dell&#8217;array bordo[] il valore &#8220;1&#8221;, mentre nell&#8217;altro caso, quando i due valori sono uguali, memorizziamo &#8220;0&#8221;. Chiudiamo questo blocco con updatePixels(), consigliato anche se non strettamente necessario.<\/p>\n<pre style=\"color:#039\">c = loadImage(\"DSC05842.JPG\");\nimage(c, 0, 0, width, height);\nloadPixels();\nfor (int i = 0; i &lt; width * height - 1; i++) {\nif (bordo[i] == 1){\nx = i%width;\ny = i\/width;\nstroke(pixels[i]);\nbeginShape();\nvertex(x, y); \/\/ first point\nbezierVertex( x + random(25), y + random(25), x + random(25), y + random(25), x + random(25), y + random(25));\nendShape();\n}\n}<\/pre>\n<p>Ora conosciamo dove sono i bordi ma non abbiamo pi\u00f9 i valori relativi ai colori di questi bordi, avendo applicato la funzione &#8220;filter(THRESHOLD, 0.4)&#8221;.<\/p>\n<p>Per questo carichiamo di nuovo la stessa immagine una seconda volta. Ora scansioniamo contemporaneamente gli array bordo[] e Pixels[] con un ciclo &#8220;for&#8221;. Quando siamo sul bordo, prendiamo il colore del pixel corrispondente e ci tracciamo una curva attraverso la funzione &#8220;bezierVertex&#8221;, assegnando dei valori random ai parametri che essa richiede, in modo da disegnare delle piccole curve. Ovviamente si pu\u00f2 giocare con questi parametri per cambiare l&#8217;effetto risultante.<\/p>\n<p>Il punto di partenza della curva sar\u00e0 lungo il bordo e dobbiamo ricavare le sue coordinate, cio\u00e8 dobbiamo fare il passaggio inverso a quello della figura qui sopra.<\/p>\n<p>Come al solito, il punto origine del piano (0, 0) si trova nell&#8217;angolo in alto a sinistra, anche in Processing.<\/p>\n<p>Guardando la figura qui sotto, supponiamo che nell&#8217;elemento 8 dell&#8217;array bordo[] ci sia memorizzato il valore &#8220;1&#8221;. La posizione di questo punto nel piano \u00e8 data dalle due coordinate (x, y), cos\u00ec ricavate: la x \u00e8 il resto della divisione intera di 8 per 5 (la larghezza dell&#8217;immagine), quindi 3, mentre la y \u00e8 data dalla parte intera della divisione di 8 per 5, quindi 1. Allora le coordinate sono (3, 1).<br \/>\n<a href=\"http:\/\/1.bp.blogspot.com\/-jLvvxoGJOQI\/TdI3Md7TJDI\/AAAAAAAAAnM\/vE3oF8-vRCM\/s1600\/geco1.gif\"><img decoding=\"async\" alt=\"\" border=\"0\" id=\"BLOGGER_PHOTO_ID_5607605173360993330\" src=\"http:\/\/1.bp.blogspot.com\/-jLvvxoGJOQI\/TdI3Md7TJDI\/AAAAAAAAAnM\/vE3oF8-vRCM\/s320\/geco1.gif\" style=\"cursor: hand; cursor: pointer; height: 148px; margin: 0 10px 10px 0; width: 320px;\"><\/a><br \/>\nSiccome disegnamo le curve di Bezier nella sezione &#8220;draw()&#8221;, questo calcolo verr\u00e0 ripetuto ciclicamente, dando la sensazione di un movimento di questa specie di pelliccia.<\/p>\n<p><a href=\"http:\/\/www.sululab.com\/download\/gecko.rar\">Download dello sketch<\/a><\/p>\n<hr>\n<div><a href=\"http:\/\/www.sululab.com\/download\/gecko.rar\">Download the sketch<\/a><\/p>\n<p>One of the most interesting features of Processing are the built-in functions for image processing.<\/p>\n<\/div>\n<div>To use them, you can see the internal help (Help-&gt; Reference).<\/div>\n<div><\/div>\n<div>I wanted to create an effect acting on the edges of the subject of a picture, then I have a choice in which the board was sufficiently defined:<\/p>\n<p><a href=\"http:\/\/4.bp.blogspot.com\/-9EWX1fGfDV4\/TdI1E_vwjoI\/AAAAAAAAAm0\/0N9cGbJJN0w\/s1600\/DSC05842.JPG\"><img decoding=\"async\" alt=\"\" border=\"0\" id=\"BLOGGER_PHOTO_ID_5607602845977185922\" src=\"http:\/\/4.bp.blogspot.com\/-9EWX1fGfDV4\/TdI1E_vwjoI\/AAAAAAAAAm0\/0N9cGbJJN0w\/s320\/DSC05842.JPG\" style=\"cursor: hand; cursor: pointer; height: 240px; margin: 0 10px 10px 0; width: 320px;\"><\/a><br \/>\nFirst you must load the image in your project via the Sketch menu -&gt; Add Files&#8230;, this creates a folder &#8220;data&#8221; in which the image is copied to be used.<\/p>\n<p>At this point we identify the edge of the subject. The piece of code that interests us is the following (to be included in the block &#8220;draw ()&#8221;):<\/p>\n<pre style=\"color:#039\">b = loadImage(\"DSC05842.JPG\");\nimage(b, 0, 0, width, height);\nfilter(THRESHOLD, 0.4);<\/pre>\n<p>We apply a filter to the image, through a call, &#8220;filter (THRESHOLD, 0.4), to the filter function, with the first parameter set to&#8221; Threshold &#8220;, which identifies precisely the contours of objects in the picture, turning the image into black and white. Playing a little with the second parameter (ranging from 0 to 1, default 0.5) we can improve the yield for our photography. The result is this:<\/p>\n<p><a href=\"http:\/\/1.bp.blogspot.com\/-6yrJUzNrE20\/TdI1x9q9fvI\/AAAAAAAAAm8\/n5AxBBjj1fg\/s1600\/geco_thre.jpg\"><img decoding=\"async\" alt=\"\" border=\"0\" id=\"BLOGGER_PHOTO_ID_5607603618514304754\" src=\"http:\/\/1.bp.blogspot.com\/-6yrJUzNrE20\/TdI1x9q9fvI\/AAAAAAAAAm8\/n5AxBBjj1fg\/s320\/geco_thre.jpg\" style=\"cursor: hand; cursor: pointer; height: 257px; margin: 0 10px 10px 0; width: 320px;\"><\/a><\/p>\n<div>\n<pre style=\"color:#039\">loadPixels();\nfor (int i = 0; i &lt; width * height - 1; i++) {\nif (pixels[i] != pixels[i + 1]){\nbordo[i] = 1;\n}else{\nbordo[i] = 0;\n}\n}\nupdatePixels();<\/pre>\n<div>It is important to understand how Processing uses the information contained in the file: through the loadPixels() function, the image pixel data are loaded into the array pixels[], elements of which contain the color value of every pixel.<\/div>\n<div>The image is &#8220;sliced\u200b\u200b&#8221; in the sense of the width, in thick lines of 1px, and then all the lines are placed one after the other, forming a single array. If, for example, we had a picture made \u200b\u200bup of 5&#215;3 pixels, this would be treated like this:<br \/>\n<a href=\"http:\/\/2.bp.blogspot.com\/-oX7OtrlEnvM\/TdI3MC1Bx3I\/AAAAAAAAAnE\/zKEQIX8Q4TA\/s1600\/geco.gif\"><img decoding=\"async\" alt=\"\" border=\"0\" id=\"BLOGGER_PHOTO_ID_5607605166086932338\" src=\"http:\/\/2.bp.blogspot.com\/-oX7OtrlEnvM\/TdI3MC1Bx3I\/AAAAAAAAAnE\/zKEQIX8Q4TA\/s320\/geco.gif\" style=\"cursor: hand; cursor: pointer; height: 148px; margin: 0 10px 10px 0; width: 320px;\"><\/a><\/p>\n<p>We have used the threshold function, so the values in the array \u200b\u200bwill be only two: one for the white and one for the black.<\/p>\n<p>Now we want to simplify the array in order to have the &#8220;1&#8221; along the edges and &#8220;0&#8221; in all other points. To do this, we scan the array Pixels[] through a &#8220;for&#8221; loop, and when we find two different values \u200b\u200bfor two consecutive pixels, which indicates the presence of the edge, we store in the corresponding array bordo[] the value &#8220;1&#8221;. While in the other case, when the two values \u200b\u200bare equal, store &#8220;0&#8221;.  We close this block with updatePixels(), recommended but not necessary.<\/p>\n<pre style=\"color:#039\"><span>c = loadImage(\"DSC05842.JPG\");\nimage(c, 0, 0, width, height);\nloadPixels();\nfor (int i = 0; i &lt; width * height - 1; i++) {\nif (bordo[i] == 1){\nx = i%width;\ny = i\/width;\nstroke(pixels[i]);\nbeginShape();\nvertex(x, y); \/\/ first point\nbezierVertex( x + random(25), y + random(25), x + random(25), y + random(25), x + random(25), y + random(25));\nendShape();\n}\n}<\/span><\/pre>\n<p>Now we know where are the edges but we do not have values \u200b\u200bfor the colors of these edges, because we used the &#8220;filter (THRESHOLD, 0.4).<\/p>\n<p>So we load again the same image a second time. Now we scan in the same time arraies bordo[] and Pixels[] by a &#8220;for&#8221; loop. When we&#8217;re on the edge, we color the corresponding pixel, and we draw a curve through the &#8220;bezierVertex&#8221;, assigning random values \u200b\u200bto the parameters it requires, in order to draw small curves. Of course you can play with these parameters to change the resulting effect.<\/p>\n<p>The starting point of the curve is along the edge and we will derive its coordinates, ie we have to apply the opposite function of the picture above.<\/p>\n<p>As usual, the origin point of the plan (0, 0) is located in the upper left corner of the image, even in Processing.<\/p>\n<p>Looking at the figure below, suppose that in the element 8 of the array  bordo[] is stored the value &#8220;1&#8221;. The location of this point in the plane is given by two coordinates (x, y), so obtained: x is the remainder of the integer division of 8 by 5 (the width of the image), then 3, and y is given by the integer part of the integer division of 8 by 5, then 1. So the coordinates are (3, 1).<br \/>\n<a href=\"http:\/\/1.bp.blogspot.com\/-jLvvxoGJOQI\/TdI3Md7TJDI\/AAAAAAAAAnM\/vE3oF8-vRCM\/s1600\/geco1.gif\"><img decoding=\"async\" alt=\"\" border=\"0\" id=\"BLOGGER_PHOTO_ID_5607605173360993330\" src=\"http:\/\/1.bp.blogspot.com\/-jLvvxoGJOQI\/TdI3Md7TJDI\/AAAAAAAAAnM\/vE3oF8-vRCM\/s320\/geco1.gif\" style=\"cursor: hand; cursor: pointer; height: 148px; margin: 0 10px 10px 0; width: 320px;\"><\/a><br \/>\nAs we draw Bezier curves in the &#8220;draw()&#8221; section, this calculation will be repeated periodically, giving the feeling of a movement of this kind of fur.<\/p>\n<p><a href=\"http:\/\/www.sululab.com\/download\/gecko.rar\">Download the sketch<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>English version below. Download dello sketch Una delle caratteristiche pi\u00f9 interessanti di Processing \u00e8 il fatto di avere delle funzioni predefinite per lavorare con le immagini. Per il loro utilizzo si pu\u00f2 consultare l&#8217;help interno all&#8217;ambiente di sviluppo (Help-&gt; Reference)&#8230;. <a class=\"more-link\" href=\"https:\/\/www.sululab.com\/blog\/2011\/05\/17\/processing-geco-peloso-furry-gecko\/\">Continua a leggere &rarr;<\/a><\/p>\n","protected":false},"author":1,"featured_media":330,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[224,216,223],"tags":[],"class_list":["post-132","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-image-processing","category-processing","category-tutorial"],"_links":{"self":[{"href":"https:\/\/www.sululab.com\/blog\/wp-json\/wp\/v2\/posts\/132","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sululab.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sululab.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sululab.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sululab.com\/blog\/wp-json\/wp\/v2\/comments?post=132"}],"version-history":[{"count":1,"href":"https:\/\/www.sululab.com\/blog\/wp-json\/wp\/v2\/posts\/132\/revisions"}],"predecessor-version":[{"id":1133,"href":"https:\/\/www.sululab.com\/blog\/wp-json\/wp\/v2\/posts\/132\/revisions\/1133"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.sululab.com\/blog\/wp-json\/wp\/v2\/media\/330"}],"wp:attachment":[{"href":"https:\/\/www.sululab.com\/blog\/wp-json\/wp\/v2\/media?parent=132"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sululab.com\/blog\/wp-json\/wp\/v2\/categories?post=132"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sululab.com\/blog\/wp-json\/wp\/v2\/tags?post=132"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}