hugin_panorama.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 import os
3 import glob
4 import shutil
5 import subprocess
6 import cv2
7 import rospy
8 import rospkg
9 
10 from sensor_msgs.msg import CompressedImage
11 from cv_bridge import CvBridge
12 from std_srvs.srv import Empty
13 
14 def load_image(filename):
15  img = cv2.imread(filename, -1)
16  if img is None:
17  rospy.logerr("ERROR image file didn't load or doesn't exist: %s" % filename)
18  exit(1)
19  return img
20 
21 class HuginPanorama():
22  def __init__(self):
23  rospy.Service('stitch', Empty, self.stitch_callback)
24  rospy.Service('reset', Empty, self.reset_callback)
25  self.publisher = rospy.Publisher('panorama/compressed', CompressedImage, queue_size=10)
26 
27  # Get the path to where input and output images for the panorama are stored
28  self.images_path = rospy.get_param('~images_path')
29 
30  # Create path if it does not exist
31  if not os.path.exists(self.images_path):
32  os.makedirs(self.images_path)
33 
34  rospy.loginfo('Using working directory: %s'% self.images_path)
35 
36  def stitch_callback(self, data):
37  self.do_stitch()
38  return []
39 
40  def reset_callback(self, data):
41  rospy.loginfo('Clearing images waiting to be stitched.')
42  self.cleanup(delete_images=True)
43  return []
44 
46  """ returns space seperated list of files in the images_path """
47  print(" ".join(os.listdir(self.images_path)))
48  return " ".join(os.listdir(self.images_path))
49 
50  def hugin_stitch(self):
51  files = self.get_image_filenames()
52 
53  if files == None or files == "":
54  rospy.logerr("Did not find any images to stitch in: %s" % self.images_path)
55  return
56 
57  rospy.loginfo("Stitching files: %s" % files)
58 
59  # create project file
60  self.bash_exec('pto_gen -o pano.pto %s' % files)
61  # do cpfind
62  self.bash_exec('cpfind -o pano.pto --multirow --celeste pano.pto')
63  # do clean
64  self.bash_exec('cpclean -o pano.pto pano.pto')
65  # do vertical lines
66  self.bash_exec('linefind -o pano.pto pano.pto')
67  # do optimize locations
68  self.bash_exec('autooptimiser -a -m -l -s -o pano.pto pano.pto')
69  # calculate size
70  self.bash_exec('pano_modify --canvas=AUTO --crop=AUTO -o pano.pto pano.pto')
71  # stitch
72  self.bash_exec('hugin_executor --stitching --prefix=output pano.pto')
73  # compress
74  self.bash_exec('convert output.tif output.png')
75 
76  output_file = os.path.join(self.images_path, 'output.png')
77  if not os.path.isfile(output_file):
78  rospy.logerr('Hugin failed to create a panorama.')
79  return
80 
81  rospy.loginfo('Panorama saved to: %s/output.png' % self.images_path)
82 
83  self.publish_pano()
84  rospy.loginfo('Finished.')
85 
86  def publish_pano(self):
87  img = load_image(os.path.join(self.images_path, 'output.png'))
88  compressed_image = CvBridge().cv2_to_compressed_imgmsg(img)
89  self.publisher.publish(compressed_image)
90 
91  def cleanup(self, delete_images=False):
92  # Hugin project files and output images
93  files_to_be_deleted = ['output.tif', 'output.png', 'pano.pto']
94 
95  # Optionally delete images
96  if delete_images:
97  image_types = ('*.png', '*.jpg', '*.gif')
98  for file_type in image_types:
99  path = os.path.join(self.images_path,file_type)
100  files_to_be_deleted.extend(glob.glob(path))
101 
102  # Do file deletion
103  for file in files_to_be_deleted:
104  file_to_be_deleted = os.path.join(self.images_path, file)
105  if os.path.isfile(file_to_be_deleted):
106  os.remove(file_to_be_deleted)
107 
108  def do_stitch(self):
109  rospy.loginfo('Stitching panorama...')
110  self.cleanup()
111  self.hugin_stitch()
112 
113  def bash_exec(self, cmd):
114  sp = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.images_path)
115  out, err = sp.communicate()
116  if out:
117  rospy.loginfo("\n%s" % out)
118  if err:
119  rospy.logerr("\n%s" % err)
120  return out, err, sp.returncode
121 
122 def main():
123  rospy.init_node('hugin_panorama')
124  Pano = HuginPanorama()
125  rospy.spin()
def cleanup(self, delete_images=False)


hugin_panorama
Author(s): Daniel Snider
autogenerated on Mon Jun 10 2019 13:37:30