# dunkles Pixel erkennen (openCV)



## dsNDesign (27. Juli 2014)

Hei,
ich habe folgendes vor:

ich habe ein weißes Bild, in welchem sich an einer Stelle ein schwarzer Bereich befindet. Das Bild ist 3px hoch und z.B. 500px breit. Der schwarze Bereich ist etwa 5-6px breit.

Nun möchte ich die x-Koordinate des Mittelpunktes des schwarzen Bereichs herausfinden. Hierzu steht mir openCV zur Verfügung.

Wie stelle ich das an?

Viele Grüße


----------



## Hunter (27. Juli 2014)

Hallo,

soll dein Programm Platformunabhängig sein? Falls nein und es nur auf Windows laufen muss, könntest Du die Windows-Funktionen verwenden.
Da ich nicht mit openCV nicht auseinandergesetzt habe würde ich folgendes Vorschlagen, du müsstest dies dann nur noch umsetzten:

```
struct BlackPixel {
int firstBlackPx;
int firstBlackPy;
int lastBlackPx;
int lastBlackPy;
bool lastPixelBlack;
};

BlackPixel bpx;
bpx.firstBlackPx = -1;
bpx.firstBlackPy = -1;
bpx.lastBlackPx = -1;
bpx.lastBlackPy = -1;
bpx.lastPixelBlack = false;

for(int i = 0; i < image.getWidth(); i++) {
   for(int j = 0; j < image.getHeight(); j++) {
      if(image.getPixelColor(i, j) == RGB(0, 0, 0) && bpx.firstBlackPx != -1) { //Finde Anfangskoordinaten des schwarzen Bereichs heraus
      bpx.firstBlackPx = i;
      bpx.firstBlackPy = j;
      }
      else if(image.getPixelColor(i, j) == RGB(0, 0, 0))
         bpx.lastPixelBlack = true;
      else if(image.getPixelColor(i, j) != RGB(0, 0, 0))
         bpx.lastPixelBlack = false;
      else if(bpx.lastBlackPx == -1 && image.getPixelColor(i, j) != RGB(0, 0, 0) && bpx.lastPixelBlack ==  true) //Finde letzte Position des schwarzen X-Pixels heraus
         bpx.lastBlackPx = i;
      else if(bpx.lastBlackPy == -1 && image.getPixelColor(i, j) != RGB(0, 0, 0) && bpx.lastPixelBlack == true) //Finde letzte Position des schwarzen Y-Pixels heraus
         bpx.lastBlackPy = j;
      if(bpx.lastBlackPy != -1 && bpx.lastBlackPx != -1)
         break;
      }
}


//Berechne Pixel vom Mittelpunkt des Schwarzen Bereichs
float xMid = (bpx.lastBlackPx - bpx.firstBlackPx) / 2 + bpx.firstBlackPx;
float yMid = (bpx.lastBlackPy - bpx.firstBlackPy) / 2 + bpx.firstBlackPy;
```

Wenn ich jetzt keinen Denkfehler gemacht habe müsste dies funktionieren.


----------



## Jennesta (27. Juli 2014)

Hallo,
was genau heißt bei dir schwarzer Bereich 3px x 5-6 px? Also ein schwarzes Rechteck oder kann es auch nur eine Reihe sein.
Ansonsten wird die schnellste Methode sein einfach zeilenweise durch das Bild zu iterieren und sobald du auf ein schwarzes Pixel triffst prüfst du wie häufig diese Pixel auftreten, also ob es deiner Definition des Bereichs genügt.
Dazu speicherst du dann einfach x-Koordinate vom ersten und vom letzten Pixel und berechnest dann den Mittelpunkt. Schwieriger wirds, wenn dein Bild nicht rein schwarz/weiß ist, dann musst du per Schwellschwert prüfen.

Grüße,
Jennesta


----------



## ComFreek (27. Juli 2014)

Zur Farberkennung würde ich den HSV-Farbraum vorschlagen. Hierbei kannst du anhand "V" = "Value" prüfen, wie hell eine bestimmte Farbe ist.
Bei RGB würde das beispielsweise nicht so einfach klappen, weil bei RGB keine Helligkeitskomponente in dieser Art vorhanden ist.


----------



## derpfaff (6. August 2014)

Hallo dsNDesign,

ich weiß nicht, ob du dein Problem bereits gelöst hast, aber im Prinzip musst du doch nur das Bild von links nach rechts durchlaufen und den Grauwert (sofern der Wertebereich 0 - 255) überprüfen. Sobald du also folgende Bedingung erfüllst, weißt du die linke X-Koordinate.

```
if(0 == pixelValue)
```
Nun gehst du weiter nach rechts, bis du wiederum folgende Bedingung erfüllt hast:

```
if(255 == pixelValue)
```
Jetzt weißt du, dass das vorherige Pixel das letzte schwarze Pixel war (hast also die rechte X-Koordinate) und musst nur noch rechnen:

```
int xCenter = (int)((x2 - x1)/2.0)
```

Einziges Manko: wenn das schwarze Objekt 4 px breit ist, liegt der Mittelpunkt genau zwischen dem dritten und vierten Pixel.

Und die Abfrage der Helligkeitswerte mittels OpenCV kannst du so realisieren:

```
uchar pixelValue = image->imageData[currentRow*image->widthStep + currentColumn];
```

Habe jetzt eine Weile nicht mit OpenCV gearbeitet, sollte in etwa aber so funktionieren.

Viel Erfolg!
derPfaff


----------

