image_publisher.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 import os
4 from threading import Lock
5 
6 import cv2
7 import numpy as np
8 
9 import cv_bridge
10 from cv_bridge.boost.cv_bridge_boost import getCvType
11 import dynamic_reconfigure.server
12 import rospy
13 
14 from jsk_perception.cfg import ImagePublisherConfig
15 from sensor_msgs.msg import CameraInfo
16 from sensor_msgs.msg import Image
17 
18 
20 
21  def __init__(self):
22  self.lock = Lock()
23  self.imgmsg = None
24  self.encoding = rospy.get_param('~encoding', 'bgr8')
25  self.frame_id = rospy.get_param('~frame_id', 'camera')
26  self.fovx = rospy.get_param('~fovx', None)
27  self.fovy = rospy.get_param('~fovy', None)
28  if (self.fovx is None) != (self.fovy is None):
29  rospy.logwarn('fovx and fovy should be specified, but '
30  'specified only {}'
31  .format('fovx' if self.fovx else 'fovy'))
32  dynamic_reconfigure.server.Server(
33  ImagePublisherConfig, self._cb_dyn_reconfig)
34  self.pub = rospy.Publisher('~output', Image, queue_size=1)
35  self.publish_info = rospy.get_param('~publish_info', True)
36  if self.publish_info:
37  self.pub_info = rospy.Publisher(
38  '~output/camera_info', CameraInfo, queue_size=1)
39  rate = rospy.get_param('~rate', 1.)
40  rospy.Timer(rospy.Duration(1. / rate), self.publish)
41 
42  def _cb_dyn_reconfig(self, config, level):
43  file_name = config['file_name']
44  config['file_name'] = os.path.abspath(file_name)
45  img = cv2.imread(file_name, cv2.IMREAD_UNCHANGED)
46  # when file is gray scale but encoding is not grayscale,
47  # load the image again in color
48  if (len(img.shape) == 2 and
49  getCvType(self.encoding) not in [
50  cv2.CV_8UC1, cv2.CV_16UC1, cv2.CV_32FC1]):
51  img = cv2.imread(file_name, cv2.IMREAD_COLOR)
52  if img is None:
53  rospy.logwarn('Could not read image file: {}'.format(file_name))
54  with self.lock:
55  self.imgmsg = None
56  else:
57  rospy.loginfo('Read the image file: {}'.format(file_name))
58  with self.lock:
59  self.imgmsg = self.cv2_to_imgmsg(img, self.encoding)
60  return config
61 
62  def publish(self, event):
63  if self.imgmsg is None:
64  return
65  now = rospy.Time.now()
66  # setup ros message and publish
67  with self.lock:
68  self.imgmsg.header.stamp = now
69  self.imgmsg.header.frame_id = self.frame_id
70  self.pub.publish(self.imgmsg)
71  if self.publish_info:
72  info = CameraInfo()
73  info.header.stamp = now
74  info.header.frame_id = self.frame_id
75  info.width = self.imgmsg.width
76  info.height = self.imgmsg.height
77  if self.fovx is not None and self.fovy is not None:
78  fx = self.imgmsg.width / 2.0 / \
79  np.tan(np.deg2rad(self.fovx / 2.0))
80  fy = self.imgmsg.height / 2.0 / \
81  np.tan(np.deg2rad(self.fovy / 2.0))
82  cx = self.imgmsg.width / 2.0
83  cy = self.imgmsg.height / 2.0
84  info.K = np.array([fx, 0, cx,
85  0, fy, cy,
86  0, 0, 1.0])
87  info.P = np.array([fx, 0, cx, 0,
88  0, fy, cy, 0,
89  0, 0, 1, 0])
90  info.R = [1, 0, 0, 0, 1, 0, 0, 0, 1]
91  self.pub_info.publish(info)
92 
93  def cv2_to_imgmsg(self, img, encoding):
94  bridge = cv_bridge.CvBridge()
95  # resolve encoding
96  if getCvType(encoding) in [cv2.CV_8UC1, cv2.CV_16UC1, cv2.CV_32FC1]:
97  # mono8
98  if len(img.shape) == 3:
99  if img.shape[2] == 4:
100  code = cv2.COLOR_BGRA2GRAY
101  else:
102  code = cv2.COLOR_BGR2GRAY
103  img = cv2.cvtColor(img, code)
104  if getCvType(encoding) == cv2.CV_16UC1:
105  # 16UC1
106  img = img.astype(np.float32)
107  img = img / 255 * (2 ** 16)
108  img = img.astype(np.uint16)
109  elif getCvType(encoding) == cv2.CV_32FC1:
110  # 32FC1
111  img = img.astype(np.float32)
112  img /= 255
113  elif getCvType(encoding) == cv2.CV_8UC3 and len(img.shape) == 3:
114  # 8UC3
115  # BGRA, BGR -> BGR
116  img = img[:, :, :3]
117  # BGR -> RGB
118  if encoding in ('rgb8', 'rgb16'):
119  img = img[:, :, ::-1]
120  elif (getCvType(encoding) == cv2.CV_8UC4 and
121  len(img.shape) == 3 and img.shape[2] == 4):
122  # 8UC4
123  if encoding in ('rgba8', 'rgba16'):
124  # BGRA -> RGBA
125  img = img[:, :, [2, 1, 0, 3]]
126  else:
127  rospy.logerr('unsupported encoding: {0}'.format(encoding))
128  return
129  return bridge.cv2_to_imgmsg(img, encoding=encoding)
130 
131 
132 if __name__ == '__main__':
133  rospy.init_node('image_publisher')
135  rospy.spin()


jsk_perception
Author(s): Manabu Saito, Ryohei Ueda
autogenerated on Mon May 3 2021 03:03:27