00001
00002
00003 import os
00004 from threading import Lock
00005
00006 import cv2
00007 import numpy as np
00008
00009 import cv_bridge
00010 from cv_bridge.boost.cv_bridge_boost import getCvType
00011 import dynamic_reconfigure.server
00012 import rospy
00013
00014 from jsk_perception.cfg import ImagePublisherConfig
00015 from sensor_msgs.msg import CameraInfo
00016 from sensor_msgs.msg import Image
00017
00018
00019 class ImagePublisher(object):
00020
00021 def __init__(self):
00022 self.lock = Lock()
00023 self.imgmsg = None
00024 self.encoding = rospy.get_param('~encoding', 'bgr8')
00025 self.frame_id = rospy.get_param('~frame_id', 'camera')
00026 self.fovx = rospy.get_param('~fovx', None)
00027 self.fovy = rospy.get_param('~fovy', None)
00028 if (self.fovx is None) != (self.fovy is None):
00029 rospy.logwarn('fovx and fovy should be specified, but '
00030 'specified only {}'
00031 .format('fovx' if self.fovx else 'fovy'))
00032 dynamic_reconfigure.server.Server(
00033 ImagePublisherConfig, self._cb_dyn_reconfig)
00034 self.pub = rospy.Publisher('~output', Image, queue_size=1)
00035 self.publish_info = rospy.get_param('~publish_info', True)
00036 if self.publish_info:
00037 self.pub_info = rospy.Publisher(
00038 '~output/camera_info', CameraInfo, queue_size=1)
00039 rate = rospy.get_param('~rate', 1.)
00040 rospy.Timer(rospy.Duration(1. / rate), self.publish)
00041
00042 def _cb_dyn_reconfig(self, config, level):
00043 file_name = config['file_name']
00044 config['file_name'] = os.path.abspath(file_name)
00045 img_bgr = cv2.imread(file_name)
00046 if img_bgr is None:
00047 rospy.logwarn('Could not read image file: {}'.format(file_name))
00048 with self.lock:
00049 self.imgmsg = None
00050 else:
00051 rospy.loginfo('Read the image file: {}'.format(file_name))
00052 with self.lock:
00053 self.imgmsg = self.cv2_to_imgmsg(img_bgr, self.encoding)
00054 return config
00055
00056 def publish(self, event):
00057 if self.imgmsg is None:
00058 return
00059 now = rospy.Time.now()
00060
00061 with self.lock:
00062 self.imgmsg.header.stamp = now
00063 self.imgmsg.header.frame_id = self.frame_id
00064 self.pub.publish(self.imgmsg)
00065 if self.publish_info:
00066 info = CameraInfo()
00067 info.header.stamp = now
00068 info.header.frame_id = self.frame_id
00069 info.width = self.imgmsg.width
00070 info.height = self.imgmsg.height
00071 if self.fovx is not None and self.fovy is not None:
00072 fx = self.imgmsg.width / 2.0 / \
00073 np.tan(np.deg2rad(self.fovx / 2.0))
00074 fy = self.imgmsg.height / 2.0 / \
00075 np.tan(np.deg2rad(self.fovy / 2.0))
00076 cx = self.imgmsg.width / 2.0
00077 cy = self.imgmsg.height / 2.0
00078 info.K = np.array([fx, 0, cx,
00079 0, fy, cy,
00080 0, 0, 1.0])
00081 info.P = np.array([fx, 0, cx, 0,
00082 0, fy, cy, 0,
00083 0, 0, 1, 0])
00084 info.R = [1, 0, 0, 0, 1, 0, 0, 0, 1]
00085 self.pub_info.publish(info)
00086
00087 def cv2_to_imgmsg(self, img_bgr, encoding):
00088 bridge = cv_bridge.CvBridge()
00089
00090 if getCvType(encoding) == 0:
00091
00092 img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
00093 elif getCvType(encoding) == 2:
00094
00095 img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
00096 img = img.astype(np.float32)
00097 img = img / 255 * (2 ** 16)
00098 img = img.astype(np.uint16)
00099 elif getCvType(encoding) == 5:
00100
00101 img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
00102 img = img.astype(np.float32)
00103 img /= 255
00104 elif getCvType(encoding) == 16:
00105
00106 if encoding in ('rgb8', 'rgb16'):
00107
00108 img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
00109 else:
00110 img = img_bgr
00111 else:
00112 rospy.logerr('unsupported encoding: {0}'.format(encoding))
00113 return
00114 return bridge.cv2_to_imgmsg(img, encoding=encoding)
00115
00116
00117 if __name__ == '__main__':
00118 rospy.init_node('image_publisher')
00119 ImagePublisher()
00120 rospy.spin()