4 from threading
import Lock
10 from cv_bridge.boost.cv_bridge_boost
import getCvType
11 import dynamic_reconfigure.server
14 from jsk_perception.cfg
import ImagePublisherConfig
15 from sensor_msgs.msg
import CameraInfo
16 from sensor_msgs.msg
import Image, CompressedImage
19 from PIL
import Image
as PIL_Image
20 from PIL
import ExifTags
as PIL_ExifTags
21 from jsk_recognition_msgs.msg
import ExifTags, ExifGPSInfo
32 self.
encoding = rospy.get_param(
'~encoding',
'bgr8')
33 self.
frame_id = rospy.get_param(
'~frame_id',
'camera')
34 self.
fovx = rospy.get_param(
'~fovx',
None)
35 self.
fovy = rospy.get_param(
'~fovy',
None)
37 if (self.
fovx is None) != (self.
fovy is None):
38 rospy.logwarn(
'fovx and fovy should be specified, but '
40 .format(
'fovx' if self.
fovx else 'fovy'))
41 dynamic_reconfigure.server.Server(
43 self.
pub = rospy.Publisher(
'~output', Image, queue_size=1)
44 self.
pub_compressed = rospy.Publisher(
'{}/compressed'.format(rospy.resolve_name(
'~output')), CompressedImage, queue_size=1)
47 '{}/compressedDepth'.format(rospy.resolve_name(
'~output')),
48 CompressedImage, queue_size=1)
52 '~output/camera_info', CameraInfo, queue_size=1)
54 self.
pub_exif = rospy.Publisher(
'~exif', ExifTags, queue_size=1)
55 rate = rospy.get_param(
'~rate', 1.)
56 rospy.Timer(rospy.Duration(1. / rate), self.
publish)
59 def encode_value(value, attr, data):
60 attr_type = type(attr)
61 value_type = type(value)
62 if attr_type == list
and value_type == tuple:
63 for i
in range(len(value)):
64 attr[i] = encode_value(value[i], attr[i], data)
67 if attr_type == str
and value_type == unicode:
69 value = value.encode(
'ascii',
'ignore')
70 if attr_type == int
and value_type == str:
72 value = map(ord, value)[0]
73 elif attr_type == float
and value_type == tuple:
75 value =
float(
'{}.{}'.format(value[0], value[1]))
78 string_tag = get(tag, tag)
81 elif type(string_tag) == str:
82 decoded_tag = re.sub(
'([a-z])([A-Z])',
'\\1_\\2', string_tag)
83 decoded_tag = re.sub(
'([a-zA-Z])([0-9])',
'\\1_\\2', decoded_tag)
84 decoded_tag = re.sub(
'([XYZ])Resolution',
'\\1_resolution', decoded_tag)
85 decoded_tag = re.sub(
'([F])Number',
'\\1_number', decoded_tag)
86 decoded_tag = re.sub(
'(ISO)',
'\\1_', decoded_tag)
87 decoded_tag = re.sub(
'(GPS)',
'\\1_', decoded_tag)
88 decoded_tag = decoded_tag.lower()
89 if decoded_tag ==
'gps_info':
90 gps_data = ExifGPSInfo()
93 data.gps_info = gps_data
96 setattr(data, decoded_tag, encode_value(value, getattr(data, decoded_tag), data))
97 except AttributeError
as e:
98 rospy.logwarn(
"Undefiend exif tags [{:x} {}({}) {}]".format(tag, string_tag, decoded_tag, value))
99 except Exception
as e:
100 rospy.logerr(
"Wrong exif information {} [{:x} {}({}) {}]".format(e, tag, string_tag, decoded_tag, value))
102 rospy.logwarn(
"Unknown exif tags [{:x} {} {}]".format(tag, string_tag, value))
106 exif_data =ExifTags()
107 self.
info = PIL_Image.open(file_name)._getexif()
109 for tag, value
in self.
info.items():
114 file_name = config[
'file_name']
115 config[
'file_name'] = os.path.abspath(file_name)
117 img = cv2.imread(file_name, cv2.IMREAD_UNCHANGED)
119 rospy.logwarn(
'Could not read image file: {}'.format(file_name))
123 rospy.loginfo(
'Read the image file: {}'.format(file_name))
126 if (len(img.shape) == 2
and
128 cv2.CV_8UC1, cv2.CV_16UC1, cv2.CV_32FC1]):
129 img = cv2.imread(file_name, cv2.IMREAD_COLOR)
141 now = rospy.Time.now()
144 self.
imgmsg.header.stamp = \
145 self.
compmsg.header.stamp = now
146 self.
imgmsg.header.frame_id = \
148 if self.
pub.get_num_connections() > 0:
154 info.header.stamp = now
155 info.header.frame_id = self.
frame_id
156 info.width = self.
imgmsg.width
157 info.height = self.
imgmsg.height
158 if self.
fovx is not None and self.
fovy is not None:
159 fx = self.
imgmsg.width / 2.0 / \
160 np.tan(np.deg2rad(self.
fovx / 2.0))
161 fy = self.
imgmsg.height / 2.0 / \
162 np.tan(np.deg2rad(self.
fovy / 2.0))
163 cx = self.
imgmsg.width / 2.0
164 cy = self.
imgmsg.height / 2.0
165 info.K = np.array([fx, 0, cx,
168 info.P = np.array([fx, 0, cx, 0,
171 info.R = [1, 0, 0, 0, 1, 0, 0, 0, 1]
177 bridge = cv_bridge.CvBridge()
179 cv_type = getCvType(encoding)
181 if cv_type
in [cv2.CV_8UC1, cv2.CV_16UC1, cv2.CV_32FC1]:
183 if len(img.shape) == 3:
184 if img.shape[2] == 4:
185 code = cv2.COLOR_BGRA2GRAY
187 code = cv2.COLOR_BGR2GRAY
188 img = cv2.cvtColor(img, code)
189 if cv_type == cv2.CV_16UC1:
193 img = img.astype(np.float32)
194 img = np.clip(img / 255.0 * (2 ** 16 - 1), 0, 2 ** 16 - 1)
195 img = img.astype(np.uint16)
196 elif cv_type == cv2.CV_32FC1:
198 img = img.astype(np.float32)
200 comp_depth_msg = depth_to_compressed_depth(img)
201 return bridge.cv2_to_imgmsg(img, encoding=encoding), comp_depth_msg
203 target_format = encoding
204 elif cv_type == cv2.CV_8UC3
and len(img.shape) == 3:
207 img = comp_img = img[:, :, :3]
208 target_format =
'bgr8'
210 if encoding ==
'rgb8':
211 img = img[:, :, ::-1]
212 elif cv_type == cv2.CV_16UC3
and len(img.shape) == 3:
219 img = img.astype(np.float32)
220 img = np.clip(img / 255.0 * (2 ** 16 - 1), 0, 2 ** 16 - 1)
221 img = comp_img = img.astype(np.uint16)
222 target_format =
'bgr16'
224 if encoding ==
'rgb16':
225 img = img[:, :, ::-1]
226 elif (cv_type == cv2.CV_8UC4
and
227 len(img.shape) == 3
and img.shape[2] == 4):
228 comp_img = img[:, :, :3]
229 target_format =
'bgr8'
231 if encoding ==
'rgba8':
233 img = img[:, :, [2, 1, 0, 3]]
234 elif (cv_type == cv2.CV_16UC4
and
235 len(img.shape) == 3
and img.shape[2] == 4):
237 img = img.astype(np.float32)
238 img = np.clip(img / 255.0 * (2 ** 16 - 1), 0, 2 ** 16 - 1)
239 img = img.astype(np.uint16)
240 comp_img = img[:, :, :3]
241 target_format =
'bgr16'
242 if encoding ==
'rgba16':
244 img = img[:, :, [2, 1, 0, 3]]
246 rospy.logerr(
'unsupported encoding: {0}'.format(encoding))
248 compmsg = bridge.cv2_to_compressed_imgmsg(comp_img, dst_format=dst_format)
251 compmsg.format =
'{}; {} compressed {}'.format(
252 encoding, dst_format, target_format)
253 return bridge.cv2_to_imgmsg(img, encoding=encoding), compmsg
257 if __name__ ==
'__main__':
258 rospy.init_node(
'image_publisher')