docs: def frames(self):
          """Retrieve the next frame from the image directory and convert it to a ColorImage,
          a DepthImage, and an IrImage.
  
          Parameters
          ----------
          skip_registration : bool
              If True, the registration step is skipped.
  
          Returns
          -------
          :obj:`tuple` of :obj:`ColorImage`, :obj:`DepthImage`, :obj:`IrImage`, :obj:`numpy.ndarray`
              The ColorImage, DepthImage, and IrImage of the current frame.
  
          Raises
          ------
          RuntimeError
              If the stream is not running or if all images in the
              directory have been used.
          """
          if not self._running:
              raise RuntimeError('Device pointing to %s not runnning. Cannot read frames' %(self._path_to_images))
  
          if self._im_index >= self._num_images:
              raise RuntimeError('Device is out of images')
  
          # read images
          color_filename = os.path.join(self._path_to_images, 'color_%d%s' %(self._im_index, self._color_ext))
          color_im = ColorImage.open(color_filename, frame=self._frame)
          depth_filename = os.path.join(self._path_to_images, 'depth_%d.npy' %(self._im_index))
          depth_im = DepthImage.open(depth_filename, frame=self._frame)
          self._im_index = (self._im_index + 1) % self._num_images
          return color_im, depth_im, None