Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (WinAPI, Konsole) » Funktion zum Zählen von Farben

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
07.10.2017, 23:24 Uhr
Yadgar



Hi(gh)!

Nach mehreren Monaten Pause bin ich mal wieder mit YIP (Yadgar's Image Processor), meinem kommandozeilenbasierten Bildbearbeitungsprogramm für Linux und Windows zugange... und komme bei der Funktion count zum Zählen von Farben in einem Bild nicht weiter.

Hier die Funktion:


C++:
unsigned int count(vector<vector<pixel> > &img)
{
  unsigned int h = img.size();
  unsigned int w = img[0].size();
  unsigned int c, r, i, cc=0;
  bool newcolor;
  vector<pixel> colors;
  colors.push_back(img[0].at(0));
  
  cc = 1;
  
  cout << "Funktion count wurde aufgerufen!" << endl;
  
  newcolor = true;
  
  for (r=0; r<h; r++)
  {
    for (c=0; c<w; c++)
    {
      i=0;
      while(newcolor==true && i<cc)
      {
        cout << "Farbe Rotwert: " << colors[i].get_red() << endl;
          cout << "Farbe Gr" << uuml << "nwert: " << colors[i].get_green() << endl;
          cout << "Farbe Blauwert: " << colors[i].get_blue() << endl;
          cout << "Pixel Rotwert: " << img[r].at(c).get_red() << endl;
          cout << "Pixel Gr" << uuml << "nwert: " << img[r].at(c).get_green() << endl;
          cout << "Pixel Blauwert: " << img[r].at(c).get_blue() << endl;

        if (img[r].at(c).get_red() == colors[i].get_red()
            || img[r].at(c).get_green() == colors[i].get_green()
            || img[r].at(c).get_blue() == colors[i].get_blue())
        {
          newcolor = false;    
        }
        i++;
      }    
      if (newcolor)    
      {
          colors.push_back(img[r].at(c));
          cout << "Neue Farbe gefunden!" << endl;
          cc++;
      }
      newcolor = true;
      // cout << "Zeile " << r <<" ,Spalte " << c << endl;
    }
  }
  return cc;
}



Gedacht habe ich mir das so: ein zweidimensionaler Vektor, der die Bilddaten vom selbstdefinierten Typ pixel enthält, wird per Referenz an die Funktion übergeben; in der Funktion wird dann ein Vektor für die gefundenen Farben, ebenfalls vom Typ pixel angelegt. Dann wird Zeile für Zeile, Spalte für Spalte für jedes Pixel überprüft, ob die Farbe bereits existiert - die am Beginn des Vergleichs-Durchlaufs (innerste Schleife) auf true gesetzte bool-Variable "newcolor" wird false, sobald im Farb-Vektor eine mit dem aktuellen Pixel übereinstimmende Farbe gefunden wird, was gleichzeitig Abbruchkriterium für die while-Schleife ist. Ist am Ende des Vergleichs-Durchlaufs newcolor immer noch true, wird das jeweilige Pixel-Farbtripel an den Farbvektor angehangen.

Soweit die Theorie. In der Praxis stelle ich leider fest, dass die innerste while-Schleife nur für das allererste Pixel durchlaufen wird (und mit newcolor=false endet, da ich vorher die erste Farbe bereits gesetzt hatte, da ich mir nicht sicher war, ob ich an einen völlig leeren Vektor mit push_back Elemente anfügen kann), dann aber nie mehr. Die äußeren zwei Schleifen werden, wie ich anhand der Testausgaben feststellen könnte, einwandfrei abgearbeiten, also muss der Fehler in der while-Schleife und/oder der anschließenden if-Abfrage stecken. Aber wo?

Bis bald im Khyberspace!

Yadgar
--
Flagmaker - ein Programmier-Blog
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
08.10.2017, 15:34 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


Hi,

wie genau soll deine Funktion nun funktionieren? Alle enthaltenen Farben zählen? (also z.b 5 x rgb(50,30,32), 8 x rgb(12,0,50), usw?)

Prinzipiell musst du um alle Farben zu erhalten, auch jeden Pixel ansehen und überprüfen ob du die aktuelle Farbe schon in der Liste der gesehenen Farben hast. Du darfst ausgeben deiner Farbtabelle und ermitteln dieser nicht verschmischen!

quasi eine Art (Pseudocode)


Code:
für jeden pixel:
  ist farbe schon in farbtabelle?
    nein, dann zu farbtabelle hinzufügen
farbtabelle ausgeben




Zitat:

da ich mir nicht sicher war, ob ich an einen völlig leeren Vektor mit push_back Elemente anfügen kann


natürlich! du fügst zu beginn ja auch auf einen völlig leeren Vektor ein element hinzu!

Ein anderer Hinweis noch: da deine Funktion ja dein Bild nicht verändern soll, sollte dein bild-vector-vector const sein. const zu verwenden ist normalerweise guter stil, das hilft u.A versehentliche Variablendreher oder Fehlzugriffe schon zur Compile-Zeit zu ermitteln.
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
09.10.2017, 10:21 Uhr
Yadgar



Hi(gh)!


Zitat von FloSoft:

wie genau soll deine Funktion nun funktionieren? Alle enthaltenen Farben zählen? (also z.b 5 x rgb(50,30,32), 8 x rgb(12,0,50), usw?)



Nein, an eine Histogramm-Funktion habe ich (erstmal) noch nicht gedacht (wäre aber eine interessante Idee für später)... die Funktion soll jetzt nur die Anzahl der verschiedenen im Bild enthaltenen Farben ausgeben!


Zitat von FloSoft:

Prinzipiell musst du um alle Farben zu erhalten, auch jeden Pixel ansehen und überprüfen ob du die aktuelle Farbe schon in der Liste der gesehenen Farben hast. Du darfst ausgeben deiner Farbtabelle und ermitteln dieser nicht verschmischen!

quasi eine Art (Pseudocode)


Code:
für jeden pixel:
  ist farbe schon in farbtabelle?
    nein, dann zu farbtabelle hinzufügen
farbtabelle ausgeben





Das habe ich auch so gemacht - trotzdem kommt am Ende als Ausgabe immer nur "Das Bild enthält 1 Farben", weil offensichtlich die Vergleichs-Schleife (while) nur einmal durchlaufen wird, nämlich beim ersten zu vergleichenden Pixel des Bildes! Warum?


Zitat von FloSoft:

Ein anderer Hinweis noch: da deine Funktion ja dein Bild nicht verändern soll, sollte dein bild-vector-vector const sein. const zu verwenden ist normalerweise guter stil, das hilft u.A versehentliche Variablendreher oder Fehlzugriffe schon zur Compile-Zeit zu ermitteln.


Mein Programm enthält ja noch eine ganze Reihe anderer Funktionen, bei denen das Bild sehr wohl verändert wird, also ergibt eine Definition von vornherein als Konstante keinen Sinn... oder meinstest du Übergabe per konstanter Referenz?

Bis bald im Khyberspace!

Yadgar
--
Flagmaker - ein Programmier-Blog
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
09.10.2017, 13:12 Uhr
Tommix



Hallo,
müsste bei dem ersten if nicht dreimal != stehen statt == ?
- Tommix
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
09.10.2017, 18:58 Uhr
ao

(Operator)


Ich glaube, du musst newcolor für jedes Pixel neu auf true setzen, nicht nur ein einziges Mal. Und außerhalb der inneren Schleife brauchst du es überhaupt nicht.

Also so:


C++:
  for (r=0; r<h; r++)
  {
    for (c=0; c<w; c++)
    {
      i=0;
      bool newcolor = true;
      while(newcolor==true && i<cc)
      {



 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
09.10.2017, 19:26 Uhr
ao

(Operator)


Sorry, das letzte stimmt nicht. newcolor = true machst du ja am Ende der Schleife.

Da du Debugger und ähnliche Werkzeuge ja für überflüssig oder für unter deiner Würde hältst, bleibt dir wohl nur, alle Variablen, die in den Kontrollstrukturen relevant sind (r, c, newcolor, i, cc) in jedem Schleifendurchlauf auszugeben und zu hoffen, dass dir etwas auffällt.

Es ist übrigens unnötig und gefährlich, die Anzahl der Farben in einer eigenen Variablen (cc) mitzuführen. Unnötig, weil count.size() dir dir die Anzahl jederzeit liefert, und gefährlich, weil du es nicht merkst, wenn deine eigene Verwaltung einen Fehler hat und davon abweicht.

Und natürlich solltest du das erste colors.push_back schnellstens entfernen. Mit solchen Sonderfälle brichst du dir den Hals.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
09.10.2017, 19:29 Uhr
ao

(Operator)


Neuer Versuch:


C++:
        if (img[r].at(c).get_red() == colors[i].get_red()
            || img[r].at(c).get_green() == colors[i].get_green()
            || img[r].at(c).get_blue() == colors[i].get_blue())
        {
          newcolor = false;    
        }


muss heißen:

C++:
        if (img[r].at(c).get_red() == colors[i].get_red()
            && img[r].at(c).get_green() == colors[i].get_green()
            && img[r].at(c).get_blue() == colors[i].get_blue())
        {
          newcolor = false;    
        }


Zwei Pixel sind dann farbgleich, wenn sie in allen Komponenten übereinstimmen.

Das wäre jetzt ein Anlass, der Klasse pixel einen ==-Operator zu spendieren.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (WinAPI, Konsole) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: