[php] Kleurenzoeker

Pagina: 1
Acties:
  • 103 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Farmerpeter
  • Registratie: Maart 2005
  • Laatst online: 02-12-2024

Farmerpeter

`'t kan verkeren

Topicstarter
Met een webcam moet het mogelijk zijn om beelden te herkennen, om dit zelf voor elkaar te krijgen, ben ik begonnen met een PHP scriptje wat een plaatje analyseert.

Hierbij maak ik gebruik van php5.1 en de GD library, de kleur die ik in mijn voorbeeld zou willen herkennen is geel mijn object voldoet aan de volgende RGB waarden

R>210
G>210
190<B>150

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
     $start_x = 1;
     $start_y = 1;
     $im = ImageCreateFromJPeG("C:\Program Files\Pryme\Log\colorrecog.jpg");
     $rgb = ImageColorAt($im,$start_x,$start_y);
     $r = ($rgb >> 16) & 0xFF;
     $g = ($rgb >> 8) & 0xFF;
     $b = $rgb & 0xFF;



while ($start_x<320);
 {
 echo "$rgb,$start_x++";
 }


Hierna ben ik bezig met een scriptje, wat eerst elke rij afzoekt ($start_x++) dus x elke verhogen naar een kleur die aan de voorwaarden voldoet, maar zelfs het simpel voorbeeld met een kleurvoorwaarde lukt mij al niet :'( als de kleur gevonden is moet er dus een berichtje worden gegeven en opgeslagen maar dat lukt wel

PHP:
1
2
3
4
5
6
7
8
9
10
function search_color ($findcol) 
{
if ($r>$rgeel)
{
echo "kleurvoorwaarde voor rood voldaan R=$r" ;
[s][/s]}
else {$start_x++ 
return $findcol;
}
}


Ik hoop dat iemand deze loop functie wel werken kan maken zonder de function om het IF verhaal krijg ik de $start_x op 101, maar er moet natuurlijk doorgegaan worden, en dat lukt mij juist niet.

AM2 X2 3600 @ 3.0Ghz Asrock AliveNF4G-DVI OCZ pc5300


Acties:
  • 0 Henk 'm!

  • semicolon
  • Registratie: Mei 2004
  • Niet online
Farmerpeter schreef op woensdag 09 augustus 2006 @ 20:42:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
     $start_x = 1;
     $start_y = 1;
     $im = ImageCreateFromJPeG("C:\Program Files\Pryme\Log\colorrecog.jpg");
     $rgb = ImageColorAt($im,$start_x,$start_y);
     $r = ($rgb >> 16) & 0xFF;
     $g = ($rgb >> 8) & 0xFF;
     $b = $rgb & 0xFF;



while ($start_x<320);
 {
 echo "$rgb,$start_x++";
 }
Je moet in die while loop wel elke keer opnieuw imagecolorat uitvoeren om weer de nieuwe RGB waarde te achterhalen. Nu echo je gewoon de hele tijd hetzelfde (op start_x na).

Ik heb zelf ook een keer zoiets gemaakt om te bestuderen of een plaatje licht of donker is, dus het is zeker mogelijk.

Ah je hebt de code rechtstreeks van PHP gepakt op de while loop na. Je moet die losse $r,$b,$g trouwens echo-en en niet de $rgb, want die bevat een index van de kleur.
Returns the index of the color of the pixel at the specified location in the image specified by image.
Oja en nog een dingetje, je moet niet vergeten dat je nu alleen de EERSTE kolom pixels elke rij afgaat.

Hoe ik het deed was:

code:
1
2
3
4
5
- loop aantal pixels hoogte
 - loop aantal pixels breedte
  - sla RGB gegevens elk apart op.
 - /loop
- /loop


Van elke pixel heb je nu de rgb gegevens, en toen ging ik het gemiddelde berekenen van R, G en natuurlijk B. Natuurlijk heb ik uiteindelijk nog wat truukjes toegepast om sneller te scannen want letterlijk elke pixel is natuurlijk overkill, en misschien zijn er wel betere manieren voor, maar voor mij werkte het op het moment prima op die manier.

[ Voor 47% gewijzigd door semicolon op 09-08-2006 20:59 ]

:D/-<


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Trouwens nog een dingetje om mee te nemen is ook te kijken wat de omliggende waarden zijn, want 1 pixel geel in een voor de rest zwart vlak is waarschijnlijk een webcam-error en niet wat je zoekt... Helemaal met foto's is dit leuk...

Wat ik ooit eens heb gedaan is :
Kies eerst een ruime range ( toon 64 kleuren en laat de persoon de meest erop lijkende kleur selecteren )
Kies dan ook een precieze range / plaatje
eerst steekproeven nemen ( om de 10 / 25 pixels ofzo hing af van de resolutie van de plaatjes ) om te zien of het een donker / licht plaatje is.
Dan al naargelang de steekproeven er een bepaald pallet van 256 ( had er een aantal ) overheen gooien zodat losse pixels verdwenen.
Dan het hele plaatje resizen naar beneden wederom zodat kleine onderdelen verdwenen.
In dit groffe kleurenplaatje elke pixel onderzoeken of het niet ergens binnen de ruim gezochte range lag, en over welk oppervlakte we dan praten.
Gevonden oppervlakte terugrekenen naar waar het in het originele plaatje ligt.
Dan in het originele plaatje ( of een minder-kleuren exemplaar ) in de net teruggerekende oppervlaktes zoeken naar het precieze patroon.

Lijkt veel werk, is het ook best wel om goed op te zetten, maar je moet wat als je met 4MP plaatjes wilt werken en de snelheid erin wilt houden.

Maar bottomline, verlaag het aantal kleuren ( of vind je het echt belangrijk dat op 16 miljoen kleuren jouw geeldefinitie net 1 waarde hoger is dan al het geel wat er in het plaatje zit ??? ) en verklein het plaatje ( want 1 pixel terugvinden op een 4MP plaatje is niet echt relevant en behoorlijk arbeidsintensief voor je pc )

Acties:
  • 0 Henk 'm!

  • semicolon
  • Registratie: Mei 2004
  • Niet online
Post hierboven heeft gelijk, maar ik kan het wel begrijpen als je eerst ff simpel iets wilt opzetten om het daarna te optimalizeren, je moet natuurlijk eerst weten WAT je doet voor je het beter doet.

Om het even over je vergelijkingen te hebben...
R > 210
G > 210
190 <B> 150

Op zo'n manier vind je geel niet. RGB voor 'geel' is 255,255,0, en daar matched die conditie niet aan (om maar een voorbeeld te noemen.)

[ Voor 4% gewijzigd door semicolon op 09-08-2006 21:46 ]

:D/-<


Acties:
  • 0 Henk 'm!

  • Farmerpeter
  • Registratie: Maart 2005
  • Laatst online: 02-12-2024

Farmerpeter

`'t kan verkeren

Topicstarter
Bedankt voor de hulp met de loop functie, heb het gebeuren nu wel werkend.

De opmerkingen van Gomez voor optimaliseren en sneller maken komen eigenlijk later pas aan de orde, eerst een werkend systeem krijgen, snelheid komt later pas maar zal uiteindelijk wel belangrijk zijn omdat ik een snelle reactie wil hebben.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  do {
      $start_x++;
      $rgb = ImageColorAt($im,$start_x,$start_y);
     $r = ($rgb >> 16) & 0xFF;
     $g = ($rgb >> 8) & 0xFF;
     $b = $rgb & 0xFF;
     if ($start_x<238)
        {
          if ($r>225)
          {
             if ($g>225)
             {
              if ($b<190)
              {
              echo "<hr> X=$start_x Y=$start_y R=$r G=$g B=$b";
              //save coordinaten
              }
             }
          }
       
       
        }
        else 
          {
            $start_y++;
            $start_x=1;
          } 
    }
    while ($start_y<239 );


Deze code doorzoekt m'n hele image eerst rijen doorlopen van links naar rechts, daarna links met rij erboven beginnen, en alleen waarden uitputten die voor mij interresant zijn.

PHP valt me echt mee, naast vroeger een beetje met HTML rommelen heb ik nooit zo veel aan programmeren gedaan, maar met php.net kom je een heel eind de taal is lekker makkelijk en heeft een verschrikkelijke berg mogelijkheden, heb naast dit script ook al een ODBC connectie met een simpele access database om wat zut in op te slaan. ook handig is de functie die alvast een indicatie geeft wat je waarschijnlijk fout hebt getypt, als je typefouten maakt.

AM2 X2 3600 @ 3.0Ghz Asrock AliveNF4G-DVI OCZ pc5300


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Je code werkt nu, maar de leesbaarheid kan misschien iets beter. Omdat je precies weet hoe je x en y laat lopen, kun je denk ik beter for-loops gebruiken. Daarnaast kun je om meerdere dingen in één if-statement te laten matchen de logical and (&&) gebruiken.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
  for($start_x = 1; $start_x < 238; $start_x++ ) {
    for($start_y = 1; $start_y < 239; $start_y++ ) {
      $rgb = ImageColorAt($im,$start_x,$start_y);
      $r = ($rgb >> 16) & 0xFF;
      $g = ($rgb >> 8) & 0xFF;
      $b = $rgb & 0xFF;
      if($r>225 && $g>225 && $b<190) {
        echo "<hr> X=$start_x Y=$start_y R=$r G=$g B=$b";
        //save coordinaten
      }
    }
  }

[ Voor 1% gewijzigd door GlowMouse op 13-08-2006 12:58 . Reden: indention beter; typo ($r>255 ipv $r>225) ]


Acties:
  • 0 Henk 'm!

  • Farmerpeter
  • Registratie: Maart 2005
  • Laatst online: 02-12-2024

Farmerpeter

`'t kan verkeren

Topicstarter
Bedankt voor je tip ziet inderdaad er een stuk beter uit.

over dat if && gebeuren, is het niet sneller om het voorwaarde voor voorwaarde te doen, zodat als de eerste IF al False geeft de rest niet uitgerekend hoeft te worden?

AM2 X2 3600 @ 3.0Ghz Asrock AliveNF4G-DVI OCZ pc5300


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Farmerpeter schreef op zaterdag 12 augustus 2006 @ 23:47:
over dat if && gebeuren, is het niet sneller om het voorwaarde voor voorwaarde te doen, zodat als de eerste IF al False geeft de rest niet uitgerekend hoeft te worden?
PHP voert intern optimalisaties uit. Wanneer de eerste niet waar is, wordt de tweede al niet meer gecheckt meen ik. Je kunt daarom de minst voorkomende vooraan zetten. Daarnaast lijkt me de functie ImageColorAt in vergelijking met een enkele groter-dan check zoveel langzamer, dat je je over zo'n if niet meer druk hoeft te maken.
Hier wat code ter illustratie:
PHP:
1
2
3
4
5
6
7
8
9
10
11
if(a() && b()) {
    echo 'kan niet waar zijn!';
}

function a() {
  return false;
}
function b() {
  echo 'baah!';
  return true;
}

a() geeft direct false, dus wordt b() niet meer uitgevoerd. Verwissel je in het if-statement a() en b(), zie je wel dat b wordt uitgevoerd (getest op PHP 5.1.2).

[ Voor 22% gewijzigd door GlowMouse op 12-08-2006 23:56 ]


Acties:
  • 0 Henk 'm!

  • BalusC
  • Registratie: Oktober 2000
  • Niet online

BalusC

Carpe diem

GlowMouse schreef op zaterdag 12 augustus 2006 @ 23:52:
PHP voert intern optimalisaties uit. Wanneer de eerste niet waar is, wordt de tweede al niet meer gecheckt meen ik.
Dit worden conditionele expressies genoemd: && en || :) Niks bijzonders. Wanneer je & en | gebruikt ipv && en || dan worden gewoon de béide voorwaarden getest.

Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

BalusC schreef op zondag 13 augustus 2006 @ 08:37:
[...]
Dit worden conditionele expressies genoemd: && en || :) Niks bijzonders. Wanneer je & en | gebruikt ipv && en || dan worden gewoon de béide voorwaarden getest.
Nee, && en || maken deel uit van de verzameling binaire conditionele operatoren. Wat je ermee bakt zijn boolse expressies :P In het bijzonder zijn de && en || respectievelijk de short-circuited AND en short-circuited OR, ook wel lazy AND en lazy OR genoemd. Bij de && houdt dat in dat wanneer de linkeroperand naar false evalueert, dat daarmee de rechter operand niet meer ge-evalueerd wordt, omdat de expressie bij voorbaat in z'n geheel niet naar een true kan evalueren, en dus false wordt. Bij de || houdt dat analoog in dat wanneer de linkeroperand naar true evalueert, dat de rechter operand niet meer ge-evalueerd wordt (een don't care voor jullie Karnaugh liefhebbers), omdat de hele expressie bij voorbaat nu al naar true evalueert.
De & en | behoren tot de verzameling van bitwise operatoren, waarbij het van belang is dat zowel linker als rechteroperand ge-evalueerd worden, voor b.v. bitmask operaties. Er zit dus voor de leken wel degelijk verschil tussen deze twee soorten operatoren.

Acties:
  • 0 Henk 'm!

  • BalusC
  • Registratie: Oktober 2000
  • Niet online

BalusC

Carpe diem

De "&&" en "||" heten op zich idd conditionele operatoren.

Acties:
  • 0 Henk 'm!

  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Wat misschien ook een idee is: bedenk eerst een functie die als input een kleur neemt, en als output een waarde tussen 0 en 1. 0 is helemaal niet geel (255, 0, 0) en 1.0 is helemaal geel (0,255,255). Zo kan je bijvoorbeeld kijken hoe geel een plaatje nou echt is :)

Succes!

Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 08:59

Creepy

Tactical Espionage Splatterer

BalusC schreef op zondag 13 augustus 2006 @ 08:37:
[...]
Dit worden conditionele expressies genoemd: && en || :) Niks bijzonders. Wanneer je & en | gebruikt ipv && en || dan worden gewoon de béide voorwaarden getest.
Er zijn talen die gebruik van && en || niet op die manier optimaliseren (en dat is dom ja).

Overigens && en || zijn logische operatoren. | en & zijn bitwise operatoren en dienen daardoor altijd uitgevoerd te worden anders klopt de uitkomst nier meer. Gebruikt voor condities met true en false dus altijd de && en ||

Bij de && kan je na de eerste conditie al stoppen als deze false is. Bij de || als de eerste true is

Edit: anders herhaal ik gewoon even wat prototype al heeft gezegd. Tis nog vroeg zullen we maar zeggen :z

[ Voor 11% gewijzigd door Creepy op 13-08-2006 10:28 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • BalusC
  • Registratie: Oktober 2000
  • Niet online

BalusC

Carpe diem

Creepy schreef op zondag 13 augustus 2006 @ 10:24:
Er zijn talen die gebruik van && en || niet op die manier optimaliseren (en dat is dom ja).
Zoals PHP? :X
Overigens && en || zijn logische operatoren.
OK, als je het goed wilt doen: Conditionele logische operatoren :P

Maar we gaan offtopic 8)7

Acties:
  • 0 Henk 'm!

Anoniem: 76570

Creepy schreef op zondag 13 augustus 2006 @ 10:24:
[...]

Er zijn talen die gebruik van && en || niet op die manier optimaliseren (en dat is dom ja).
Ik weet dat er idiote programmeertalen bestaan, maar dit gaat er bij mij moeilijk in tbh. Ik vind ook niet dat je het onder de noemer "optimaliseren" moet plaatsen: het is gewoon een duidelijke eigenschap die ik iig ook vaak zat gebruik.

Overigens gaat PHP nog wat verder met deze operatoren, in dat je ze ook zonder if kunt gebruiken.
PHP:
1
2
3
<?php
    mysql_connect($a,$b,$c) || die("Unable to connect");
?>


@hieronder
Of het nu wel of niet in een if-statement staat maakt niks uit, en dat is niet iets wat specifiek is voor PHP :)
Dat is dus WEL redelijk specifiek voor php. In java, c#, visual basic, java script kan het niet :).

[ Voor 16% gewijzigd door Anoniem: 76570 op 13-08-2006 13:34 ]


Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

PHP doet dat dus wel ;)
Anoniem: 76570 schreef op zondag 13 augustus 2006 @ 12:23:
Overigens gaat PHP nog wat verder met deze operatoren, in dat je ze ook zonder if kunt gebruiken.
PHP:
1
2
3
<?php
    mysql_connect($a,$b,$c) || die("Unable to connect");
?>
mysql_connect returned een resource indien het connecten is gelukt, en anders false. Een resource evalueerd altijd naar true binnen PHP waardoor er bij een mislukt inlogpoging het deel na de || operator wordt geevalueerd. Of het nu wel of niet in een if-statement staat maakt niks uit, en dat is niet iets wat specifiek is voor PHP :)

Acties:
  • 0 Henk 'm!

  • Farmerpeter
  • Registratie: Maart 2005
  • Laatst online: 02-12-2024

Farmerpeter

`'t kan verkeren

Topicstarter
Ondertussen ben ik weer een stuk wijzer, over if-statements en conditionele expressies. Ik ben niet al te vaak aanwezig daarom duurde een reactie van mijn kant best lang.

Ik heb het stukje code van Glow mouse overgenomen, ziet er wat korter uit. ik ben nu met mijn eigenlijke doel bezig, het herkennen van mijn object, wat ik nu zie is dat JPG eigenlijk een te hoge kwaliteit heeft, al ga ik naar gif, dan heb ik een hoop minder kleuren. maar de randen worden hierdoor minder scherp en dus slechter te herkennen.

Terwijl ik juist scherpe hoeken wil. Ik zit net in Paint.net met een optie te spelen die de resolutie vermindert (pixelate), ik denk dat het plaatje in een kleiner formaat opslaan, toch wel de oplossing is, ondanks het scherpteverlies.

Heeft er iemand ervaring met het herkennen van objecten (dmv webcam) welke formaat gaf een goed resultaat?

AM2 X2 3600 @ 3.0Ghz Asrock AliveNF4G-DVI OCZ pc5300


Acties:
  • 0 Henk 'm!

  • DroogKloot
  • Registratie: Februari 2001
  • Niet online

DroogKloot

depenisvanjezus

Erhm... algoritmes voor het herkennen van objecten (of zelfs maar de randen ervan) gaan wel even wat verder dan een wandelingetje over alle pixels met twee for-loopjes, edge detection bijvoorbeeld wordt vaak gedaan met behulp van Gaussische convolutie-kernels om de 1e- en 2e-orde afgeleiden (die deel van de locale structuur van een beeld vormen) te vinden welke dan worden afgezocht naar zero-crossings en objectherkenning is nog weer een tikkeltje lastiger (daar komt onder andere principale componenten analyse bij kijken), dus weet waar je aan begint. ;)

Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

aanvulling bij droogkloot:

bovendien gebruikt men in beeldverwerking/herkenning zelden RGB waarden.
men schakelt meestal over naar een andere color-space zoals bvb:
YUV, XYZ, xyz, xyY LUV en andere.

waarin Y meestal de luminantie(helderheid) is en u,v/x,y/X,Z de chrominantie (kleur) bepalen

kijk hier maar eens bvb:
http://en.wikipedia.org/wiki/CIE_1931_color_space

[ Voor 11% gewijzigd door H!GHGuY op 19-08-2006 19:27 ]

ASSUME makes an ASS out of U and ME

Pagina: 1