<?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>GrgrDvrt &#187; optimisation</title>
	<atom:link href="http://grgrdvrt.com/blog/tag/optimisation/feed/" rel="self" type="application/rss+xml" />
	<link>http://grgrdvrt.com/blog</link>
	<description>Un blog utilisant WordPress</description>
	<lastBuildDate>Tue, 10 Jan 2012 09:04:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Median Cut</title>
		<link>http://grgrdvrt.com/blog/332/median-cut/</link>
		<comments>http://grgrdvrt.com/blog/332/median-cut/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 16:45:31 +0000</pubDate>
		<dc:creator>Grgrdvrt</dc:creator>
				<category><![CDATA[Flash]]></category>
		<category><![CDATA[bitmapData]]></category>
		<category><![CDATA[couleur]]></category>
		<category><![CDATA[filtre]]></category>
		<category><![CDATA[optimisation]]></category>

		<guid isPermaLink="false">http://grgrdvrt.com/blog/?p=332</guid>
		<description><![CDATA[Le median cut filter est un filtre qui me paraissait super intéressant. Et puis en fait non. Enfin si, mais pas comme je l'aurai imaginé au début.]]></description>
			<content:encoded><![CDATA[<p>Au début de l&#8217;histoire, le truc qui m&#8217;a fait rêver c&#8217;est l&#8217;outil <a href="http://www.inthemod.com/inthemod.html">in the mod</a> de <a href="http://blog.drwoohoo.com/">Dr Woohoo</a> qui permet de récupérer une palette de couleurs à partir d&#8217;une image.<br/>
Alors moi tout naïf je me dis &#8220;ouai c&#8217;est facile, c&#8217;est tout comme réduire le nombre de couleurs de l&#8217;image&#8221; et je repense à nicoptère qui a fait <a href="http://en.nicoptere.net/?p=8">un truc qui y ressemble.</a><br/>
Sauf qu&#8217;en fait ce que je veux (va savoir pourquoi) c&#8217;est récupérer un nombre précis de couleurs. Alors j&#8217;en parle avec Nicoptère et là il me dit &#8220;ah mais ça a rien à voir (pov&#8217; nul), toi c&#8217;est une posterisation que tu veux faire! &#8220;. Ce à quoi google me répond &#8220;la posterisation <a href="http://www.adobe.com/designcenter/photoshop/articles/phs8posteriz.html">c&#8217;est ça</a>&#8220;. Ah bein oui, c&#8217;est un beau chien, mais là c&#8217;est le contraire de ce que je veux.<br/>
C&#8217;est quand même un bon début parcequ&#8217;en fouinant dans cette direction je découvre le <a href="http://web.cs.wpi.edu/~matt/courses/cs563/talks/color_quant/CQmediancut.html">median cut filter</a> et même comment <a href="http://www.leptonica.com/papers/mediancut.pdf">améliorer l&#8217;algorithme</a>. Bien sûr tout celà n&#8217;est pas à confondre avec avec l&#8217;autrement plus compliqué <a href="http://en.nicoptere.net/?p=444">mean shift filter</a>.<br/>
Bon, trop bien! Cette fois c&#8217;est le bon.</p><br/><br/>

<p>Là je fais une pause dans l&#8217;histoire, juste pour dire que si tu veux obtenir des belles couleurs d&#8217;une belle image, tu peux tout de suite aller chez soulwire voir ces articles:
<a href="http://blog.soulwire.co.uk/flash/actionscript-3/extract-average-colours-from-bitmapdata">couleurs moyennes</a> et <a href="http://blog.soulwire.co.uk/flash/actionscript-3/colourutils-bitmapdata-extract-colour-palette">extraire une palette de couleurs</a>, c&#8217;est plus simple et ça marche mieux.<br/>
Par contre tu vas rater la partie intéressante de l&#8217;histoire.</p><br/><br/>

<p>Pour en revenir au median cut filter, si tu te disais &#8220;Chouette, un filtre! on va sortir PixelBender&#8221; tu te trompes, ça marchera pas. C&#8217;est pas comme le BlurFilter ou ColorMatrixFilter, qui traitent chaque pixel pour les redéfinir en fonction de leurs voisins ou de paramètres quelconques. Là c&#8217;est l&#8217;espace colorimétrique de l&#8217;image qu&#8217;on va tripoter.</p><br/><br/>
<p><img src="/storage/332/color_space.jpg"/>L&#8217;espace colorimétrique c&#8217;est ce que tu vois juste à côté, un cube dans lequel chaque point est une couleur déterminée par sa position sur les axes R, G, B.</p><br/>
<p><img src="/storage/332/vlaminck.jpg"/>Maurice de Vlaminck a peint Les arbres rouges en 1906. C&#8217;est une huile sur toile de 65 x 81 cm et tu peux le voir au 5ème étage du Centre Pompidou.<br/>
Là (hérésie!) je l&#8217;ai recadré pour qu&#8217;il rentre dans la grille de l&#8217;article.</p>
<p><img src="/storage/332/vlaminck_color_space.jpg"/>Ici c&#8217;est toujours le Vlaminck mais représenté dans l&#8217;espace colorimétrique. Cette fois il n&#8217;est pas recadré. Si tu veux, <a href="/storage/332/color_space.rar">voilà les sources</a> pour que tu puisse faire la même chose avec tes images. Les résultats sont très différents selon les images, c&#8217;est assez intréssant</p>

<p><img src="/storage/332/one_box.jpg"/>On commence par mettre le tableau dans une boite. En vrai une boite ce sera juste une liste de pixels.</p>
<p><img src="/storage/332/two_boxes.jpg"/>Ensuite on regarde quel est le côté le plus long. Pour ça il suffit de prendre les valeurs extrèmes de rouge, vert et bleu dans la liste de pixels. On va alors trier la liste selon leur valeur de rouge si par exemple c&#8217;est dans le vert qu&#8217;on a le plus d&#8217;amplitude. Il n&#8217;y a plus qu&#8217;à diviser notre liste en deux parts égales de façon à obtenir deux boites contenant le même nombre de pixels.</p>
<p>On recommence la dernière étape avec la boite qui a le plus long côté jusqu&#8217;à avoir autant de boites qu&#8217;on veut de couleurs. On obtient la palette en récupérant la couleur moyenne de chaque boite. Après pour reconstituer l&#8217;image il faudrait faire une posterisation. Moi je me contente d&#8217;attribuer aux pixels la couleur de la boite où ils sont, ça revient presque au même.</p><br/><br/>

<p>Voilà <a href="/storage/332/median_cut_filter.rar">les sources du truc</a>.<br/>
Et voilà des images reconstituées avec 2, 4, 8 et 32 couleurs et les palettes correspondantes</p>
<p><img src="/storage/332/vlaminck_2.jpg"><img style="margin-right:0px;" src="/storage/332/vlaminck_4.jpg"><img src="/storage/332/vlaminck_8.jpg"><img style="margin-right:0px;" src="/storage/332/vlaminck_32.jpg"></p>
<p>Le fauvisme prend un sérieux coup.<br/>
À moins de 20 couleurs les palettes sont loin de ce qu&#8217;on pourrait attendre.</p>

<p>Tu es déçu et je te comprends. En lot de consolation, voilà un bonus cool sur le tri des tableaux</p>
<p>On a vu que l&#8217;algorithme nécessite que les pixels d&#8217;une boite soient triés lors de la division de celle-ci.<br/>
Trier un Vector c&#8217;est simple avec la methode sort(). Ça prend en paramètre une fonction de notre choix c qui est top pour trier des éléments comme on veux. L&#8217;inconvénient c&#8217;est que c&#8217;est lent. Trop lent pour trier tous les pixels d&#8217;une image.</p><br/><br/>

Voilà le test de base avec un Vector.<int>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">//nombre de valeurs à trier</span>
<span style="color: #000000; font-weight: bold;">var</span> n:<span style="color: #0066CC;">int</span> = <span style="color: #cc66cc;">20000</span>;
<span style="color: #808080; font-style: italic;">//Vector contenant les valeurs à trier</span>
<span style="color: #000000; font-weight: bold;">var</span> values:Vector.<span style="color: #66cc66;">&lt;</span>int<span style="color: #66cc66;">&gt;</span> = <span style="color: #000000; font-weight: bold;">new</span> Vector.<span style="color: #66cc66;">&lt;</span>int<span style="color: #66cc66;">&gt;</span><span style="color: #66cc66;">&#40;</span>n, <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #808080; font-style: italic;">//valeur maximale contenue dans le Vector (minimum 0)</span>
<span style="color: #000000; font-weight: bold;">var</span> valMax:<span style="color: #0066CC;">int</span> = 0xFF;
<span style="color: #808080; font-style: italic;">//remplissage du Vector avec des valeurs aléatoires</span>
<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">var</span> i:<span style="color: #0066CC;">int</span> = <span style="color: #cc66cc;">0</span>; i<span style="color: #66cc66;">&lt;</span> n; i++<span style="color: #66cc66;">&#41;</span>values<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> = <span style="color: #0066CC;">Math</span>.<span style="color: #0066CC;">random</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> valMax;
<span style="color: #000000; font-weight: bold;">var</span> t:<span style="color: #0066CC;">int</span> = <span style="color: #0066CC;">getTimer</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #808080; font-style: italic;">//tri</span>
values.<span style="color: #0066CC;">sort</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>v1:<span style="color: #0066CC;">int</span>, v2:<span style="color: #0066CC;">int</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span><span style="color: #b1b100;">return</span> v1 - v2;<span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0066CC;">trace</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">getTimer</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> - t<span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>



<p>chez moi j&#8217;ai :<br/> 
72 ms pour 10 000 éléments<br/>
3 900 ms pour 100 000 éléments<br/>
14 500 ms pour 200 000 éléments<br/>
après on dépasse les 15 secondes et ça plante.<br/>
Dommage, une image de 500&#215;500 ça fait déjà 250 000 pixels.</p><br/><br/>

<p>Heureusement les algorithmes de tri sont très nombreux et le <a href="http://en.wikipedia.org/wiki/Counting_sort">counting sort</a> m&#8217;a paru sympa.<br/>
Si on reprend le test de tout à l&#8217;heure</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> countingSort<span style="color: #66cc66;">&#40;</span>a:Vector.<span style="color: #66cc66;">&lt;</span>int<span style="color: #66cc66;">&gt;</span>, k:<span style="color: #0066CC;">int</span><span style="color: #66cc66;">&#41;</span>:Vector.<span style="color: #66cc66;">&lt;</span>int<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">var</span> n:<span style="color: #0066CC;">int</span> = a.<span style="color: #0066CC;">length</span>;
	<span style="color: #000000; font-weight: bold;">var</span> b:Vector.<span style="color: #66cc66;">&lt;</span>int<span style="color: #66cc66;">&gt;</span> = <span style="color: #000000; font-weight: bold;">new</span> Vector.<span style="color: #66cc66;">&lt;</span>int<span style="color: #66cc66;">&gt;</span><span style="color: #66cc66;">&#40;</span>n, <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span>;
	<span style="color: #000000; font-weight: bold;">var</span> c:Vector.<span style="color: #66cc66;">&lt;</span>int<span style="color: #66cc66;">&gt;</span> = <span style="color: #000000; font-weight: bold;">new</span> Vector.<span style="color: #66cc66;">&lt;</span>int<span style="color: #66cc66;">&gt;</span><span style="color: #66cc66;">&#40;</span>k, <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span>;
	<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">var</span> i:<span style="color: #0066CC;">int</span> = <span style="color: #cc66cc;">0</span>; i<span style="color: #66cc66;">&lt;</span> n; i++<span style="color: #66cc66;">&#41;</span>c<span style="color: #66cc66;">&#91;</span>a<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span> = c<span style="color: #66cc66;">&#91;</span>a<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span> + <span style="color: #cc66cc;">1</span>;
	<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span>i = <span style="color: #cc66cc;">1</span>; i <span style="color: #66cc66;">&lt;</span> k; i++<span style="color: #66cc66;">&#41;</span>c<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> = c<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> + c<span style="color: #66cc66;">&#91;</span>i - <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#93;</span>;
	<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span>i = n - <span style="color: #cc66cc;">1</span>; i <span style="color: #66cc66;">&gt;</span>= <span style="color: #cc66cc;">0</span>; i--<span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		b<span style="color: #66cc66;">&#91;</span>c<span style="color: #66cc66;">&#91;</span>a<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>-<span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#93;</span> = a<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>;
		c<span style="color: #66cc66;">&#91;</span>a<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span> = c<span style="color: #66cc66;">&#91;</span>a<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span> - <span style="color: #cc66cc;">1</span>;
	<span style="color: #66cc66;">&#125;</span>
	<span style="color: #b1b100;">return</span> b;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">var</span> n:<span style="color: #0066CC;">int</span> = <span style="color: #cc66cc;">100000</span>;
<span style="color: #000000; font-weight: bold;">var</span> values:Vector.<span style="color: #66cc66;">&lt;</span>int<span style="color: #66cc66;">&gt;</span> = <span style="color: #000000; font-weight: bold;">new</span> Vector.<span style="color: #66cc66;">&lt;</span>int<span style="color: #66cc66;">&gt;</span><span style="color: #66cc66;">&#40;</span>n, <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">var</span> valMax:<span style="color: #0066CC;">int</span> = 0xFF;
<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">var</span> i:<span style="color: #0066CC;">int</span> = <span style="color: #cc66cc;">0</span>; i<span style="color: #66cc66;">&lt;</span> n; i++<span style="color: #66cc66;">&#41;</span> values<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> = <span style="color: #0066CC;">Math</span>.<span style="color: #0066CC;">random</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> valMax;
&nbsp;
<span style="color: #000000; font-weight: bold;">var</span> t:<span style="color: #0066CC;">int</span> = <span style="color: #0066CC;">getTimer</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
values = countingSort<span style="color: #66cc66;">&#40;</span>values, valMax + <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0066CC;">trace</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">getTimer</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> - t<span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>



<p>2ms pour 10 000 éléments<br/>
17ms pour 100 000 éléments<br/>
1600ms pour 10 000 000 éléments<br/>
Bon, en gros pour 50 fois plus d&#8217;éléments ça met à peu près 10 fois moins de temps. Pas mal non?</p><br/><br/>

<p>Bien sûr comme tu ne crois pas à la magie, tu sais qu&#8217;il y a des inconvénients.<br/>
En fait là ça marche bien parceque les valeurs à trier sont des entiers compris entre 0 et 255<br/>
Avec des nombre décimaux ça ne marcherai pas. Et avec des nombres négatifs il faudrait adapter un peu.<br/>
Avec des valeurs issues d&#8217;un large interval c&#8217;est la mémoire qui prendrait un coup.<br/>
Et puis il faut réécrire la fonction pour chaque type de Vector<br/>
<a href="http://en.wikipedia.org/wiki/Quicksort">Le quickSort</a> est plus pratique pour ces cas là, mais peut-être un peu moins rapide dans le cas des canaux rgb.
</p><br/><br/>
<p>La leçon c&#8217;est que le median cut filter ça sert peut-être à rien mais au moins maintenant je sais mieux trier mes objets</p>]]></content:encoded>
			<wfw:commentRss>http://grgrdvrt.com/blog/332/median-cut/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

