def process(raw_msg, model, out, flags): ''' Given an original image message (sensor_msgs/Image), fill in the out ImageSet with the processed (debayered, rectified, grayscaled) images (in numpy format) based on the flags. @param raw_msg: sensor_msgs/Image original image message to process @param model: image_geometry.PinholeCameraModel object used to rectify images if RECT or RECT_COLOR flag is set. Can just pass in None if you aren't using RECT or RECT_COLOR @param out: an ImageSet object. The requested images will be set in out based on the flags bitmask @param flags: an integer bitmask inticating which processed images you want in out. ex: process(msg, model, out, ImageProc.RECT_COLOR | ImageProc.RECT) will fill the raw, rect_color, and rect images in out. ''' # always set raw out.raw = ImageProc.bridge.imgmsg_to_cv2(raw_msg) if not bool(flags & ImageProc.ALL): return mono = ImageProc.MONO | ImageProc.RECT color = ImageProc.COLOR | ImageProc.RECT_COLOR # Check that camera model is set if we are rectifying an image rect = bool(ImageProc.RECT | ImageProc.RECT_COLOR) if rect and not isinstance(model, PinholeCameraModel): raise Exception( 'camera model is not a PinholeCameraModel instance') raw_encoding = raw_msg.encoding # convert bayer to color and mono as needed if raw_encoding.find('bayer') != -1: if color: out.color = cvtColor2(out.raw, raw_encoding, 'bgr8') out.color_encoding = 'bgr8' if mono: out.mono = cvtColor2(out.raw, raw_encoding, 'mono8') elif raw_encoding.find('mono') != -1: if mono: out.mono = out.raw if color: raise Exception('cant get color from mono image') else: # Otherwise assume color if mono: out.mono = cvtColor2(out.raw, raw_encoding, 'mono8') if color: out.color = out.raw out.color_encoding = raw_encoding if flags & ImageProc.RECT: if out.rect is None: out.rect = np.zeros(out.mono.shape) model.rectifyImage(out.mono, out.rect) if flags & ImageProc.RECT_COLOR: if out.rect_color is None: out.rect_color = np.zeros(out.color.shape, out.color.dtype) model.rectifyImage(out.color, out.rect_color)
def process(raw_msg, model, out, flags): ''' Given an original image message (sensor_msgs/Image), fill in the out ImageSet with the processed (debayered, rectified, grayscaled) images (in numpy format) based on the flags. @param raw_msg: sensor_msgs/Image original image message to process @param model: image_geometry.PinholeCameraModel object used to rectify images if RECT or RECT_COLOR flag is set. Can just pass in None if you aren't using RECT or RECT_COLOR @param out: an ImageSet object. The requested images will be set in out based on the flags bitmask @param flags: an integer bitmask inticating which processed images you want in out. ex: process(msg, model, out, ImageProc.RECT_COLOR | ImageProc.RECT) will fill the raw, rect_color, and rect images in out. ''' # always set raw out.raw = ImageProc.bridge.imgmsg_to_cv2(raw_msg) if not bool(flags & ImageProc.ALL): return mono = ImageProc.MONO | ImageProc.RECT color = ImageProc.COLOR | ImageProc.RECT_COLOR # Check that camera model is set if we are rectifying an image rect = bool(ImageProc.RECT | ImageProc.RECT_COLOR) if rect and not isinstance(model, PinholeCameraModel): raise Exception('camera model is not a PinholeCameraModel instance') raw_encoding = raw_msg.encoding # convert bayer to color and mono as needed if raw_encoding.find('bayer') != -1: if color: out.color = cvtColor2(out.raw, raw_encoding, 'bgr8') out.color_encoding = 'bgr8' if mono: out.mono = cvtColor2(out.raw, raw_encoding, 'mono8') elif raw_encoding.find('mono') != -1: if mono: out.mono = out.raw if color: raise Exception('cant get color from mono image') else: # Otherwise assume color if mono: out.mono = cvtColor2(out.raw, raw_encoding, 'mono8') if color: out.color = out.raw out.color_encoding = raw_encoding if flags & ImageProc.RECT: if out.rect is None: out.rect = np.zeros(out.mono.shape) model.rectifyImage(out.mono, out.rect) if flags & ImageProc.RECT_COLOR: if out.rect_color is None: out.rect_color = np.zeros(out.color.shape, out.color.dtype) model.rectifyImage(out.color, out.rect_color)
def imgmsg_to_cv2(self, img_msg, desired_encoding = "passthrough"): """ Convert a sensor_msgs::Image message to an OpenCV :ctype:`cv::Mat`. :param img_msg: A sensor_msgs::Image message :param desired_encoding: The encoding of the image data, one of the following strings: * ``"passthrough"`` * one of the standard strings in sensor_msgs/image_encodings.h :rtype: :ctype:`cv::Mat` :raises CvBridgeError: when conversion is not possible. If desired_encoding is ``"passthrough"``, then the returned image has the same format as img_msg. Otherwise desired_encoding must be one of the standard image encodings This function returns an OpenCV :ctype:`cv::Mat` message on success, or raises :exc:`cv_bridge.CvBridgeError` on failure. """ import cv2 import numpy as np dtype, n_channels = self.encoding_to_dtype_with_channels(img_msg.encoding) im = np.ndarray(shape=(img_msg.height, img_msg.width, n_channels), dtype=dtype, buffer=img_msg.data) if desired_encoding == "passthrough": return im from cv_bridge.boost.cv_bridge_boost import cvtColor2 try: res = cvtColor2(im, img_msg.encoding, desired_encoding) except RuntimeError as e: raise CvBridgeError(e) return res
def compressed_imgmsg_to_cv2(cmprs_img_msg, desired_encoding="passthrough"): """ Convert a sensor_msgs::CompressedImage message to an OpenCV :cpp:type:`cv::Mat`. :param cmprs_img_msg: A :cpp:type:`sensor_msgs::CompressedImage` message :param desired_encoding: The encoding of the image data, one of the following strings: * ``"passthrough"`` * one of the standard strings in sensor_msgs/image_encodings.h :rtype: :cpp:type:`cv::Mat` :raises CvBridgeError: when conversion is not possible. If desired_encoding is ``"passthrough"``, then the returned image has the same format as img_msg. Otherwise desired_encoding must be one of the standard image encodings This function returns an OpenCV :cpp:type:`cv::Mat` message on success, or raises :exc:`cv_bridge.CvBridgeError` on failure. If the image only has one channel, the shape has size 2 (width and height) """ str_msg = cmprs_img_msg.data buf = np.ndarray(shape=(1, len(str_msg)), dtype=np.uint8, buffer=cmprs_img_msg.data) im = cv2.imdecode(buf, cv2.IMREAD_ANYCOLOR) if desired_encoding == "passthrough": return im try: res = cvtColor2(im, "bgr8", desired_encoding) except RuntimeError as e: raise CvBridgeError(e) return res
def process(self, args, images): dir = Path(args.dir) image_bridge = CvBridge() idx = 0 dir.mkdir(parents=True, exist_ok=True) for topic, img_msg, t in images: img = image_bridge.imgmsg_to_cv2(img_msg) if args.encoding != 'passthrough': if img_msg.encoding.startswith('bayer_') and args.demosaicing: # use custom debayering # cvtColor2 unfortunately doesn't expose a demosaicing algorithm parameter conv_code = conversion_code( img_msg.encoding, args.encoding, args.demosaicing) img = cv.cvtColor(img, conv_code) else: try: img = cvtColor2(img, img_msg.encoding, args.encoding) except RuntimeError as e: raise CvBridgeError(e) tpc_path = topic.lstrip('/').replace('/', '_') filename = args.name.replace('%tpc', tpc_path) filename = filename.replace('%t', str(t)) filename = filename.replace('%i', str(idx).zfill(8)) img_path = dir / filename cv.imwrite(str(img_path), img) idx += 1
def imgmsg_to_cv2(self, img_msg, desired_encoding="passthrough"): """ Convert a sensor_msgs::Image message to an OpenCV :cpp:type:`cv::Mat`. :param img_msg: A :cpp:type:`sensor_msgs::Image` message :param desired_encoding: The encoding of the image data, one of the following strings: * ``"passthrough"`` * one of the standard strings in sensor_msgs/image_encodings.h :rtype: :cpp:type:`cv::Mat` :raises CvBridgeError: when conversion is not possible. If desired_encoding is ``"passthrough"``, then the returned image has the same format as img_msg. Otherwise desired_encoding must be one of the standard image encodings This function returns an OpenCV :cpp:type:`cv::Mat` message on success, or raises :exc:`cv_bridge.CvBridgeError` on failure. If the image only has one channel, the shape has size 2 (width and height) """ import cv2 import numpy as np if img_msg.encoding == '32FC1': dtype = 'float32' n_channels = 1 elif img_msg.encoding == '32FC4': dtype = 'float32' n_channels = 4 elif img_msg.encoding == '8UC4': dtype = 'uint8' n_channels = 4 else: dtype, n_channels = self.encoding_to_dtype_with_channels( img_msg.encoding) dtype = np.dtype(dtype) dtype = dtype.newbyteorder('>' if img_msg.is_bigendian else '<') if n_channels == 1: im = np.ndarray(shape=(img_msg.height, img_msg.width), dtype=dtype, buffer=img_msg.data) else: im = np.ndarray(shape=(img_msg.height, img_msg.width, n_channels), dtype=dtype, buffer=img_msg.data) # If the byt order is different between the message and the system. if img_msg.is_bigendian == (sys.byteorder == 'little'): im = im.byteswap().newbyteorder() if desired_encoding == "passthrough": return im from cv_bridge.boost.cv_bridge_boost import cvtColor2 try: res = cvtColor2(im, img_msg.encoding, desired_encoding) except RuntimeError as e: raise CvBridgeError(e) return res
def imgmsg_to_cv2(self, img_msg, desired_encoding = "passthrough"): """ Convert a sensor_msgs::Image message to an OpenCV :cpp:type:`cv::Mat`. :param img_msg: A :cpp:type:`sensor_msgs::Image` message :param desired_encoding: The encoding of the image data, one of the following strings: * ``"passthrough"`` * one of the standard strings in sensor_msgs/image_encodings.h :rtype: :cpp:type:`cv::Mat` :raises CvBridgeError: when conversion is not possible. If desired_encoding is ``"passthrough"``, then the returned image has the same format as img_msg. Otherwise desired_encoding must be one of the standard image encodings This function returns an OpenCV :cpp:type:`cv::Mat` message on success, or raises :exc:`cv_bridge.CvBridgeError` on failure. If the image only has one channel, the shape has size 2 (width and height) """ import cv2 import numpy as np dtype, n_channels = self.encoding_to_dtype_with_channels(img_msg.encoding) dtype = np.dtype(dtype) dtype = dtype.newbyteorder('>' if img_msg.is_bigendian else '<') if n_channels == 1: im = np.ndarray(shape=(img_msg.height, img_msg.width), dtype=dtype, buffer=img_msg.data) else: im = np.ndarray(shape=(img_msg.height, img_msg.width, n_channels), dtype=dtype, buffer=img_msg.data) # If the byt order is different between the message and the system. if img_msg.is_bigendian == (sys.byteorder == 'little'): im = im.byteswap().newbyteorder() if desired_encoding == "passthrough": return im from cv_bridge.boost.cv_bridge_boost import cvtColor2 try: res = cvtColor2(im, img_msg.encoding, desired_encoding) except RuntimeError as e: raise CvBridgeError(e) return res
def compressed_imgmsg_to_cv2(self, cmprs_img_msg, desired_encoding = "passthrough"): """ Convert a sensor_msgs::CompressedImage message to an OpenCV :cpp:type:`cv::Mat`. :param cmprs_img_msg: A :cpp:type:`sensor_msgs::CompressedImage` message :param desired_encoding: The encoding of the image data, one of the following strings: * ``"passthrough"`` * one of the standard strings in sensor_msgs/image_encodings.h :rtype: :cpp:type:`cv::Mat` :raises CvBridgeError: when conversion is not possible. If desired_encoding is ``"passthrough"``, then the returned image has the same format as img_msg. Otherwise desired_encoding must be one of the standard image encodings This function returns an OpenCV :cpp:type:`cv::Mat` message on success, or raises :exc:`cv_bridge.CvBridgeError` on failure. If the image only has one channel, the shape has size 2 (width and height) """ import cv2 import numpy as np str_msg = cmprs_img_msg.data buf = np.ndarray(shape=(1, len(str_msg)), dtype=np.uint8, buffer=cmprs_img_msg.data) im = cv2.imdecode(buf, cv2.IMREAD_ANYCOLOR) if desired_encoding == "passthrough": return im from cv_bridge.boost.cv_bridge_boost import cvtColor2 try: res = cvtColor2(im, "bgr8", desired_encoding) except RuntimeError as e: raise CvBridgeError(e) return res