<?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>deadlime &#187; mintafelismerés</title>
	<atom:link href="http://deadlime.hu/tag/mintafelismeres/feed/" rel="self" type="application/rss+xml" />
	<link>http://deadlime.hu</link>
	<description>unexpected terminator</description>
	<lastBuildDate>Mon, 14 May 2012 20:38:51 +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>A hármasok nyomában</title>
		<link>http://deadlime.hu/2007/01/24/a-harmasok-nyomaban/</link>
		<comments>http://deadlime.hu/2007/01/24/a-harmasok-nyomaban/#comments</comments>
		<pubDate>Tue, 23 Jan 2007 23:23:54 +0000</pubDate>
		<dc:creator>Nagy Krisztián</dc:creator>
				<category><![CDATA[nincs kategória]]></category>
		<category><![CDATA[képfeldolgozás]]></category>
		<category><![CDATA[mintafelismerés]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://deadlime.hu/2007/01/24/a-harmasok-nyomaban/</guid>
		<description><![CDATA[Kezdek beállni erre a havi egy bejegyzésre. Ez nem feltétlen egy jó dolog, de legalább valami rendszeresség már van benne. Azért nem ártana letornászni ezt legalább heti egyre, de addig is, jöjjön a "januári bejegyzés". Remélem sikerül valami érdekeset hoznom az év első deadlime-os bejegyzésével. A téma ismét a képekkel és a GD könyvtárral lesz [...]]]></description>
			<content:encoded><![CDATA[<p>Kezdek beállni erre a havi egy bejegyzésre. Ez nem feltétlen egy jó dolog, de legalább valami rendszeresség már van benne. Azért nem ártana letornászni ezt legalább heti egyre, de addig is, jöjjön a "januári bejegyzés". Remélem sikerül valami érdekeset hoznom az év első deadlime-os bejegyzésével.</p>

<p>A téma ismét a képekkel és a GD könyvtárral lesz kapcsolatos, bár a régi adatrejtéses bitbűvészkedésnél kicsit tovább merészkedünk a képfeldolgozás és a mintafelismerés irányába. A feladat roppant egyszerű lesz, egy adott képen szeretnénk megtalálni - lehetőleg - az összes hármas számot (azért pont a hármast, mert az kellően hasonlít a nagy b betűre, valamint a nyolcas számra is, így nehezítve a dolgunkat). Ehhez adott <a href="http://deadlime.hu/wp-content/uploads/2007/01/image.gif">maga a kép</a>, amin keresünk (egy kis zajjal nehezítettem a keresést, különben elég egyszerű lenne...), valamint <a href="http://deadlime.hu/wp-content/uploads/2007/01/template.gif">egy minta</a>, hogy mit is szeretnénk megtalálni. Vessük is rögtön bele magunkat a hogyanokba.</p>

<p>Több fajta módszer is létezik annak megállapítására, hogy egy kép bizonyos része és egy minta mennyire hasonlít egymásra. A módszerek lényegében abból állnak, hogy vesszük a mintát, ráillesztjük a kép bal felső sarkára, egy megfelelő képlet segítségével kiszámítjuk, hogy ott mennyire illeszkedik (vagy épp nem illeszkedik), az értéket eltároljuk, majd a mintát eltoljuk egy pixellel balra. Ha elértünk a sor végére, akkor egy pixellel lejjebb toljuk a mintát és visszaugrunk a sor elejére. Innentől már csak az adott képletben fogunk eltérni. Nézzük is az elsőt, ami az <acronym title="Sum of Square Differences">SSD</acronym> nevet kapta, és elsőre talán egy picit ijesztőnek tűnhet:</p>

<div><img id="image95" src="http://deadlime.hu/wp-content/uploads/2007/01/ssd.gif" alt="SSD"/></div>

<p>A képletben látható W a minta lokális koordinátáinak halmaza (tehát függetlenek attól, hogy a képen belül hol járunk éppen), az F pedig a kép koordinátáinak halmaza. Az adatrejtéses bejegyzés óta megtartottam azt a jó szokásomat, hogy továbbra is szürkeárnyalatos képekkel dolgozok, tehát az f és a w függvények olyanok, hogy a kép- illetve a minta koordinátihoz rendelnek egy 0 és 255 közötti számot. Jöjjön egy példa is, hogy egy kicsit leegyszerűsített helyzetben ez hogyan is működik:</p>

<div><img id="image97" src="http://deadlime.hu/wp-content/uploads/2007/01/ssd_pelda.gif" alt="SSD példa"/></div>

<p>A szám, amit a végén megkapunk az "Eredmény" részben lévő pixelek értékeinek összege, azaz nyolc lesz. Mint az látszik, ez a módszer azt adja meg, hogy a képnek ez a része mennyire különbözik a mintától, vagyis minél közelebb van a visszatérési érték a nullához, annál jobb nekünk. A teszteléseim során az SSD elég szép eredményeket ért el a zaj nélküli, fekete-fehér képek esetén (gyakorlatilag az összes hármast megtalálta, mivel egy ilyen mintához érve a képlet visszatérési értéke nulla volt), de a zajjal nem tudott mit kezdeni.</p>

<p>Így jött a képbe az <acronym title="Sum of Square Differences (shift-corrected)">SSD<sub>SC</sub></acronym>, amivel a kép és a minta közti intenzitás-különbséget próbáljuk korrigálni. Az új képlet lényegét muszáj leszek szavakban elmagyarázni, mivel szélességében meghaladja a design befogadóképességét, tehát: lényegében az f(x+x',y+y') függvényértékből levonunk egy f<sub>2</sub>(x,y) függvényértéket és a w(x',y') értékből is egy w<sub>2</sub> értéket. Majd még az így kapott értékeket is kivonjuk egymásból és az egészet négyzetre emeljük (mint azt tettük a sima SSD esetében is). Már csak azt kellene tudni, hogy ez az f<sub>2</sub> és a w<sub>2</sub> hogyan is jön ki. Az f<sub>2</sub> a kép minta által borított pixeleinek átlagértéke (az összes pixel értékének az összege osztva a pixelek számával), a w<sub>2</sub> pedig a minta pixeleinek az átlagértéke (hasonlóan számolva). Tulajdonképpen azt fejezik ki, hogy a minta és a minta által fedett képterület mennyire sötétek illetve világosak.<br/>
Magam is meglepődtem a módszer eredményességén, megfelelő hibahatár mellett az összes hármast sikerült megtalálnia a zajos képen (hibahatár alatt értem azt, hogy mekkora különbséget engedek meg a kép adott része és a minta között, hogy az még találatnak számítson).</p>

<p>Így a végére pedig jöjjön egy PHP-s megvalósítás az SSD<sub>SC</sub>-ra:</p>

<pre class="code prettyprint lang-php">$image = imagecreatefromgif('image.gif');
$template = imagecreatefromgif('template.gif');

$image_width = imagesx($image);
$image_height = imagesy($image);

$template_width = imagesx($template);
$template_height = imagesy($template);

for ($x=0;$x&lt;$image_width;++$x) {
	for ($y=0;$y&lt;$image_height;++$y) {
		$tmp = imagecolorsforindex($image, imagecolorat($image, $x, $y));
		$image_data[$x][$y] = $tmp['red'];
	}
}

$template_average = 0;
for ($x=0;$x&lt;$template_width;++$x) {
	for ($y=0;$y&lt;$template_height;++$y) {
		$tmp = imagecolorsforindex($template, imagecolorat($template, $x, $y));
		$template_data[$x][$y] = $tmp['red'];
		$template_average += $tmp['red'];
	}
}
$template_average = $template_average / ($template_width * $template_height);

imagedestroy($template);

$hibahatar = 100000;

$min = array();
$min_values = array();</pre>

<p>Első körben még semmi komoly, betöltöm a két képet, meghatározom a méretüket, az összes pixelük színét eltárolom egy-egy tömbben (az $image_data és a $template_data tömbök) és meghatározom a w<sub>2</sub> értékét (ez lenne a $template_average, amit ugyebár elég egyszer kiszámolni, mivel nem függ a minta képen való elhelyezkedésétől). Most jön a neheze, a főciklus(ok):</p>

<pre class="code prettyprint lang-php">for ($image_x=0;$image_x&lt;($image_width - $template_width);++$image_x) {
	for ($image_y=0;$image_y&lt;($image_height - $template_height);++$image_y) {

		$SSD[$image_x][$image_y] = 0;

		$image_average = 0;
		for ($template_x=0;$template_x&lt;$template_width;++$template_x) {
			for ($template_y=0;$template_y&lt;$template_height;++$template_y) {
				$image_average += $image_data[($image_x + $template_x)][($image_y + $template_y)];
			}
		}
		$image_average = $image_average / ($template_width * $template_height);

		for ($template_x=0;$template_x&lt;$template_width;++$template_x) {
			for ($template_y=0;$template_y&lt;$template_height;++$template_y) {
				$SSD[$image_x][$image_y] += pow((
					($image_data[($image_x + $template_x)][($image_y + $template_y)] - $image_average) -
					($template_data[$template_x][$template_y] - $template_average)
				), 2);
			}
		}
	}

	$min[$image_x] = min($SSD[$image_x]);
	foreach ($SSD[$image_x] as $k =&gt; $v) {
		if ($v &lt;= ($min[$image_x] + $hibahatar)) {
			$min_values[$image_x][] = $k;
		}
	}
}</pre>

<p>Mint az észrevehető, jó pár ciklus van egymásba ágyazva, ezért nem éppen várható el a scripttől, hogy másodpercek alatt lefusson, főleg ha nem éppen kis képekről van szó. Végül pedig bejelöljük a találatokat az eredeti képen egy zöld négyzettel és elmentjük az új képet:</p>

<pre class="code prettyprint lang-php">$green = imagecolorallocate($image, 0, 255, 0);

$the_min = min($min);
foreach ($min as $k =&gt; $v) {
	if ($v &lt;= ($the_min + $hibahatar)) {
		foreach ($min_values[$k] as $k2 =&gt; $v2) {
			imagerectangle($image, $k-1, $v2-1, $k+$template_width, $v2+$template_height, $green);
		}
	}
}

imagegif($image, 'image_new.gif');

imagedestroy($image);</pre>

<p>A végére pedig jöjjön egy kép, hogy az SSD<sub>SC</sub> nálam milyen eredménnyel járt a példakódban is használt 100000-es hibahatárt használva:</p>

<div style="text-align: center;"><img id="image98" src="http://deadlime.hu/wp-content/uploads/2007/01/ssdsc_100000.gif" alt="ssdsc_100000.gif" /></div>

<p>Remélem mindenkinek sikerült felkeltenem az érdeklődését. Igény esetén szót ejthetek még esetleg a CC, NCC, MNCC képletekről (ezek az SSD-vel ellentétben a hasonlóságok mérésére szolgálnak). Addig is, akit komolyabban is érdekel a téma, annak tudom ajánlani <a href="http://visual.ipan.sztaki.hu/">ezt a weboldalt</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://deadlime.hu/2007/01/24/a-harmasok-nyomaban/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

