Seite 1 von 1

Was bedeuten diese Zeilen?

Verfasst: Mittwoch 8. Januar 2020, 19:13
von JanaSophie
Liebe alle hier,

Nachdem ich nun openCV installiert habe, arbeite ich daran, ein Beispiel mit Film/Bildbearbeitung durchzuarbeiten, was mit gut passt, siehe hier:

https://medium.com/@janhettenkofer/find ... 5b564db044

Da geht es darum, dass ein Bild eingelesen und der hellste / durchschnittliche Punkt (Farbe) errechnet wird

base = cv2.imread(args.base, cv2.IMREAD_UNCHANGED)
base = np.float32(base) / np.iinfo(base.dtype).max
base = cv2.mean(base)

Die erste Zeile verstehe ich, da wird das Bild geladen und das Ergebnis "base" müsste vom Typ "Mat"? sein (ich hab bei "imread in der doku gelesen, weil man ja immer auf den Typ achten soll :-) )

Aber was ist das Ergebnis von np-float32(base) in der nächsten Zeile? Also eine Variable vom Typ "Mat" (wie sieht das aus) wird umgewandelt in eine Zahl??

Re: Was bedeuten diese Zeilen?

Verfasst: Mittwoch 8. Januar 2020, 19:30
von Sirius3
`imread` liefert üblicherweise Daten vom Typ byte, also ganze Zahlen zwischen 0 und 255. `float32` wandelt dann das Array in ein Array mit dem Datentyp 32bit Fließkommazahl um, die dann durch die größte Zahl geteilt wird, die ein byte annehmen kann; letztlich hast Du also ein Array mit Zahlen von 0.0 bis 1.0.

Re: Was bedeuten diese Zeilen?

Verfasst: Mittwoch 8. Januar 2020, 19:39
von JanaSophie
Also ich hab hier nachgelesen: https://docs.opencv.org/3.4/d4/da8/grou ... odecs.html
Gibt es eine andere Stelle, wo ich für Python besser nachlesen kann? Wie soll man denn von "Mat" auf ein Byte-array kommen??

Aber gut, also "base = np.float32(base)" Macht aus einem Array mit lauter Bytes ein gleich großes Array mit lauter Gleitkommazahlen, richtig?

Was liefert dann "np.iinfo(base.dtype).max" Eine Zahl? Und wie kann ich ein Array durch eine Zahl teilen und es kommt 0..1 raus? Seltsam, also Python soll doch so einfach lesbar sein . aber das kann ich so noch nicht unterschreiben (ich kenne nur Java sonst)

Re: Was bedeuten diese Zeilen?

Verfasst: Mittwoch 8. Januar 2020, 20:03
von Sirius3
Theoretisch kann der Rückgabewert von imread irgendeinen Zahlentyp haben, meist sind das aber Bytes. Und eine Matrix mit einem Skalar zu multiplizieren ist in der Mathematik definiert und ist bei NumPy auch nicht anders. Wenn man also einen mathematischen Hintergrund hat, dann ist das sehr gut lesbar.

Re: Was bedeuten diese Zeilen?

Verfasst: Donnerstag 9. Januar 2020, 01:48
von __blackjack__
@JanaSophie: `Mat` ist ein C++-Datentyp von OpenCV — auf Python-Seite kommt das als Numpy-Array an. Welche Dimansionen das Array hat und welchen Typ die Elemente des Arrays haben, kann man nicht so genau sagen weil beim Lesen angegeben wurde, dass die Daten unverändert geladen werden sollen.

Neben der OpenCV-Dokumentation muss man sich also auch mit Numpy beschäftigen, also beispielsweise mal das Tutorial in dessen Dokumentation durcharbeiten. Wie dort Slicing und Rechenoperationen mit Arrays definiert sind, macht den ganzen Charme dieser Arrays aus.

Das man die skalaren Numpy-Datentypen zum Umwandeln eines Arrays verwenden kann war mir übrigens auch neu. Ich hätte dafür die `astype()`-Methode verwendet: ``base = base.astype(np.float32) / np.iinfo(base.dtype).max``

Was an dem Code aus dem Blogbeitrag dann etwas doof ist, ist das der den Namen `base` für das Array und dann für den Mittelwert der Arraywerte verwendet. Das man Namen in Python nacheinnder verschiedene/beliebige Typen zuweisen kann ist nett und IMHO auch sinnvoll solange der ”duck type” gleich ist. Also zum Beispiel ”Array das Bild repräsentiert” ohne das man sich dabei auf einen konkreten Datentyp für die Elemente von diesen Arrays festlegen muss, aber mal ein Bild und mal einen Mittelwert im gleichen Namensraum an den gleichen Namen zu binden ist keine gute Idee.

Die interaktive Shell ist in Python ein gutes Werkzeug, sowohl zum lernen als auch zum kennenlernen und erforschen von Bibliotheken. Da kann man mit Code live experimentieren, sieht die Werte, kann die Typen abfragen, und die Hilfstexte die bei vielen Bibliotheken direkt an den Objekten hinterlegt sind. Wirf mal einen Blick auf IPython und/oder JupyterLab.

Code: Alles auswählen

In [24]: img = cv2.imread("test.jpg", cv2.IMREAD_UNCHANGED)                     

In [25]: img                                                                    
Out[25]: 
array([[[ 97, 122, 148],
        [ 97, 122, 148],
        [ 96, 121, 147],
        ...,
        [ 38,  39,  37],
        [ 38,  39,  37],
        [ 38,  39,  35]],

       [[ 96, 122, 146],
        [ 96, 121, 147],
        [ 95, 120, 146],
        ...,
        [ 38,  39,  37],
        [ 38,  39,  37],
        [ 38,  39,  35]],

       [[ 93, 119, 143],
        [ 92, 118, 142],
        [ 92, 117, 143],
        ...,
        [ 38,  39,  37],
        [ 38,  39,  37],
        [ 38,  39,  35]],

       ...,

       [[ 26,  30,  48],
        [ 26,  30,  48],
        [ 26,  30,  48],
        ...,
        [  6,  13,  30],
        [  6,  13,  30],
        [  6,  13,  30]],

       [[ 26,  30,  48],
        [ 26,  30,  48],
        [ 26,  30,  48],
        ...,
        [  5,  12,  29],
        [  5,  12,  29],
        [  5,  12,  29]],

       [[ 25,  29,  47],
        [ 25,  29,  47],
        [ 25,  29,  47],
        ...,
        [  4,  11,  28],
        [  4,  11,  28],
        [  4,  11,  28]]], dtype=uint8)

In [26]: np.float32(img)                                                        
Out[26]: 
array([[[ 97., 122., 148.],
        [ 97., 122., 148.],
        [ 96., 121., 147.],
        ...,
        [ 38.,  39.,  37.],
        [ 38.,  39.,  37.],
        [ 38.,  39.,  35.]],

       [[ 96., 122., 146.],
        [ 96., 121., 147.],
        [ 95., 120., 146.],
        ...,
        [ 38.,  39.,  37.],
        [ 38.,  39.,  37.],
        [ 38.,  39.,  35.]],

       [[ 93., 119., 143.],
        [ 92., 118., 142.],
        [ 92., 117., 143.],
        ...,
        [ 38.,  39.,  37.],
        [ 38.,  39.,  37.],
        [ 38.,  39.,  35.]],

       ...,

       [[ 26.,  30.,  48.],
        [ 26.,  30.,  48.],
        [ 26.,  30.,  48.],
        ...,
        [  6.,  13.,  30.],
        [  6.,  13.,  30.],
        [  6.,  13.,  30.]],

       [[ 26.,  30.,  48.],
        [ 26.,  30.,  48.],
        [ 26.,  30.,  48.],
        ...,
        [  5.,  12.,  29.],
        [  5.,  12.,  29.],
        [  5.,  12.,  29.]],

       [[ 25.,  29.,  47.],
        [ 25.,  29.,  47.],
        [ 25.,  29.,  47.],
        ...,
        [  4.,  11.,  28.],
        [  4.,  11.,  28.],
        [  4.,  11.,  28.]]], dtype=float32)

In [27]: img.dtype                                                              
Out[27]: dtype('uint8')

In [28]: np.iinfo(img.dtype)                                                    
Out[28]: iinfo(min=0, max=255, dtype=uint8)

In [29]: np.iinfo(img.dtype).max                                                
Out[29]: 255

In [30]: np.float32(img) / np.iinfo(img.dtype).max                              
Out[30]: 
array([[[0.38039216, 0.47843137, 0.5803922 ],
        [0.38039216, 0.47843137, 0.5803922 ],
        [0.3764706 , 0.4745098 , 0.5764706 ],
        ...,
        [0.14901961, 0.15294118, 0.14509805],
        [0.14901961, 0.15294118, 0.14509805],
        [0.14901961, 0.15294118, 0.13725491]],

       [[0.3764706 , 0.47843137, 0.57254905],
        [0.3764706 , 0.4745098 , 0.5764706 ],
        [0.37254903, 0.47058824, 0.57254905],
        ...,
        [0.14901961, 0.15294118, 0.14509805],
        [0.14901961, 0.15294118, 0.14509805],
        [0.14901961, 0.15294118, 0.13725491]],

       [[0.3647059 , 0.46666667, 0.56078434],
        [0.36078432, 0.4627451 , 0.5568628 ],
        [0.36078432, 0.45882353, 0.56078434],
        ...,
        [0.14901961, 0.15294118, 0.14509805],
        [0.14901961, 0.15294118, 0.14509805],
        [0.14901961, 0.15294118, 0.13725491]],

       ...,

       [[0.10196079, 0.11764706, 0.1882353 ],
        [0.10196079, 0.11764706, 0.1882353 ],
        [0.10196079, 0.11764706, 0.1882353 ],
        ...,
        [0.02352941, 0.05098039, 0.11764706],
        [0.02352941, 0.05098039, 0.11764706],
        [0.02352941, 0.05098039, 0.11764706]],

       [[0.10196079, 0.11764706, 0.1882353 ],
        [0.10196079, 0.11764706, 0.1882353 ],
        [0.10196079, 0.11764706, 0.1882353 ],
        ...,
        [0.01960784, 0.04705882, 0.11372549],
        [0.01960784, 0.04705882, 0.11372549],
        [0.01960784, 0.04705882, 0.11372549]],

       [[0.09803922, 0.11372549, 0.18431373],
        [0.09803922, 0.11372549, 0.18431373],
        [0.09803922, 0.11372549, 0.18431373],
        ...,
        [0.01568628, 0.04313726, 0.10980392],
        [0.01568628, 0.04313726, 0.10980392],
        [0.01568628, 0.04313726, 0.10980392]]], dtype=float32)

In [31]: (np.float32(img) / np.iinfo(img.dtype).max).mean()                     
Out[31]: 0.25126287

Re: Was bedeuten diese Zeilen?

Verfasst: Donnerstag 9. Januar 2020, 09:31
von JanaSophie
Na ich sehe schon, ich war zu ungeduldig, jetzt habe jetzt auch die Zeile verstanden, glaube ich. :-)

Diese detaillierte Ausgabe mit [in] und [out] - wie kriegt man die hin, also dass man das so sieht?

Dass man Namen (Variablen) in Python nacheinander verschiedene/beliebige Typen zuweisen kann, ist für mich total irritierend, gerade in dem Beispiel, aber ich muss das ja nicht machen.

Re: Was bedeuten diese Zeilen?

Verfasst: Donnerstag 9. Januar 2020, 11:49
von __blackjack__
@JanaSophie: Das mit den In/Out ist IPython oder JupyterLab.

Die ersten beiden Zuweisungen an `base` sind IMHO okay, auch wenn das einmal ein Array mit in den meisten Fällen Bytewerten ist und dann eines mit 32-Bit-Gleitkommazahlen. Beide male repräsentiert der Wert ja das gleiche: die Pixelwerte des gelesenen Bildes.