Source code for pyctools.components.deinterlace.simple

#  Pyctools - a picture processing algorithm development kit.
#  http://github.com/jim-easterbrook/pyctools
#  Copyright (C) 2014-18  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/>.

__all__ = ['SimpleDeinterlace']
__docformat__ = 'restructuredtext en'

import numpy

from pyctools.core.config import ConfigBool, ConfigEnum
from pyctools.core.base import Component

[docs] class SimpleDeinterlace(Component): """Simple interlace to sequential converter. Insert lines of zero or repeat previous line to convert each interlaced frame to two sequential frames. ============ ==== ==== Config ============ ==== ==== ``mode`` str Can be set to ``insertzero`` or ``repeatline``. ``inverse`` bool Interlace to sequential or vice versa. ``topfirst`` bool Top field first. ============ ==== ==== """ def initialise(self): self.config['mode'] = ConfigEnum(choices=('insertzero', 'repeatline')) self.config['inverse'] = ConfigBool() self.config['topfirst'] = ConfigBool(value=True) self.first_field = True def process_frame(self): self.update_config() repeat_line = self.config['mode'] == 'repeatline' if self.config['inverse']: self.do_inverse(self.config['topfirst']) else: self.do_forward(self.config['topfirst'], repeat_line) def do_forward(self, top_field_first, repeat_line): if self.first_field: in_frame = self.input_buffer['input'].peek() self.in_data = in_frame.as_numpy() else: in_frame = self.input_buffer['input'].get() out_frame = self.outframe_pool['output'].get() out_frame.initialise(in_frame) audit = out_frame.metadata.get('audit') audit += 'data = SimpleDeinterlace(data)\n' audit += ' mode: {}\n'.format(self.config['mode']) audit += ' topfirst: {}\n'.format(self.config['topfirst']) out_frame.metadata.set('audit', audit) out_frame.frame_no = in_frame.frame_no * 2 out_frame.data = numpy.empty( self.in_data.shape, dtype=self.in_data.dtype) ylen = self.in_data.shape[0] if self.first_field == top_field_first: out_frame.data[0::2] = self.in_data[0::2] if repeat_line: stop = ylen - (ylen % 2) out_frame.data[1::2] = self.in_data[0:stop:2] else: out_frame.data[1::2] = 0 else: out_frame.data[1::2] = self.in_data[1::2] if repeat_line: stop = ylen - ((ylen + 1) % 2) out_frame.data[0] = 0 out_frame.data[2::2] = self.in_data[1:stop:2] else: out_frame.data[0::2] = 0 if not self.first_field: out_frame.frame_no += 1 self.send('output', out_frame) self.first_field = not self.first_field def do_inverse(self, top_field_first): in_frame = self.input_buffer['input'].get() if self.first_field: self.first_field_data = in_frame.as_numpy() self.first_field = not self.first_field return out_frame = self.outframe_pool['output'].get() out_frame.initialise(in_frame) second_field_data = in_frame.as_numpy() audit = out_frame.metadata.get('audit') audit += 'data = SimpleReinterlace(data)\n' audit += ' topfirst: {}\n'.format(self.config['topfirst']) out_frame.metadata.set('audit', audit) out_frame.frame_no = in_frame.frame_no // 2 out_frame.data = numpy.empty( second_field_data.shape, dtype=second_field_data.dtype) if top_field_first: out_frame.data[0::2] = self.first_field_data[0::2] out_frame.data[1::2] = second_field_data[1::2] else: out_frame.data[1::2] = self.first_field_data[1::2] out_frame.data[0::2] = second_field_data[0::2] self.send('output', out_frame) self.first_field = not self.first_field