fcn_depth_prediction.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 from __future__ import print_function
4 
5 from distutils.version import LooseVersion
6 
7 import itertools, pkg_resources, sys
8 if LooseVersion(pkg_resources.get_distribution("chainer").version) >= LooseVersion('7.0.0') and \
9  sys.version_info.major == 2:
10  print('''Please install chainer < 7.0.0:
11 
12  sudo pip install chainer==6.7.0
13 
14 c.f https://github.com/jsk-ros-pkg/jsk_recognition/pull/2485
15 ''', file=sys.stderr)
16  sys.exit(1)
17 if [p for p in list(itertools.chain(*[pkg_resources.find_distributions(_) for _ in sys.path])) if "cupy-" in p.project_name ] == []:
18  print('''Please install CuPy
19 
20  sudo pip install cupy-cuda[your cuda version]
21 i.e.
22  sudo pip install cupy-cuda91
23 
24 ''', file=sys.stderr)
25  # sys.exit(1)
26 import chainer
27 from chainer import cuda
28 import chainer.functions as F
29 import chainer.serializers as S
30 import cv2
31 import numpy as np
32 
33 import cv_bridge
34 from jsk_recognition_utils.chainermodels import FCN8sDepthPrediction
35 from jsk_recognition_utils.chainermodels import FCN8sDepthPredictionConcatFirst
36 from jsk_topic_tools import ConnectionBasedTransport
37 import message_filters
38 import rospy
39 from sensor_msgs.msg import Image
40 
41 
42 def colorize_depth(depth, min_value=None, max_value=None):
43  min_value = np.nanmin(depth) if min_value is None else min_value
44  max_value = np.nanmax(depth) if max_value is None else max_value
45  if np.isinf(min_value) or np.isinf(max_value):
46  rospy.logwarn('Min or max value for depth colorization is inf.')
47 
48  colorized = depth.copy()
49  nan_mask = np.isnan(colorized)
50  colorized[nan_mask] = 0
51  colorized = 255 * (colorized - min_value) / (max_value - min_value)
52  colorized = np.minimum(np.maximum(colorized, 0), 255).astype(np.uint8)
53  colorized = cv2.applyColorMap(colorized, cv2.COLORMAP_JET)
54  colorized[nan_mask] = (0, 0, 0)
55  return colorized
56 
57 
58 class FCNDepthPrediction(ConnectionBasedTransport):
59 
60  def __init__(self):
61  super(self.__class__, self).__init__()
62  self.backend = rospy.get_param('~backend', 'chainer')
63  self.model_name = rospy.get_param('~model_name')
64  self.model_file = rospy.get_param('~model_file')
65  self.gpu = rospy.get_param('~gpu', -1) # -1 is cpu mode
66  self.target_names = rospy.get_param('~target_names')
67  self.bg_label = rospy.get_param('~bg_label', 0)
68  self.proba_threshold = rospy.get_param('~proba_threshold', 0.0)
69  self.mean_bgr = np.array([104.00698793, 116.66876762, 122.67891434])
70  self._load_model()
71  self.pub_depth = self.advertise('~output', Image, queue_size=1)
72  self.pub_depth_raw = self.advertise(
73  '~output/depth_pred_raw', Image, queue_size=1)
74  self.pub_label = self.advertise('~output/label', Image, queue_size=1)
75  self.pub_proba = self.advertise(
76  '~output/proba_image', Image, queue_size=1)
77 
78  def _load_model(self):
79  if self.backend == 'chainer':
80  self._load_chainer_model()
81  else:
82  raise RuntimeError('Unsupported backend: %s', self.backend)
83 
85  n_class = len(self.target_names)
86  if self.model_name == 'fcn8s_depth_prediction':
87  self.model = FCN8sDepthPrediction(n_class=n_class)
88  elif self.model_name == 'fcn8s_depth_prediction_concat_first':
89  self.model = FCN8sDepthPredictionConcatFirst(n_class=n_class)
90  else:
91  raise ValueError(
92  'Unsupported ~model_name: {}'.format(self.model_name))
93  rospy.loginfo('Loading trained model: {0}'.format(self.model_file))
94  if self.model_file.endswith('.npz'):
95  S.load_npz(self.model_file, self.model)
96  rospy.loginfo(
97  'Finished loading trained model: {0}'.format(self.model_file))
98  if self.gpu != -1:
99  self.model.to_gpu(self.gpu)
100  if LooseVersion(chainer.__version__) < LooseVersion('2.0.0'):
101  self.model.train = False
102 
103  def subscribe(self):
104  queue_size = rospy.get_param('~queue_size', 10)
105  sub_img = message_filters.Subscriber(
106  '~input', Image, queue_size=1, buff_size=2**24)
107  sub_depth = message_filters.Subscriber(
108  '~input/depth', Image, queue_size=1, buff_size=2**24)
109  self.subs = [sub_img, sub_depth]
110  if rospy.get_param('~approximate_sync', False):
111  slop = rospy.get_param('~slop', 0.1)
112  sync = message_filters.ApproximateTimeSynchronizer(
113  fs=self.subs, queue_size=queue_size, slop=slop)
114  else:
116  fs=self.subs, queue_size=queue_size)
117  sync.registerCallback(self._cb)
118 
119  def unsubscribe(self):
120  for sub in self.subs:
121  sub.unregister()
122 
123  def transform_depth(self, depth):
124  if depth.dtype == np.uint16:
125  depth = depth.astype(np.float32) * 0.001
126  min_value = self.model.min_depth
127  max_value = self.model.max_depth
128  depth_viz_rgb = colorize_depth(
129  depth,
130  min_value=min_value, max_value=max_value
131  )
132  depth_viz_bgr = depth_viz_rgb[:, :, ::-1].astype(np.float32)
133  depth_viz_bgr = (depth_viz_bgr - self.mean_bgr).transpose((2, 0, 1))
134  return depth_viz_bgr
135 
136  def _cb(self, img_msg, depth_msg):
137  br = cv_bridge.CvBridge()
138  bgr_img = br.imgmsg_to_cv2(img_msg, desired_encoding='bgr8')
139  depth_img = br.imgmsg_to_cv2(depth_msg, desired_encoding='passthrough')
140  if depth_img.ndim > 2:
141  depth_img = np.squeeze(depth_img, axis=2)
142  bgr_img = (bgr_img - self.mean_bgr).transpose((2, 0, 1))
143  depth_viz_bgr = self.transform_depth(depth_img)
144 
145  label_pred, proba_img, depth_pred = \
146  self.predict_depth(bgr_img, depth_viz_bgr)
147  depth_pred_raw = depth_pred.copy()
148  depth_pred[label_pred == 0] = depth_img[label_pred == 0]
149 
150  label_msg = br.cv2_to_imgmsg(label_pred.astype(np.int32), '32SC1')
151  label_msg.header = img_msg.header
152  self.pub_label.publish(label_msg)
153  proba_msg = br.cv2_to_imgmsg(proba_img.astype(np.float32))
154  proba_msg.header = img_msg.header
155  self.pub_proba.publish(proba_msg)
156  depth_msg = br.cv2_to_imgmsg(depth_pred.astype(np.float32))
157  depth_msg.header = img_msg.header
158  self.pub_depth.publish(depth_msg)
159  depth_raw_msg = br.cv2_to_imgmsg(depth_pred_raw.astype(np.float32))
160  depth_raw_msg.header = img_msg.header
161  self.pub_depth_raw.publish(depth_raw_msg)
162 
163  def predict_depth(self, bgr, depth_bgr=None):
164  if self.backend == 'chainer':
165  return self._predict_depth_chainer_backend(bgr, depth_bgr)
166  raise ValueError('Unsupported backend: {0}'.format(self.backend))
167 
168  def _predict_depth_chainer_backend(self, bgr, depth_bgr=None):
169  bgr_data = np.array([bgr], dtype=np.float32)
170  depth_bgr_data = np.array([depth_bgr], dtype=np.float32)
171  if self.gpu != -1:
172  bgr_data = cuda.to_gpu(bgr_data, device=self.gpu)
173  depth_bgr_data = cuda.to_gpu(depth_bgr_data, device=self.gpu)
174  if LooseVersion(chainer.__version__) < LooseVersion('2.0.0'):
175  bgr = chainer.Variable(bgr_data, volatile=True)
176  depth_bgr = chainer.Variable(depth_bgr_data, volatile=True)
177  self.model(bgr, depth_bgr)
178  else:
179  with chainer.using_config('train', False):
180  with chainer.no_backprop_mode():
181  bgr = chainer.Variable(bgr_data)
182  depth_bgr = chainer.Variable(depth_bgr_data)
183  self.model(bgr, depth_bgr)
184 
185  proba_img = F.softmax(self.model.mask_score)
186  label_pred = F.argmax(self.model.mask_score, axis=1)
187  depth_pred = F.sigmoid(self.model.depth_score)
188  proba_img = F.transpose(proba_img, (0, 2, 3, 1))
189  max_proba_img = F.max(proba_img, axis=-1)
190  # squeeze batch axis, gpu -> cpu
191  proba_img = cuda.to_cpu(proba_img.data)[0]
192  max_proba_img = cuda.to_cpu(max_proba_img.data)[0]
193  label_pred = cuda.to_cpu(label_pred.data)[0]
194  depth_pred = cuda.to_cpu(depth_pred.data)[0]
195  # uncertain because the probability is low
196  label_pred[max_proba_img < self.proba_threshold] = self.bg_label
197  # get depth image
198  depth_pred = depth_pred[0, :, :]
199  depth_pred *= (self.model.max_depth - self.model.min_depth)
200  depth_pred += self.model.min_depth
201 
202  return label_pred, proba_img, depth_pred
203 
204 
205 if __name__ == '__main__':
206  rospy.init_node('fcn_depth_prediction')
208  rospy.spin()
def colorize_depth(depth, min_value=None, max_value=None)


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