OpenCV-Punkte (x, y) repräsentieren (Spalte, Zeile) oder (Zeile, Spalte)

74

Ich habe ein 300x200 Bild in einer Matrix src. Ich mache die folgende Operation am Bild.

for(int i=0;i<src.rows;i++){
  for(int j=0;j<src.cols;j++){
    line( src, Point(i,j),Point(i,j), Scalar( 255, 0, 0 ),  1,8 );
  }
}
imshow("A",src);
waitKey(0);

Ich hatte erwartet, dass es das gesamte Bild in Weiß bedeckt, aber der untere Teil des Bildes bleibt leer. Während, wenn ich das mache

  for(int i=0;i<src.rows;i++){
    for(int j=0;j<src.cols;j++){
      src.at<uchar>(i,j)=255;
    }
  }
  imshow("A",src);
  waitKey(0);

Das gesamte Bild ist weiß bedeckt. So bedeutet dies , dass src.at<uchar>(i,j)unter Verwendung (i,j)als (Zeile, Spalte) , aber Point(x,y)unter Verwendung (x,y)als (Spalte, Zeile)

user3747190
quelle
2
Das ist richtig. Die Dokumentation sagt so viel - Punkt (x, y) und bei (Zeile, Spalte) ist die Art und Weise, wie es implementiert wird.
Roger Rowland
1
Ja. Punkte und Größe gehen (x, y); (Breite, Höhe), - Matte hat (Reihe, Spalte).
Berak
1
Vielen Dank, dass Sie diese Frage gestellt haben. Diese verdammte Inkonsistenz kostet mich Stunden des Debuggens ...
Yuqli

Antworten:

116

So bedeutet dies , dass src.at(i,j)unter Verwendung (i,j)als (Zeile, Spalte) , aber Point(x,y)unter Verwendung (x,y)als (Spalte, Zeile)

Das ist richtig! Da dies viele Leute zu verwirren scheint, schreibe ich meine Interpretation aus folgendem Grund:

In OpenCV cv::Matwird sowohl für Bilder als auch für Matrizen verwendet, da ein diskretes Bild im Wesentlichen mit einer Matrix identisch ist.

In der Mathematik haben wir verschiedene Dinge:

  1. Matrizen, die eine Anzahl von Zeilen und eine Anzahl von Spalten haben.
  2. Diagramme (von Funktionen), die mehrere Achsen haben und das Diagramm in Form eines Bildes grafisch darstellen.
  3. Punkte, die nach den Achsen des Koordinatensystems geordnet sind, das normalerweise eine kartesische Koordinate ist.

1. Für Matrizen ist die mathematische Notation in Zeilen-Hauptreihenfolge zu ordnen

Nach der herkömmlichen Matrixnotation werden Zeilen durch den ersten Index eines zweidimensionalen Arrays und Spalten durch den zweiten Index nummeriert, dh a1,2 ist das zweite Element der ersten Zeile, das nach unten und rechts zählt. (Beachten Sie, dass dies das Gegenteil von kartesischen Konventionen ist.)

Entnommen aus http://en.wikipedia.org/wiki/Row-major_order#Explanation_and_example

Wie in der Mathematik ist Zeile: 0, Spalte: 0 das Element oben links in der Matrix. Zeile / Spalte sind wie in Tabellen ...

0/0---column--->
 |
 |
row
 |
 |
 v

2. Für Punkte wird ein Koordinatensystem ausgewählt, das zwei Dinge erfüllt: 1. Es verwendet dieselben Einheitengrößen und denselben "Ursprung" wie die Matrixnotation, sodass oben links Punkt (0,0) und Achsenlänge 1 sind bedeutet die Länge von 1 Zeile oder 1 Spalte. 2. Es verwendet "Bildnotation" für die Achsenordnung, was bedeutet, dass die Abszisse (horizontale Achse) der erste Wert ist, der die x-Richtung bezeichnet, und die Ordinate (vertikale Achse) der zweite Wert ist, der die y-Richtung bezeichnet.

Der Punkt, an dem sich die Achsen treffen, ist der gemeinsame Ursprung der beiden Zahlenlinien und wird einfach als Ursprung bezeichnet. Es wird oft mit O bezeichnet, und wenn ja, werden die Achsen Ox und Oy genannt. Eine Ebene mit definierten x- und y-Achsen wird häufig als kartesische Ebene oder xy-Ebene bezeichnet. Der Wert von x wird als x-Koordinate oder Abszisse und der Wert von y als y-Koordinate oder Ordinate bezeichnet.

Die Auswahl der Buchstaben ergibt sich aus der ursprünglichen Konvention, bei der der letzte Teil des Alphabets verwendet wird, um unbekannte Werte anzuzeigen. Der erste Teil des Alphabets wurde verwendet, um bekannte Werte zu bezeichnen.

http://en.wikipedia.org/wiki/Cartesian_coordinate_system#Two_dimensions

In einer perfekten Welt würden wir das Koordinatensystem der Punkte / Bilder so wählen:

 ^
 |
 |
 Y
 |
 |
0/0---X--->

aber da wir diesen Ursprung in oberen linken und positiven Werten haben wollen, um nach unten zu gehen, ist es stattdessen:

0/0---X--->
 |
 |
 Y
 |
 |
 v

Für die Bildverarbeitung mag die Notation der Zeilen zuerst seltsam sein, für Mathematiker wäre es jedoch seltsam, mit der x-Achse zuerst auf eine Matrix zuzugreifen.

In OpenCV können Sie also Folgendes verwenden: mat.at<type>(row,column)oder, mat.at<type>(cv::Point(x,y))um auf denselben Punkt zuzugreifen, wenn x=columnund y=rowder vollkommen verständlich ist =)

Hoffe das richtig. Ich weiß nicht viel über die Notationen, aber das sagt mir meine Erfahrung in Mathematik und Bildgebung.

Micka
quelle
2
lustige Tatsache: In der Schule konnte ich mich nicht leicht an die Reihenfolge des Matrixindex am Anfang erinnern, daher war meine Vermutung "Spaltenindex wahrscheinlich zuerst, weil es die gleiche Richtung wie die x-Achse ist, die zuerst für Punkte ist". . leider falsch :-(
Micka
Was meinten Sie mit "Graphen (von Funktionen)"? Entschuldigung, das habe ich nicht verstanden. Könnten Sie das bitte näher erläutern oder nützliche Ressourcen dafür teilen? Vielen Dank!
Mailand,
Graphen (von Funktionen) sind Visualisierungen in der Mathematik, die so etwas wie ein Bild sind, wobei die x- und y-Koordinatenrichtungen durch Konvention gegeben sind.
Micka
1
Oh, jetzt habe ich es verstanden. Ich hatte es mit "Grafik - eine Datenstruktur" und "Funktion - in der Programmierung" verwechselt :-D Danke für die Klarstellung :)
Mailand
5

Ich habe eine schnelle und schnelle Lösung für dieses Problem gefunden, indem ich einfach die Koordinaten von opencv in kartesische Koordinaten im 4. Quadranten konvertiert habe, indem ich einfach ein (-) ve-Zeichen vor die y-Koordinate gesetzt habe.

Auf diese Weise konnte ich meine vorhandenen Algorithmen und alle kartesischen Standardsystemgleichungen mit opencv verwenden, ohne das System durch eine teure Konvertierung zwischen Koordinatensystemen zu belasten.

0/0---X--->
 |
 |
 Y
 |
 |
 v
 (opencv)

0/0---X----> 
|
|
|
-Y
|
|
v
(4th quadrant)
Dev Aggarwal
quelle
Ich versuche, opencv-Koordinaten in kartesische Koordinaten umzuwandeln. Kannst du mir erklären, wie du es gemacht hast? Ich arbeite mit Python. und das Erhalten von x, y koodeniert mit der Funktion x, y, w, h = cv2.boundingRect (c). danke
SergioGeeK7
Ich wollte nur sagen, dass die Antwort, die ich zuvor gegeben habe, falsch war. Hier ist die richtige, markierte Änderungen in Anführungszeichen
Dev Aggarwal
Fügen Sie also ein -ve-Zeichen auf der "Ordinate" Ihrer Koordinaten hinzu, dh ändern Sie "y" in "-y", und es sollte die Arbeit erledigen. w, h kann
Dev Aggarwal
Warum funktioniert das? Wenn Sie in der OpenCV-Welt "Von links nach rechts" entlang der horizontalen Achse bewegen, sehen Sie, dass die Koordinaten zunehmen, und wenn Sie sich von oben nach unten entlang der vertikalen Achse bewegen, nehmen die Koordinaten zu. Diese Art von Verhalten wird im 4. Quadranten des kartesischen Systems beobachtet.
Dev Aggarwal
3

Hier ist ein visuelles Beispiel, um Pythons [Zeile, Spalten] von OpenCVs [x, y] zu unterscheiden.

import numpy as np
import matplotlib.pyplot as plt
import cv2

img = np.zeros((5,5))  # initialize empty image as numpy array
img[0,2] = 1  # assign 1 to the pixel of row 0 and column 2

M = cv2.moments(img)  # calculate moments of binary image
cX = int(M["m10"] / M["m00"])  # calculate x coordinate of centroid
cY = int(M["m01"] / M["m00"])  # calculate y coordinate of centroid

img2 = np.zeros((5,5))  # initialize another empty image
img2[cX,cY] = 1  # assign 1 to the pixel with x = cX and y = cY

img3 = np.zeros((5,5))  # initialize another empty image
img3[cY,cX] = 1  # invert x and y

plt.figure()
plt.subplots_adjust(wspace=0.4)  # add space between subplots
plt.subplot(131), plt.imshow(img, cmap = "gray"), plt.title("With [rows,cols]")
plt.subplot(132), plt.imshow(img2, cmap = "gray"), plt.title("With [x,y]")
plt.subplot(133), plt.imshow(img3, cmap= "gray"), plt.title("With [y,x]"), plt.xlabel('x'), plt.ylabel('y')

Dies wird Folgendes ausgeben:

Geben Sie hier die Bildbeschreibung ein

Tommaso Di Noto
quelle