create_markers.py
Go to the documentation of this file.
1 #!/usr/bin/python
2 
3 import os, sys, argparse
4 import subprocess
5 import imp, importlib
6 
7 # Hack if a user has 'em' instead of 'empy' installed with pip
8 # If the module em doesn't have the expand function use the full path
9 em = None
10 for path in sys.path:
11  filename = os.path.join(path, 'em.py')
12  if os.path.exists(filename):
13  em = imp.load_source('em', filename)
14  if "expand" in dir(em):
15  break
16 # For-else: else is called if loop doesn't break
17 else:
18  print "ERROR: could not find module em, please sudo apt install python-empy"
19  exit(2)
20 
21 import cv2
22 import cv2.aruco as aruco
23 
24 """
25 Generate a PDF file containaing one or more fiducial marker for printing
26 """
27 
28 def checkCmd(cmd, package):
29  rc = os.system("which %s > /dev/null" % cmd)
30  if rc != 0:
31  print """This utility requires %s. It can be installed by typing:
32  sudo apt install %s""" % (cmd, package)
33  sys.exit(1)
34 
35 def genSvg(id, dicno, paper_size):
36  return em.expand("""<svg width="@(paper_width)mm" height="@(paper_height)mm"
37  version="1.1"
38  xmlns:xlink="http://www.w3.org/1999/xlink"
39  xmlns="http://www.w3.org/2000/svg">
40 
41  <rect x="@((paper_width - fid_len)/2)mm" y="@((paper_height - fid_len)/2)mm" width="@(fid_len)mm" height="4.0mm" style="stroke:none; fill:black"/>
42  <rect x="@((paper_width - fid_len)/2)mm" y="@((paper_height + fid_len)/2 - 4)mm" width="@(fid_len)mm" height="4.0mm" style="stroke:none; fill:black"/>
43  <rect x="@((paper_width - fid_len)/2)mm" y="@((paper_height - fid_len)/2)mm" width="4.0mm" height="@(fid_len)mm" style="stroke:none; fill:black"/>
44  <rect x="@((paper_width + fid_len)/2 - 4)mm" y="@((paper_height - fid_len)/2)mm" width="4.0mm" height="@(fid_len)mm" style="stroke:none; fill:black"/>
45 
46  <image x="@((paper_width - fid_len)/2)mm" y="@((paper_height - fid_len)/2)mm" width="@(fid_len)mm" height="@(fid_len)mm" xlink:href="/tmp/marker@(id).png" />
47 
48 
49  @{cut = max(fid_len/10 * 1.4, 10)}
50 
51  @{corner_x = (paper_width - fid_len)/2 - cut}
52  @{corner_y = (paper_height - fid_len)/2 - cut}
53  <line x1="@(corner_x)mm" y1="@(corner_y)mm" x2="@(corner_x + 2)mm" y2="@(corner_y)mm" style="stroke:black"/>
54  <line x1="@(corner_x)mm" y1="@(corner_y)mm" x2="@(corner_x)mm" y2="@(corner_y + 2)mm" style="stroke:black"/>
55 
56  @{corner_x = (paper_width + fid_len)/2 + cut}
57  @{corner_y = (paper_height - fid_len)/2 - cut}
58  <line x1="@(corner_x)mm" y1="@(corner_y)mm" x2="@(corner_x - 2)mm" y2="@(corner_y)mm" style="stroke:black"/>
59  <line x1="@(corner_x)mm" y1="@(corner_y)mm" x2="@(corner_x)mm" y2="@(corner_y + 2)mm" style="stroke:black"/>
60 
61  <text x="@(paper_width/2)mm" y="@(corner_y - 1)mm" text-anchor="middle" style="font-family:ariel; font-size:8;">
62  This line should be exactly @(fid_len/10)cm long.
63  </text>
64  <line x1="@(paper_width/2 - fid_len/2)mm" y1="@(corner_y)mm" x2="@(paper_width/2 + fid_len/2)mm" y2="@(corner_y)mm" style="stroke:black"/>
65  <line x1="@(corner_x)mm" y1="@(paper_height/2 - fid_len/2)mm" x2="@(corner_x)mm" y2="@(paper_height/2 + fid_len/2)mm" style="stroke:black"/>
66 
67  @{corner_x = (paper_width - fid_len)/2 - cut}
68  @{corner_y = (paper_height + fid_len)/2 + cut}
69  <line x1="@(corner_x)mm" y1="@(corner_y)mm" x2="@(corner_x + 2)mm" y2="@(corner_y)mm" style="stroke:black"/>
70  <line x1="@(corner_x)mm" y1="@(corner_y)mm" x2="@(corner_x)mm" y2="@(corner_y - 2)mm" style="stroke:black"/>
71 
72  <line x1="@(corner_x)mm" y1="@(paper_height/2 - fid_len/2)mm" x2="@(corner_x)mm" y2="@(paper_height/2 + fid_len/2)mm" style="stroke:black"/>
73  <line x1="@(paper_width/2 - fid_len/2)mm" y1="@(corner_y)mm" x2="@(paper_width/2 + fid_len/2)mm" y2="@(corner_y)mm" style="stroke:black"/>
74 
75  @{corner_x = (paper_width + fid_len)/2 + cut}
76  @{corner_y = (paper_height + fid_len)/2 + cut}
77  <line x1="@(corner_x)mm" y1="@(corner_y)mm" x2="@(corner_x - 2)mm" y2="@(corner_y)mm" style="stroke:black"/>
78  <line x1="@(corner_x)mm" y1="@(corner_y)mm" x2="@(corner_x)mm" y2="@(corner_y - 2)mm" style="stroke:black"/>
79 
80  <text x="@(paper_width/2)mm" y="@((paper_height + fid_len)/2 + 30)mm" text-anchor="middle" style="font-family:ariel; font-size:24;">@(id) D@(dicno)</text>
81 
82 </svg>
83 """, {"id": id, "dicno": dicno, "paper_width": paper_size[0], "paper_height": paper_size[1], "fid_len": 140.0})
84 
85 def genMarker(i, dicno, paper_size):
86  print " Marker %d\r" % i,
87  sys.stdout.flush()
88  aruco_dict = aruco.Dictionary_get(dicno)
89  img = aruco.drawMarker(aruco_dict, i, 2000)
90  cv2.imwrite("/tmp/marker%d.png" % i, img)
91  svg = genSvg(i, dicno, paper_size)
92  cairo = subprocess.Popen(('cairosvg', '-f', 'pdf', '-o', '/tmp/marker%d.pdf' % i, '/dev/stdin'), stdin=subprocess.PIPE)
93  cairo.communicate(input=svg)
94  # This way is faster than subprocess, but causes problems when cairosvg is installed from pip
95  # because newer versions only support python3, and opencv3 from ros does not
96  # cairosvg.svg2pdf(bytestring=svg, write_to='/tmp/marker%d.pdf' % i)
97  os.remove("/tmp/marker%d.png" % i)
98 
99 if __name__ == "__main__":
100  checkCmd("pdfunite", "poppler-utils")
101  checkCmd("cairosvg", "python-cairosvg")
102 
103 
104  parser = argparse.ArgumentParser(description='Generate Aruco Markers.')
105  parser.add_argument('startId', type=int,
106  help='start of marker range to generate')
107  parser.add_argument('endId', type=int,
108  help='end of marker range to generate')
109  parser.add_argument('pdfFile', type=str,
110  help='file to store markers in')
111  parser.add_argument('dictionary', type=int, default='7', nargs='?',
112  help='dictionary to generate from')
113  parser.add_argument('--paper-size', dest='paper_size', action='store',
114  default='letter', help='paper size to use (letter or a4)')
115 
116  args = parser.parse_args()
117 
118  outfile = args.pdfFile
119  dicno = args.dictionary
120 
121  markers = range(args.startId, args.endId + 1)
122  pdfs = map(lambda i: "/tmp/marker%d.pdf" % i, markers)
123 
124  if args.paper_size == 'letter':
125  paper_size = (215.9, 279.4)
126  elif args.paper_size == 'a4':
127  paper_size = (210, 297)
128 
129  try:
130  # For a parallel version
131  from joblib import Parallel, delayed
132  Parallel(n_jobs=-1)(delayed(genMarker)(i, dicno, paper_size) for i in markers)
133  except ImportError:
134  # Fallback to serial version
135  for i in markers:
136  genMarker(i, dicno, paper_size)
137 
138  print "Combining into %s" % outfile
139  os.system("pdfunite %s %s" % (" ".join(pdfs), outfile))
140  for f in pdfs:
141  os.remove(f)
142 
143  print '\033[91m' + """After printing, please make sure that the long lines around the marker are
144 EXACTLY 14.0 cm long. This is required for accurate position estimation.""" + '\033[0m'
145 
def genSvg(id, dicno, paper_size)
def checkCmd(cmd, package)
def genMarker(i, dicno, paper_size)


aruco_detect
Author(s): Jim Vaughan
autogenerated on Tue Jun 1 2021 03:03:28