[PYTHON] Grafikprogrammierung

Schreiben wir ein Programm mit einem Bild

Schreiben Sie das folgende Bild (picntu.png).

image

Sie können dieses Bild analysieren und ausführen. Die Oberseite ist der Teilelagerbereich. Führen Sie die Unterseite. Gehe von links oben nach rechts und gehe nach unten. Wie bei Python wird es eingerückt, um Blöcke darzustellen. Wie Schildkrötengrafiken ist es zuerst an den Koordinaten (x = 0, y = 0) und zeigt nach Norden. Sie können es mit einem Befehl verschieben.

Probe ausführen

bash


docker run -it --rm tsutomu7/picntu ./picntu picntu.png
>>>
0 0
0 2
2 2
2 0

Teilebeschreibung

--go: Mach einen Schritt. (Zuerst bei (0, 0).) --back: Gehen Sie einen Schritt zurück.

  • links: Nach links abbiegen. (Zuerst nach Norden ausgerichtet.)
  • rechts: Biegen Sie rechts ab. --def Number: Definiert eine Zahlenunterroutine. Der Umfang der Definition wird durch den Einzug bestimmt. --run Number: Führt eine Zahlenunterroutine aus. --lop Number: Wiederholen Sie diesen Vorgang für die Nummer. Der Wiederholungsbereich wird durch die Einrückung bestimmt. --pri Number: Gibt eine Nummer aus. --if = Number: Bestimmt, ob die Nummer dem Wert im Speicher entspricht. Der Bereich wird durch den Einzug bestimmt. --if <number: Legt fest, ob die Nummer den Wert im Speicher überschreitet. --if> Number: Bestimmt, ob die Nummer kleiner als der Speicherwert ist. --set Number: Legt die Nummer im Speicher fest. --add Number: Fügt dem Speicher eine Nummer hinzu. --sub Number: Subtrahiert die Nummer vom Speicher.
  • Wenn Sie die Nummer leer lassen, wird der Speicherwert verwendet. Sie können nur eine Nummer im Speicher haben.
  • Die Zahlen reichen von 0 bis 9 und 10 kehrt zu 0 zurück. ――Die folgenden Literale können anstelle von Zahlen verwendet werden.

wörtlich

--Number: Die Zahlen reichen von 0 bis 9, wobei 10 auf 0 zurückkehrt. --i, j: Lop Counter. Die erste Schleife ist i und die zweite Schleife ist j. --x, y: Repräsentiert Koordinaten. --r: Zeigt die Ausrichtung an. Nord = 0, Ost = 1. Süd = 2, West = 3.

Beispielbeschreibung

Stichprobe


def 0 | pri x | pri y
lop 4 | run 0
      | lop 2 | go
      | right

Erläuterung

  • Das Folgende ist Unterprogramm 0
  • Ausgabe x und y
  • Wiederholen Sie die folgenden 4 Male
  • Unterprogramm 0 aufrufen ――Zwei vorwärts (2 Schritte vorwärts)
  • Schau nach rechts

Führen Sie ein beliebiges Bild aus

Wenn Sie die Bilddatei in / tmp ablegen, können Sie sie wie folgt ausführen. Sie können die Größe des Bildes ändern, jedoch nicht die Position der Teile.

bash


docker run -it --rm -v /tmp:/tmp tsutomu7/picntu ./picntu /tmp/Name der Bilddatei

Wenn Sie ein zweites Argument angeben, können Sie die aus dem Bild erstellte Python sehen.

bash


docker run -it --rm tsutomu7/picntu ./picntu picntu.png 0
>>>
i, j, x, y, r, c = 0, 0, 0, 0, 0, 0
dx, dy = [0, 1, 0, 9], [1, 0, 9, 0]
def f0():
    print("\n%d" % x, end="");print(" %d" % y, end="");
for i in range(4):
    f0();
    for j in range(2):
        globals()["x"], globals()["y"] = (x + dx[r]) % 10, (y + dy[r]) % 10;
    globals()["r"] = (r + 1) % 4;

0 0
0 2
2 2
2 0

Im Browser ausführen

Gehen Sie wie folgt vor, geben Sie die Datei an und drücken Sie "Ausführen".

bash


docker run -it -d -p 5000:5000 tsutomu7/picntu
firefox localhost:5000

image

Analyseprogramm

picntu.py


import cv2, sys, unionfind

if len(sys.argv) <= 1:
    print('%s image_file' % sys.argv[0][:-3])
    exit()
im = cv2.imread(sys.argv[1])
imtop = im[5:13, 4:86] # top of card
r1 = cv2.matchTemplate(im[160:], imtop, cv2.TM_CCOEFF_NORMED)
scom = 'go back lop if_eq set ' \
       'left right else if_lt add ' \
       'def run pri if_gt sub'.split()
slit = '0 1 i 2 3 j 4 5 x 6 7 y 8 9 r'.split()
coms = [] # command list
for y, x in [(i, j) for i, p in enumerate(r1 >= 0.999)
                    for j, q in enumerate(p) if q]:
    imcom = im[y+173:y+197,x+9:x+49]
    r2 = cv2.matchTemplate(im[:150,:460], imcom, cv2.TM_CCOEFF_NORMED)
    _, v, _, (x2, y2) = cv2.minMaxLoc(r2)
    if v < 0.999:
        continue
    i = (x2+33)//92 + (y2+8)//52*5
    arg = 'c'
    if i > 7 or (i+1)%6 > 2:
        r3 = cv2.matchTemplate(im[9:147,465:545], im[y+173:y+193,x+53:x+70],
                               cv2.TM_CCOEFF_NORMED)
        _, v, _, (x3, y3) = cv2.minMaxLoc(r3)
        if v >= 0.999:
            arg = slit[(x3+8)//26 + (y3+7)//25*3]
    coms.append([-1, -1, scom[i], arg, x, y])

n = len(coms)
ux = unionfind.unionfind(n)
uy = unionfind.unionfind(n)
for i in range(n):
    coi = coms[i]
    for j in range(i+1, n):
        coj = coms[j]
        if abs(coi[4] - coj[4]) < 12:
            ux.unite(i, j)
        if abs(coi[5] - coj[5]) < 12:
            uy.unite(i, j)
for i, g in enumerate(sorted(ux.groups(), key=lambda g: coms[g[0]][4])):
    for j in g:
        coms[j][1] = i
for i, g in enumerate(sorted(uy.groups(), key=lambda g: coms[g[0]][5])):
    for j in g:
        coms[j][0] = i

ex = []
ex.append('i, j, x, y, r, c = 0, 0, 0, 0, 0, 0\n')
ex.append('dx, dy = [0, 1, 0, 9], [1, 0, 9, 0]\n')
pr, s, lp = 0, ' ', []
for v, t, com, a, _, _ in sorted(coms):
    if v > pr or s[-1] == ':':
        ex.append('\n' + '    '*t)
    if com == 'go':
        s = 'globals()["x"], globals()["y"] = (x + dx[r]) % 10, (y + dy[r]) % 10;'
    elif com == 'back':
        s = 'globals()["x"], globals()["y"] = (x + dx[(r + 2) % 4]) % 10, (y + dy[(r + 2) % 4]) % 10;'
    elif com == 'left':
        s = 'globals()["r"] = (r + 3) % 4;'
    elif com == 'right':
        s = 'globals()["r"] = (r + 1) % 4;'
    elif com == 'def':
        s = 'def f%s():' % a
    elif com == 'run':
        s = 'f%s();' % a
    elif com == 'lop':
        while lp and lp[-1] >= t:
            lp.pop()
        s = 'for %s in range(%s):' % ('ijklmn'[len(lp)], a)
        lp.append(t)
    elif com == 'else':
        s = 'else:'
    elif com == 'pri':
        s = 'print("%s%%d" %% %s, end="");' % (' ' if v == pr and s[0] == 'p' else '\\n', a)
    elif com == 'if_eq':
        s = 'if c == %s:' % a
    elif com == 'if_lt':
        s = 'if c < %s:' % a
    elif com == 'if_gt':
        s = 'if c > %s:' % a
    elif com == 'set':
        s = 'globals()["c"] = %s;' % a
    elif com == 'add':
        s = 'globals()["c"] += %s;' % a
    elif com == 'sub':
        s = 'globals()["c"] -= %s;' % a
    ex.append(s)
    pr = v
if len(sys.argv) > 2:
    print(''.join(ex))
exec(''.join(ex))
print()

Referenz: Spielen mit einer Schildkröte mit Schildkrötengrafiken (Teil 1) "Cubetto", wo auch 3-Jährige das Programmieren mit Spielzeug lernen können