Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| lehrkraefte:blc:informatik:efi-2023:images [2023/12/13 10:27] – [Codierung als Binärdaten] Ivo Blöchliger | lehrkraefte:blc:informatik:efi-2023:images [2024/01/09 14:13] (current) – [Überprüfung der Binärdatei] Ivo Blöchliger | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Dithering und Bild-Kodierung ====== | ||
| + | Die e-paper Displays zeigen (so weit ich bis jetzt verstanden habe) nur Pixel in Weiss, Schwarz und Rot an. Bilder müssen also entsprechend konvertiert werden. | ||
| + | Siehe auch das Erklärvideo zur dreifarbigen E-Ink Technologie: | ||
| + | https:// | ||
| + | ===== Dithering ===== | ||
| + | Studieren und Implementieren Sie den https:// | ||
| + | |||
| + | Verwenden Sie dazu folgende Vorlage: | ||
| + | <code python dithering.py> | ||
| + | import cv2 | ||
| + | import sys | ||
| + | import os | ||
| + | import numpy as np | ||
| + | |||
| + | file = " | ||
| + | if len(sys.argv)> | ||
| + | file = sys.argv[1] | ||
| + | if not os.path.exists(file): | ||
| + | raise f" | ||
| + | |||
| + | def readAndConvert(file): | ||
| + | return cv2.cvtColor(cv2.imread(file), | ||
| + | |||
| + | def toBWSimple(img): | ||
| + | c = np.copy(img) | ||
| + | h,w = c.shape | ||
| + | for y in range(h): | ||
| + | for x in range(w): | ||
| + | if img[y, | ||
| + | c[y,x] = 0 | ||
| + | else: | ||
| + | c[y,x] = 1.0 | ||
| + | return c | ||
| + | |||
| + | def floydSteinberg(img): | ||
| + | c = np.copy(img) | ||
| + | h,w = c.shape | ||
| + | # | ||
| + | # TODO | ||
| + | # | ||
| + | return c | ||
| + | |||
| + | |||
| + | img = readAndConvert(file) | ||
| + | print(img.shape) | ||
| + | cv2.imshow(' | ||
| + | cv2.waitKey(1000) | ||
| + | c = toBWSimple(img) | ||
| + | cv2.imshow(' | ||
| + | cv2.waitKey(1000) | ||
| + | c = floydSteinberg(img) | ||
| + | cv2.imshow(' | ||
| + | cv2.waitKey(10000) | ||
| + | |||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | ===== Codierung als Binärdaten ===== | ||
| + | Die Auflösung unserer Displays ist 800x480, d.h. es werden für ein Schwarz/ | ||
| + | |||
| + | Die Bits in den einzelnen Bytes werden als Big-Endian interpretiert, | ||
| + | |||
| + | D.h. die ersten 8 Pixel sind wie folgt codiert: Bit 7, Bit 6, Bit 5, ... , Bit 0 | ||
| + | |||
| + | Befüllen Sie folgendes Array mit dem korrekten Werten: | ||
| + | <code python> | ||
| + | n = 48000 # Oder besser aus der Displaygrösse berechnen | ||
| + | data = np.zeros((n, | ||
| + | </ | ||
| + | |||
| + | ==== Umrechnung in Bytes ==== | ||
| + | Variante 1: Multiplikation mit 2 (um eine Stelle nach links zu schieben) und Addition von 1 oder 0 (je nach Bit) | ||
| + | |||
| + | Variante 2: Bit Operationen. Um das Bit $n$ einer Binärzahl $b$ zu setzen kann folgendes verwendet werden: | ||
| + | <code python> | ||
| + | b = b | (1 << n) # Der << Operator ist der Bitshift-Operator, | ||
| + | b |= (1 << n) # Kurzform | ||
| + | </ | ||
| + | |||
| + | Variante 3: Kombination der obigen Varianten: | ||
| + | <code python> | ||
| + | b = 0 | ||
| + | for bit in bits: # Annahme: bits ist ein Array von Einsen und Nullen | ||
| + | b = (b << 1) | bit | ||
| + | </ | ||
| + | |||
| + | Wandeln Sie dann das Array ins folgende Format um | ||
| + | <code c> | ||
| + | const unsigned char myimage[48000] = { | ||
| + | 18, | ||
| + | .... | ||
| + | }; | ||
| + | </ | ||
| + | Das könnte dann im Code für das Display gebraucht werden. | ||
| + | |||
| + | Später sollen diese Daten natürlich via https direkt vom Server kommen. | ||
| + | |||
| + | ==== Schreiben in eine Datei ==== | ||
| + | Text: | ||
| + | <code python> | ||
| + | textDaten = "... whatever ..." | ||
| + | with open(" | ||
| + | f.write(textDaten) | ||
| + | </ | ||
| + | |||
| + | Binär: | ||
| + | <code python> | ||
| + | binData = np.zeros((100, | ||
| + | with open(" | ||
| + | f.write(binData) | ||
| + | </ | ||
| + | |||
| + | ===== Binäre Übertragung von Daten an den ESP32 ===== | ||
| + | <code python sendBySerial.py> | ||
| + | # On Linux: sudo apt install python3-serial | ||
| + | # On Windows: pip install serial | ||
| + | |||
| + | import serial | ||
| + | import serial.tools.list_ports | ||
| + | import re | ||
| + | import sys | ||
| + | import os | ||
| + | import time | ||
| + | |||
| + | def getPort(): | ||
| + | # From https:// | ||
| + | ports = serial.tools.list_ports.comports() | ||
| + | for port, desc, hwid in sorted(ports): | ||
| + | print(" | ||
| + | return [port for port, desc, hwid in ports if re.search(r" | ||
| + | | ||
| + | |||
| + | def getData(): | ||
| + | if len(sys.argv)!=2: | ||
| + | raise "Bitte Dateinnamen mit binären Daten angeben." | ||
| + | fn = sys.argv[1] | ||
| + | if not os.path.exists(fn): | ||
| + | raise f" | ||
| + | if not os.path.getsize(fn)==96000: | ||
| + | raise f"Die Datei hat nicht die korrekt Grösse von 96000 Bytes" | ||
| + | with open(fn, mode=' | ||
| + | data = file.read() | ||
| + | return data | ||
| + | |||
| + | |||
| + | |||
| + | data = getData() | ||
| + | port = getPort() | ||
| + | print(f" | ||
| + | with serial.Serial(port, | ||
| + | ser.write(data) | ||
| + | for i in range(3): | ||
| + | s = ser.read(1000) | ||
| + | if len(s)> | ||
| + | print(s, | ||
| + | time.sleep(0.01) | ||
| + | |||
| + | print(f" | ||
| + | </ | ||
| + | |||
| + | |||
| + | ===== Hausaufgaben auf 9. Januar 2023 ===== | ||
| + | * Verschlüsselte Zip-Datei mit passwort ' | ||
| + | * Python code, der das Dithering ausführt, nach Binary konvertiert und eine 96kB grosse Binärdatei schreibt. | ||
| + | * Input-Bild | ||
| + | * Output-Datei (binär, 96kB) | ||
| + | |||
| + | |||
| + | ==== Überprüfung der Binärdatei ==== | ||
| + | <code python readBinary.py> | ||
| + | import cv2 | ||
| + | import sys | ||
| + | import os | ||
| + | import numpy as np | ||
| + | |||
| + | file = " | ||
| + | if len(sys.argv)> | ||
| + | file = sys.argv[1] | ||
| + | if not os.path.exists(file): | ||
| + | raise f" | ||
| + | |||
| + | def readData(file): | ||
| + | with open(file, " | ||
| + | bindata = f.read() | ||
| + | img = np.zeros((480, | ||
| + | for y in range(480): | ||
| + | for x in range(800): | ||
| + | bit = 7-x%8 | ||
| + | byte = x//8+y*100 | ||
| + | bw = (bindata[byte] >> bit) & 1 | ||
| + | rw = (bindata[byte+48000] >> bit) & 1 | ||
| + | if (bw==1 and rw==1): | ||
| + | img[y][x][0] = 255 | ||
| + | img[y][x][1] = 255 | ||
| + | img[y][x][2] = 255 | ||
| + | elif rw==0: | ||
| + | img[y][x][2] = 255 | ||
| + | return img | ||
| + | |||
| + | |||
| + | |||
| + | img = readData(file) | ||
| + | cv2.imshow(" | ||
| + | cv2.waitKey(5000) | ||
| + | </ | ||