Source code for pyctools.components.io.imagefilecv

#  Pyctools - a picture processing algorithm development kit.
#  http://github.com/jim-easterbrook/pyctools
#  Copyright (C) 2016-20  Pyctools contributors
#
#  This program is free software: you can redistribute it and/or
#  modify it under the terms of the GNU General Public License as
#  published by the Free Software Foundation, either version 3 of the
#  License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#  General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see
#  <http://www.gnu.org/licenses/>.

from __future__ import print_function

__all__ = ['ImageFileReaderCV', 'ImageFileWriterCV']
__docformat__ = 'restructuredtext en'

import os

import cv2
import numpy

from pyctools.core.config import ConfigBool, ConfigPath, ConfigStr
from pyctools.core.base import Component, Transformer
from pyctools.core.frame import Frame, Metadata


[docs] class ImageFileReaderCV(Component): """Read a still image file using OpenCV library. The file is read with minimum changes to the data, so a 16-bit depth file will result in a floating point image with data in the usual 0..255 range. If you have a file format that OpenCV doesn't recognise, try the :py:class:`~pyctools.components.io.imagefilepil.ImageFileReaderPIL` component instead. ======== === ==== Config ======== === ==== ``path`` str Path name of file to be read. ======== === ==== """ inputs = [] with_outframe_pool = False def initialise(self): self.config['path'] = ConfigPath() def on_start(self): # read file self.update_config() path = self.config['path'] out_frame = Frame() image = cv2.imread(path, cv2.IMREAD_UNCHANGED) # scale data if image.dtype == numpy.uint8: pass elif image.dtype == numpy.uint16: image = image.astype(numpy.float32) / numpy.float32(2 ** 8) else: self.logger.error('Cannot handle %s data type', str(image.dtype)) self.stop() return # rearrange components if image.shape[2] == 4: # RGBA image B = image[:, :, 0] G = image[:, :, 1] R = image[:, :, 2] A = image[:, :, 3] image = numpy.dstack((R, G, B, A)) out_frame.type = 'RGBA' elif image.shape[2] == 3: # RGB image B = image[:, :, 0] G = image[:, :, 1] R = image[:, :, 2] image = numpy.dstack((R, G, B)) out_frame.type = 'RGB' elif image.shape[2] == 1: out_frame.type = 'Y' else: out_frame.type = '???' # send output frame out_frame.data = image out_frame.frame_no = 0 out_frame.metadata.from_file(path) out_frame.set_audit(self, 'data = {}\n'.format(os.path.basename(path)), with_config=self.config) self.send('output', out_frame) # shut down pipeline self.stop()
[docs] class ImageFileWriterCV(Transformer): """Write a still image file using OpenCV library. See the `OpenCV documentation`_ for more detail on the parameters. If you need to write a file format that OpenCV can't do, try the :py:class:`~pyctools.components.io.imagefilepil.ImageFileWriterPIL` component instead. ============================== ==== ==== Config ============================== ==== ==== ``path`` str Path name of file to be written. ``16bit`` bool Write a 16-bit depth file, if the format supports it. {} ============================== ==== ==== .. _OpenCV documentation: http://docs.opencv.org/2.4.11/modules/highgui/doc/reading_and_writing_images_and_video.html#imwrite """ cv2_params = [x[8:] for x in cv2.__dict__ if x.startswith('IMWRITE_')] cv2_params.sort() __doc__ = __doc__.format( '\n '.join([ '``{x}``{s} int OpenCV CV_IMWRITE_{x} parameter.'.format( x=x, s=' '*(26-len(x))) for x in cv2_params])) def initialise(self): self.done = False self.config['path'] = ConfigPath(exists=False) self.config['16bit'] = ConfigBool() for item in self.cv2_params: self.config[item] = ConfigStr() def transform(self, in_frame, out_frame): if self.done: return True self.update_config() path = self.config['path'] params = [] for item in self.cv2_params: if self.config[item]: params.append(getattr(cv2, 'IMWRITE_' + item)) params.append(int(self.config[item])) # convert data if self.config['16bit']: image = in_frame.as_numpy() * numpy.float32(2 ** 8) image = image.clip(0, 2**16 - 1) image = image.astype(numpy.uint16) else: image = in_frame.as_numpy(dtype=numpy.uint8) # rearrange components if image.shape[2] == 4: # RGBA image R = image[:, :, 0] G = image[:, :, 1] B = image[:, :, 2] A = image[:, :, 3] image = numpy.dstack((B, G, R, A)) elif image.shape[2] == 3: # RGB image R = image[:, :, 0] G = image[:, :, 1] B = image[:, :, 2] image = numpy.dstack((B, G, R)) # save image cv2.imwrite(path, image, params) # save metadata md = Metadata().copy(in_frame.metadata) md.set_audit(self, '{} = data\n'.format(os.path.basename(path)), with_date=True, with_config=self.config) md.to_file(path) self.done = True return True