[PYTHON] Die Geschichte der Ausgabe des Planetarium-Meisters im PDF-Format mit Pycairo

Dieser Artikel wurde gemäß dem Adventskalender verfasst, der von einem DMM-Gruppenkandidaten verfasst wurde, der 2020 seinen Abschluss gemacht hat.

Adventskalender für Absolventen der DMM Group '20 2019

Ich bedauere, dass ich etwas mehr Selbsteinführung oder so etwas hätte schreiben sollen, aber nachdem ich die folgenden Inhalte geschrieben habe, war die Entwicklung des Planetariums eine ziemlich zentrale Aktivität in meinem Studentenleben, daher dieser Artikel Ich werde mich stattdessen vorstellen.

0. Übersicht

Wie üblich wird ein bestimmter Kreis, der zur faulen Kante gehört, das Planetarium auf dem Festival der Technischen Hochschule ausstellen, und ich werde den Sternmeister machen, der für die Herstellung des Lichtquellengeräts erforderlich ist. (Die gesamte Koordinatenumwandlung der an den Sternmeister ausgegebenen Sterne wurde von unserem super super super exzellenten Junior durchgeführt. Ich und dieser Artikel skizzieren es nur.) Ich habe früher einen ähnlichen Master in Java und Gnuplot ausgegeben, aber das Ergebnis war etwas bimyo. Da Gnuplot ein Diagrammanzeigewerkzeug ist, scheint es nicht gut zu sein, feine Punkte wie Planetariumsterne auszugeben. Deshalb habe ich mich dieses Mal entschlossen, den Python-Wrapper Pycairo von cairo, eine Bildverarbeitungsbibliothek auf niedrigerer Ebene, zu verwenden, um den Sternmaster auszugeben. Die gezeichnete (die erste Seite) wird unten gezeigt.

example.png

Durch Drucken dieses PDF-Formats (JIS A4-Format x 12 Blatt) auf ein transparentes Druckpapier, das als OHP-Blatt bezeichnet wird, und anschließendes Entwickeln auf einem Film mit hoher Kontrastleistung, der als Eichhörnchenfilm bezeichnet wird, einem Planetarium-Lichtquellengerät vom Lochtyp Sie können einen Filter erstellen. Dieses Mal ist es das Ziel, diesen Film zu machen.

  1. cairo? Pycairo?

1.1. Was ist Kairo?

cairo ist eine Bibliothek auf niedriger Ebene zum Zeichnen von 2D-Vektorbildern.

Als ich es nachgeschlagen habe, scheint es, dass es in verschiedenen großen Oss verwendet wird.

1.2 Was ist Pycairo?

Wie bereits erwähnt, ist Pycairo der Python-Wrapper von cairo. Dies ist Pycairo, aber ich glaube, dass es relativ wenige japanische Dokumente gibt. Nun, englische Dokumente sind überall im Internet verfügbar, daher habe ich kein Problem mit der Informationsmenge.

Wenn Sie im Internet Fragen haben, können Sie diese Dokumente lesen und ausprobieren. Insbesondere wenn Sie das Kairo-Tutorial lesen, können Sie das Funktionsprinzip der Kairo-Bibliothek selbst verstehen. Es ist daher ein Muss.

3. Umweltbau

3.1 Vorbereitung

Bitte installieren Sie python3 und numpy. (Verfahren weggelassen) Es wird auch empfohlen, virtualenv und Jupyter Notebook (Colaboratory-Erweiterung) zu installieren.

3.2. Pycairo installieren

Vervollständigen Sie mit dem folgenden Befehl ohne besondere

pip install pycairo

4. Wie benutzt man Pycairo?

Es werden nur die Funktionen aufgelistet, die für die Entwicklung des Sternmeisters verwendet werden.

4.1 Vorbereitung

4.1.1 A4-Größe zeichnen

Die Größe von JIS A4 wird als "210 mm x 297 mm" angegeben und in metrischen Methoden erläutert, während Pycairo als "1pt = 1/72 von 1 Zoll" für 1pt, die kleinste Einheit, und Yard-Pfund angegeben wird. Ich fühle mich im Gesetz mörderisch. Daher haben wir keine andere Wahl, als eine Überbrückungsfunktion zwischen der metrischen Methode und der Yard-Pound-Methode zu definieren.

def inch(meter):
  return 0.0393701 * meter * 72.0

4.1.2. Vektorisierung des RGB-Strings

In Pycairo werden RGB-Farbinformationen als numerischer Wert (0,0 bis 1,0) übergeben. Da dies jedoch problematisch ist, definieren wir auch eine Funktion zum Konvertieren der RGB-Zeichenfolge in einen Vektor.

def color(color_string):
  return np.array([int(color_string[1:3], 16), int(color_string[3:5], 16), int(color_string[5:7], 16)])

4.1.3 Grundzeichnung

def draw_face(context, color_as_vector, width=100, height=100, margine=0):
  context.save()

  context.set_source_rgb(
      color_as_vector[0], 
      color_as_vector[1],
      color_as_vector[2])
  context.translate(margine, margine) #Gehen Sie zum Zeichnen zur Referenzkoordinate (Referenzpunkt)
  context.rectangle(0,0,width, height) #Zeichnen Sie, indem Sie jeden Parameter vom Referenzpunkt aus übergeben
  context.fill()

  context.restore()

with cairo.PDFSurface("example.pdf", canvas_width, canvas_height) as surface:
  for face_num in range(12):
    context = cairo.Context(surface)
    context.scale(1, 1)

    draw_face(context,
              color_as_vector=color('#000000'), 
              width=canvas_width-inch(30),
              height=canvas_height-inch(30),
              margine=inch(15))
    
    surface.show_page() #Erstellen Sie eine neue Seite&Schalten

Erstellen Sie ein PDF-Objekt mit cairo.PDFSurface. Andere sind "cairo.PSSurface", "cairo.SVGSurface" und "cairo.ImageSurface". Surface.show_page ist auch eine Funktion zum Erstellen einer neuen Seite derselben Größe im PDF-Format. Beachten Sie dann, dass der Prozess zum Erstellen der Figur zwischen "context.save" und "context.restore" geschrieben wird.

4.1.4 Vorbereitung der Quelldaten

Dieses Mal habe ich eine CSV-Datei von meinem Junior erhalten, daher werde ich sie als Daten des Sternenkatalogs importieren.

def gen_star_catalogue(file_name=None, face_num=0):
  face_vector = [[] for _ in range(face_num)]

  with open(file_name, mode='r') as csv_file:
    for line in csv.reader(csv_file, delimiter=' '):
      face_vector[int(line[0])].append([ast.literal_eval(line[1]),
                                        ast.literal_eval(line[2]),
                                        ast.literal_eval(line[3])])
  
  for face in range(face_num):
      face_vector[face] = np.array(face_vector[face])
      
  return face_vector

4.2. Zeichnen eines regulären Polygons

Dieses Mal gebe ich eine Figur eines regulären Fünfecks aus, aber um die Flexibilität des Codes zu erhöhen, implementiere ich einen Code, der eine Reihe von regulären Polygonen aus Dreiecken oder mehr ausgibt.

スクリーンショット 2019-11-26 16.56.55.png

Angenommen, ein reguläres Polygon mit einem umschreibenden Kreis mit einem Radiusradius, der auf center_pos zentriert ist. Berechnen Sie die Koordinaten jedes Scheitelpunkts der n-seitigen Form entsprechend und geben Sie dann die Scheitelpunktgruppe multipliziert mit der Rotationsmatrix aus, die sich an einem beliebigen Punkt in den beiden Dimensionen um ein beliebiges Raduis dreht.

Erzeugung eines positiven N-seitigen Scheitelpunktvektors


def gen_regular_polygon(center_pos=None, n=3, radius=1, rotate=0):
  theta = 2 * math.pi / n
  rot_rad = 2 * math.pi * rotate / 360.0

  verts = np.array([[[math.cos(i*theta) * radius + center_pos[0]],
                     [math.sin(i*theta) * radius + center_pos[1]],
                     [1]]
                    for i in range(n)])

  rcos = math.cos(rot_rad)
  rsin = math.sin(rot_rad)
  r31 = -center_pos[0]*rcos + center_pos[1]*rsin + center_pos[0]
  r32 = -center_pos[0]*rsin - center_pos[1]*rcos + center_pos[1]

  rot_vec = np.array([[rcos, -rsin, r31],
                      [rsin, rcos, r32],
                      [0, 0, 1]])
  
  verts = np.concatenate([[np.dot(rot_vec, vert)] for vert in verts])
  
  verts = np.apply_along_axis(lambda x: np.array([x[0], x[1]]), arr=verts, axis=1).reshape([n, 2])
  
  return verts

Wenn Sie es zu einem 50-seitigen Polygon machen, wird ein Polygon in der Nähe eines Kreises gezeichnet, wie in der folgenden Abbildung gezeigt. スクリーンショット 2019-11-26 17.32.56.png

4.3. Erstellen eines Randes

Sie können es mit der Kraft der Mathematik vermasseln. Ich verwende jedoch nur einfache Formeln.

\vec{n}=\frac{\vec{oc}}{|\vec{oc}|}
\vec{m_a}=len\cdot\vec{n}+\vec{a}
\vec{m_b}=len\cdot\vec{n}+\vec{b}

Danach können Sie einen Rand erstellen, indem Sie diese der Reihe nach verbinden und eine Linie zeichnen.

def draw_margines(context=None, verts=None, center_pos=None, edge_size=1, line_color_as_vec=None, frame_width=1, margin_face_num_list=None):
  vert_multi = verts.repeat(2, axis=0)
  vert_pairs = np.roll(vert_multi, -2).reshape([verts.shape[0], 2, verts.shape[1]])

  midpoints = np.apply_along_axis(func1d=lambda x: np.sum(a=x, axis=0)/2, axis=1, arr=vert_pairs)
  orth_vecs = midpoints - center_pos
  euclid_dists = np.mean(np.apply_along_axis(func1d=lambda x: np.linalg.norm(x), axis=1, arr=orth_vecs))

  normals = orth_vecs / euclid_dists
  normals_pairs = normals.repeat(2, axis=0).reshape([normals.shape[0], 2, 2])

  edges_arr = edge_size * normals_pairs + vert_pairs

  # [Ein Ende A.,Kante Eine Seitenecke,Kante B Seitenecke,Ein Ende B.]Ordnen Sie dies in der Reihenfolge an und übergeben Sie es an den Kontext
  edges_arr = np.array([[vert_pairs[x,0], edges_arr[x,0], edges_arr[x,1], vert_pairs[x,1]] for x in range(edges_arr.shape[0])])

  context.save()
  for edges in edges_arr:
    first_edge = edges[0]
    context.move_to(first_edge[0], first_edge[1])
    for edge in edges[1:]:
      context.line_to(edge[0], edge[1])
    context.set_source_rgb(line_color_as_vec[0],line_color_as_vec[1],line_color_as_vec[2])
    context.set_line_width(frame_width)
    context.stroke()
  context.restore()

4.4. Punktausgabe

Ist es genauer, "Kreis" -Ausgabe als Punktausgabe zu sagen?

def draw_stars(context=None, stars=None, radius=1.0, center_pos=None, brightness=1.0, color_as_vector=None):
  context.save()

  for star in stars:
    context.set_source_rgb(color_as_vector[0], 
                           color_as_vector[1], 
                           color_as_vector[2])
    context.arc(star[0]*radius+center_pos[0],
                star[1]*radius+center_pos[1],
               np.math.sqrt(star[2]) *brightness,
                0, 2*math.pi)
    context.fill()

  context.restore()

4.5 Zeichenausgabe mit Schriftarten

Es ist möglich, die im Betriebssystem installierte Schriftart zu verwenden. Lassen Sie uns den Schriftnamen im Voraus in context.select_font_face festlegen. Vielleicht ohne zeichnen.

def draw_text(context=None, text=None, font_size=1, pos_as_vec=None, rotate=0, color_as_vec=None):
  context.save()
  context.set_font_size(font_size)
  context.move_to(pos_as_vec[0], pos_as_vec[1]) #Zum Zeichenpunkt gehen
  context.rotate(2*math.pi*rotate/360) #Drehung
  context.set_source_rgb(color_as_vec[0], color_as_vec[1], color_as_vec[2])
  context.show_text(text) #Zeichen zeichnen
  context.restore()

with cairo.PDFSurface("example.pdf", canvas_width, canvas_height) as surface:
  for face_num in range(12):
    context = cairo.Context(surface)
    context.scale(1, 1)
    context.select_font_face("Futura")

    draw_text(context=context,
              text='Face/{:0=2}'.format(face_num+1),
              font_size=100,
              pos_as_vec=np.array([inch(250),inch(170)]),
              rotate=-90,
              color_as_vec=color("#ffffff"))
    
    draw_text(context=context,
              text="Copyright(C) 2019 Space Science Research Club, National Institute of Technology, Kitakyushu College All rights reserved.",
              font_size=10,
              pos_as_vec=np.array([inch(40),inch(193)]),
              rotate=0,
              color_as_vec=color("#ffffff"))
    
    surface.show_page()

5. Zusammenfassung

Vergleichen Sie abschließend das diesmal gezeichnete Bild mit dem zuletzt mit Gnuplot gezeichneten Bild. スクリーンショット 2019-12-01 11.21.00.png

Die Schwarz-Weiß-Inversion wird aufgrund des unterschiedlichen Verwendungszwecks des Masters abgeleitet. Selbst wenn sie abgezogen wird, werden nicht nur die Sterne als runde Punkte dargestellt, sondern auch der Unterschied in der Note jedes Sterns wird sorgfältig als Größe des Kreises verwendet. Sie können sehen, dass es in angezeigt werden kann. Wie Sie sehen können, handelt es sich bei Pycairo um eine Bibliothek auf relativ niedriger Ebene, weshalb es sich um eine Bibliothek handelt, die eine flexible grafische Anzeige ermöglicht. Da die Pycairo-Bibliothek selbst so konzipiert ist, dass sie durch prozedurale Beschreibung gezeichnet wird, ist es beim Schreiben von Code etwas schwierig, den Teil zum Zeichnen von Nebenwirkungen von der reinen Beschreibung im Sinne der funktionalen Sprache zu trennen. Ich fühlte es im Nacken. Das fühlt sich wie eine technische Herausforderung an. Ich denke jedoch, dass die Möglichkeit, mithilfe von Pycairo, das PDF-Dateien ausgeben kann, flexible Grafikdokumente zu erstellen, auf allgemeine Arbeiten angewendet werden kann.

Zum Schluss füge ich die Skizze des diesmal gezeichneten PDF-Dokuments und den gesamten Quellcode ein. Dieses Mal habe ich Goole Colaboratory mit Jupyter Notebook verwendet, damit die Quelle entsprechend angepasst wird.

スクリーンショット 2019-12-01 14.36.24.png

import cairo, math, csv, ast
from IPython.display import SVG, display
import numpy as np

#Zeichne eine Schnur
def draw_text(context=None, text=None, font_size=1, pos_as_vec=None, rotate=0, color_as_vec=None):
  context.save()
  context.set_font_size(font_size)
  context.move_to(pos_as_vec[0], pos_as_vec[1])
  context.rotate(2*math.pi*rotate/360)
  context.set_source_rgb(color_as_vec[0], color_as_vec[1], color_as_vec[2])
  context.show_text(text)
  context.restore()

#Hintergrundfarbe zeichnen
def draw_face(context, color_as_vector, width=100, height=100, margine=0):
  context.save()

  context.set_source_rgb(
      color_as_vector[0], 
      color_as_vector[1],
      color_as_vector[2])
  context.translate(margine, margine)
  context.rectangle(0,0,width, height)
  context.fill()

  context.restore()

#Zeichnung des Scheitelpunktvektors
def draw_frame(
    context,
    verts_array,
    fill_color_as_rgb_vec,
    frame_color_as_rgb_vec,
    frame_width):

  if verts_array.shape[0] < 3:
    print("ERROR")
    exit()
  else:
    context.save()

    first_vert = verts_array[0]
    tail_vert_array = verts_array[1:]

    context.move_to(first_vert[0], first_vert[1])

    for vert in tail_vert_array:
      context.line_to(vert[0], vert[1])

    context.close_path()

    context.set_source_rgb(
        fill_color_as_rgb_vec[0],
        fill_color_as_rgb_vec[1],
        fill_color_as_rgb_vec[2])
    context.fill_preserve()

    context.set_source_rgb(
        frame_color_as_rgb_vec[0],
        frame_color_as_rgb_vec[1],
        frame_color_as_rgb_vec[2]
    )
    context.set_line_width(frame_width)
    context.stroke()

    context.restore()

#Zeichne einen Stern
def draw_stars(context=None, stars=None, radius=1.0, center_pos=None, brightness=1.0, color_as_vector=None):
  context.save()

  for star in stars:
    context.set_source_rgb(color_as_vector[0], 
                           color_as_vector[1], 
                           color_as_vector[2])
    context.arc(star[0]*radius+center_pos[0],
                star[1]*radius+center_pos[1],
               np.math.sqrt(star[2]) *brightness,
                0, 2*math.pi)
    context.fill()

  context.restore()

#Erzeugung eines positiven N-seitigen Scheitelpunktvektors
def gen_regular_polygon(center_pos=None, n=3, radius=1, rotate=0):
  theta = 2 * math.pi / n
  rot_rad = 2 * math.pi * rotate / 360.0

  verts = np.array([[[math.cos(i*theta) * radius + center_pos[0]],
                     [math.sin(i*theta) * radius + center_pos[1]],
                     [1]]
                    for i in range(n)])

  rcos = math.cos(rot_rad)
  rsin = math.sin(rot_rad)
  r31 = -center_pos[0]*rcos + center_pos[1]*rsin + center_pos[0]
  r32 = -center_pos[0]*rsin - center_pos[1]*rcos + center_pos[1]

  rot_vec = np.array([[rcos, -rsin, r31],
                      [rsin, rcos, r32],
                      [0, 0, 1]])
  
  verts = np.concatenate([[np.dot(rot_vec, vert)] for vert in verts])
  
  verts = np.apply_along_axis(lambda x: np.array([x[0], x[1]]), arr=verts, axis=1).reshape([n, 2])
  
  return verts

#Meter-Zoll-Umrechnung
def inch(meter):
  return 0.0393701 * meter * 72.0

#Vektorisierung von Agb-Strings
def color(color_string):
  return np.array([int(color_string[1:3], 16), int(color_string[3:5], 16), int(color_string[5:7], 16)])

#Leimzeichnung
def draw_margines(context=None, verts=None, center_pos=None, edge_size=1, line_color_as_vec=None, frame_width=1, margin_face_num_list=None):
  vert_multi = verts.repeat(2, axis=0)
  vert_pairs = np.roll(vert_multi, -2).reshape([verts.shape[0], 2, verts.shape[1]])

  midpoints = np.apply_along_axis(func1d=lambda x: np.sum(a=x, axis=0)/2, axis=1, arr=vert_pairs)
  orth_vecs = midpoints - center_pos
  euclid_dists = np.mean(np.apply_along_axis(func1d=lambda x: np.linalg.norm(x), axis=1, arr=orth_vecs))

  normals = orth_vecs / euclid_dists
  normals_pairs = normals.repeat(2, axis=0).reshape([normals.shape[0], 2, 2])

  edges_arr = edge_size * normals_pairs + vert_pairs

  edges_arr = np.array([[vert_pairs[x,0], edges_arr[x,0], edges_arr[x,1], vert_pairs[x,1]] for x in range(edges_arr.shape[0])])

  context.save()
  for edges in edges_arr:
    first_edge = edges[0]
    context.move_to(first_edge[0], first_edge[1])
    for edge in edges[1:]:
      context.line_to(edge[0], edge[1])
    context.set_source_rgb(line_color_as_vec[0],line_color_as_vec[1],line_color_as_vec[2])
    context.set_line_width(frame_width)
    context.stroke()
  context.restore()

  inner_product = np.apply_along_axis(lambda x: np.dot(x, np.array([0,1])), axis=1, arr=normals)
  thetas = np.apply_along_axis(lambda x: np.arccos(x)/(2*np.pi)*360, axis=0, arr=inner_product)
  sign = np.apply_along_axis(lambda x: -1 if x[0]>0 else 1, axis=1, arr=normals) 
  signed_thetas = sign * thetas
  print(signed_thetas)

  context.save()
  for index, theta in enumerate(signed_thetas):
    draw_text(context=context,
              text='Face/{:0=2}'.format(margin_face_num_list[index]),
              font_size=15,
              pos_as_vec=orth_vecs[index] + center_pos + normals[index] * edge_size*0.7,
              rotate=theta,
              color_as_vec=color("#ffffff"))
  context.restore()

#Eine Sternenkarte ausschneiden
def gen_star_catalogue(file_name=None, face_num=0):
  face_vector = [[] for _ in range(face_num)]

  with open(file_name, mode='r') as csv_file:
    for line in csv.reader(csv_file, delimiter=' '):
      face_vector[int(line[0])].append([ast.literal_eval(line[1]),
                                        ast.literal_eval(line[2]),
                                        ast.literal_eval(line[3])])
  
  for face in range(face_num):
      face_vector[face] = np.array(face_vector[face])
      
  return face_vector

#Zuordnung des Kleberzugabeindex
margin_index = [[6, 5, 4, 3, 2],   [7, 6, 1, 3, 8],   [8, 2, 1, 4, 9], 
                [9, 3, 1, 5, 10],  [10, 4, 1, 6, 11], [11, 5, 1, 2, 7],
                [2, 8, 12, 11, 6], [3, 9, 12, 7, 2],  [4, 10, 12, 8, 3], 
                [5, 11, 12, 9, 4], [6, 7, 12, 10, 5], [10, 11, 7, 8, 9]]

#Hyperparameter
normal_scale = 100
canvas_height = inch(210)
canvas_width  = inch(297)
face_center_position = np.array([inch(125), inch(105)])
face_radius = inch(74.85727113)
face_mid_dist = inch(77.15727113)
face_rotate_list = [0]+[180]*10+[0]

#Entwurf eines Tabellendatenarrays
star_catalogue = gen_star_catalogue(file_name="./starout.txt", face_num=12)

#Ausgabe der PDF-Datei
with cairo.PDFSurface("example.pdf", canvas_width, canvas_height) as surface:
  for face_num in range(12):
    context = cairo.Context(surface)
    context.scale(1, 1)
    context.select_font_face("Futura")

    draw_face(context,
              color_as_vector=color('#000000'), 
              width=canvas_width-inch(30),
              height=canvas_height-inch(30),
              margine=inch(15))

    verts = gen_regular_polygon(
        center_pos=face_center_position,
        n=5,
        radius=face_radius,
        rotate=face_rotate_list[face_num])

    draw_frame(context=context,
               verts_array=verts,
               fill_color_as_rgb_vec=color('#ffffff'),
               frame_color_as_rgb_vec=color('#000000'),
               frame_width=0.02)
    
    draw_margines(context=context,
                  verts=verts,
                  center_pos=face_center_position,
                  edge_size=inch(10),
                  line_color_as_vec=color("#ff0000"),
                  frame_width=1,
                  margin_face_num_list=margin_index[face_num])
    
    stars = star_catalogue[face_num]

    draw_stars(context=context,
               stars=stars,
               radius=face_mid_dist,
               center_pos=face_center_position,
               brightness=0.5,
               color_as_vector=color('#000000'))
    
    draw_text(context=context,
              text='Face/{:0=2}'.format(face_num+1),
              font_size=100,
              pos_as_vec=np.array([inch(250),inch(170)]),
              rotate=-90,
              color_as_vec=color("#ffffff"))
    
    draw_text(context=context,
              text="Copyright(C) 2019 Space Science Research Club, National Institute of Technology, Kitakyushu College All rights reserved.",
              font_size=10,
              pos_as_vec=np.array([inch(40),inch(193)]),
              rotate=0,
              color_as_vec=color("#ffffff"))
    
    
    surface.show_page()


Nachtrag

Beim Drucken eines Planetarium-Masters verwende ich ein OHP-Blatt, das fast fossil entspricht, aber bei Druckern zu Hause und in der Schule ist das Blatt verstopft und die Druckdichte ist sehr dünn (selbst wenn es in der Umgebung am dunkelsten ist). Es gibt viele solche Dinge. Wenn Sie in diese Situation geraten, können Sie schnell zu einer Druckerei gehen, die OHP-Blätter wie Kinko drucken kann, und hier (zumindest in lokalen Geschäften) können Sie dunkel auf OHP-Blätter drucken. Ist fertig. Beim Drucken von OHP-Blättern unterstützt die Druckerei jedoch in erster Linie nur den Schwarzweißdruck. Selbst wenn dies möglich ist, ist die Farbe superhell, sodass die speziellen Farbinformationen nicht verwendet werden. Seien Sie also in diesem Punkt vorsichtig. Sollte sein. Es ist auch möglich, dass das Blatt und die Hände zum Zeitpunkt des Druckens mit Tinte verschmutzt werden, nicht nur für OHP-Blätter. Daher ist es eine gute Idee, eine Zone bereitzustellen, die nicht wie in der obigen Abbildung gezeigt herumdruckt.

Recommended Posts

Die Geschichte der Ausgabe des Planetarium-Meisters im PDF-Format mit Pycairo
Die Geschichte der Teilnahme an AtCoder
Die Geschichte des "Lochs" in der Akte
Die Geschichte eines Fehlers in PyOCR
Die Geschichte eines Parksensors in 10 Minuten mit dem GrovePi + Starter Kit
Die Geschichte des tiefen Lernens mit TPU
[Automatisierung] Extrahieren Sie die Tabelle als PDF mit Python
Die Geschichte, das optimale n in N Faust zu finden
Die Geschichte des Lesens von HSPICE-Daten in Python
Die Geschichte der Anzeige von Mediendateien in Django
Die Geschichte, die zur Installation von Pip passt
Die Geschichte des Stoppens des Produktionsdienstes mit dem Befehl hostname
Die Geschichte des Aufbaus der schnellsten Linux-Umgebung der Welt
Die Geschichte des Teilens der Pyenv-Umgebung mit mehreren Benutzern
Konvertieren Sie das Bild in .zip mit Python in PDF
Lesen Sie die Linkliste im CSV-Format mit dem Graph-Tool
Die Geschichte von sys.path.append ()
Eine Geschichte über die Änderung des Master-Namens von BlueZ
Die Geschichte des Debuggens in der lokalen Umgebung, weil die Kompilierung mit Read the Docs nicht funktioniert hat
Ablauf des Extrahierens von Text in PDF mit der Cloud Vision API
Versuchen Sie, COVID-19 Tokyo-Daten mit Python zu kratzen
Die Geschichte der Implementierung des Themas Facebook Messenger Bot mit Python
So geben Sie ein Dokument im PDF-Format mit Sphinx aus
Berechnen Sie mit Python Millionen von Stellen in der Quadratwurzel von 2
Die Geschichte der Anzeige von Bildern mit OpenCV oder PIL (nur)
Die Geschichte eines Rubinisten, der mit Python :: Dict-Daten mit Pycall kämpft
[Homologie] Zählen Sie mit Python die Anzahl der Löcher in den Daten
Die Geschichte, wie man mit discord.py einen Fragenkasten-Bot erstellt
Die Geschichte der Herabstufung der Version von Tensorflow in der Demo von Mask R-CNN.
Die Geschichte des Baus von Zabbix 4.4
Zusammenfassung des Zeichenkettenformats in Python3 Gibt an, ob mit dem alten oder dem neuen Modell gelebt werden soll
Die Geschichte des Erstellens eines Bots, der aktive Mitglieder in einem bestimmten Slack-Kanal mit Python anzeigt
Verarbeiten Sie den Inhalt der Datei der Reihe nach mit einem Shell-Skript
Eine Geschichte, die mit der Installation der maschinellen Lernbibliothek JAX zusammenhängt
Geben Sie den Inhalt von ~ .xlsx im Ordner mit Python in HTML aus
Formatieren Sie die CSV-Datei "Nationalfeiertag" des Kabinetts mit Pandas
Die Geschichte der Visualisierung beliebter Qiita-Tags mit Bar Chart Race
Visualisieren Sie die Häufigkeit von Wortvorkommen in Sätzen mit Word Cloud. [Python]
Die Geschichte, ein Modul zu erstellen, das E-Mails mit Python überspringt
Gewinner des Mannes, der den höchsten Grad an Ähnlichkeit mit der ursprünglichen Geschichte in "Der Gewinner desjenigen, der das stinkendste Hototogisu geschrieben hat" hat.
Die Geschichte von Python und die Geschichte von NaN
Beherrschen Sie die umfangreichen Funktionen von IPython
Beherrsche den Typ mit Python [Python 3.9 kompatibel]
Die Geschichte des erneuten Bereitstellens des Anwendungsservers
Die Geschichte des Exportierens eines Programms
Beherrsche das schwache Ref-Modul in Python
Eine Geschichte, die die Gegenwart von Qiita mit Qiita API + Elasticsearch + Kibana visualisiert
Die Geschichte, wie man mit Python einen 100-Yen-Frühstücks-Bot für die Universität macht
Spielen Sie den Kommentar des Nico Nico-Videos auf dem Terminal in Verbindung mit dem Video ab
Erhalten Sie eine Liste der Ergebnisse der Parallelverarbeitung in Python mit Starmap
Die Geschichte einer Soundkamera mit Touch Designer und ReSpeaker
Zeigen Sie den Status der COVID 19-Infektion in Japan mit Splunk an (GitHub-Version).
Ich habe einen Fehler beim Abrufen der Hierarchie mit MultiIndex von Pandas gemacht
Mit dem Aufkommen von systemd-homed im Jahr 2020 wird sich die Linux-Benutzerverwaltung dramatisch ändern.
Die Geschichte des Versuchs, SSH_AUTH_SOCK mit LD_PRELOAD auf dem Bildschirm veraltet zu halten
Die Geschichte der Verwendung von mysqlclient, da PyMySQL nicht mit Django 2.2 verwendet werden kann
Die Geschichte des sofortigen Herunterladens des PDF-Dokuments der grundlegenden Information Engineer-Prüfung mit Python