def frame_copy(n: int, f: VideoFrame) -> VideoFrame:
     fout = f.copy()
     frame_data, frame_props = self.get_frame(n, pipe=False)
     if self.compression_method == 'lzo':
         frame_data = pickle.loads(lzo.decompress(frame_data))
     for p in range(fout.format.num_planes):
         np.asarray(fout.get_write_array(p))[:] = frame_data[p]
     for i in frame_props:
         fout.props[i] = frame_props[i]
     return fout
Beispiel #2
0
    def render_raw_videoframe(self, vs_frame: vs.VideoFrame) -> Qt.QPixmap:
        import ctypes

        frame_data = vs_frame.get_read_ptr(0)
        frame_stride = vs_frame.get_stride(0)
        # frame_itemsize = vs_frame.get_read_array(0).itemsize
        frame_itemsize = vs_frame.format.bytes_per_sample

        # powerful spell. do not touch
        frame_data = ctypes.cast(
            frame_data,
            ctypes.POINTER(ctypes.c_char *
                           (frame_itemsize * vs_frame.width *
                            vs_frame.height)))[0]  # type: ignore
        frame_image = Qt.QImage(frame_data, vs_frame.width, vs_frame.height,
                                frame_stride, Qt.QImage.Format_RGB32)
        frame_pixmap = Qt.QPixmap.fromImage(frame_image)

        return frame_pixmap
Beispiel #3
0
 def np_to_frame(array: np.ndarray, frame: vs.VideoFrame, order: tuple = (2, 1, 0)) -> vs.VideoFrame:
     """
     Copies each channel from a numpy array into a vs.VideoFrame.
     It expects the numpy array to be BGR, with the dimension count (C) last in the shape, so HWC or WHC.
     :param array: Numpy array to retrieve planes from.
     :param frame: VapourSynth frame to store retrieved planes.
     :param order: Specify input order of the numpy array color dimensions. It is most likely 2,1,0 (BGR).
     :returns: New frame with planes from numpy array
     """
     frame = frame.copy()
     if list(order) != [0, 1, 2]:
         array = np.transpose(array[:, :, order], (0, 1, 2))  # `order` to RGB
     for plane in range(array.shape[-1]):
         np.copyto(
             np.asarray(frame.get_write_array(plane)),
             array[:, :, plane],
             casting="unsafe"
         )
     return frame
Beispiel #4
0
def frame_to_array(f: vs.VideoFrame) -> np.ndarray:
    """
    Simple wrapper to turn a video frame into an numpy array
    """
    global vs_api_below4
    if vs_api_below4 is None:
        vs_api_below4 = vs.__api_version__.api_major < 4  # type: ignore
    return np.dstack([
        f.get_read_array(p) for p in range(f.format.num_planes)  # type: ignore
    ] if vs_api_below4 else f)
 def extract_value(vs_frame: vs.VideoFrame, i: int, idx: int) \
         -> Union[int, float]:
     fmt = vs_frame.format
     if fmt.sample_type == vs.FLOAT and fmt.bytes_per_sample == 2:
         ptr = ctypes.cast(
             vs_frame.get_read_ptr(i),
             ctypes.POINTER(ctypes.c_char *
                            (2 * vs_frame.width * vs_frame.height)))
         val = unpack('e',
                      ptr.contents[(idx * 2):(idx * 2 +
                                              2)])[0]  # type: ignore
         return cast(float, val)
     else:
         ptr = ctypes.cast(
             vs_frame.get_read_ptr(i),
             ctypes.POINTER(
                 self.data_types[fmt.sample_type][fmt.bytes_per_sample]
                 * (  # type:ignore
                     vs_frame.width * vs_frame.height)))
         return ptr.contents[idx]  # type: ignore
    def _wrap_frame(frame: VideoFrame) -> VideoNode:
        core = get_proxy_or_core()

        bc = core.std.BlankClip(width=frame.width,
                                height=frame.height,
                                length=1,
                                fpsnum=1,
                                fpsden=1,
                                format=frame.format.id)

        return bc.std.ModifyFrame([bc], lambda n, f: frame.copy())
Beispiel #7
0
    def render_raw_videoframe(
            self,
            vs_frame: vs.VideoFrame,
            vs_frame_alpha: Optional[vs.VideoFrame] = None) -> Qt.QPixmap:
        # powerful spell. do not touch
        frame_data_pointer = ctypes.cast(
            vs_frame.get_read_ptr(0),
            ctypes.POINTER(ctypes.c_char *
                           (vs_frame.format.bytes_per_sample * vs_frame.width *
                            vs_frame.height)))[0]
        frame_image = Qt.QImage(frame_data_pointer,
                                vs_frame.width, vs_frame.height,
                                vs_frame.get_stride(0), Qt.QImage.Format_RGB32)

        if vs_frame_alpha is None:
            result_pixmap = Qt.QPixmap.fromImage(frame_image)
        else:
            alpha_data_pointer = ctypes.cast(
                vs_frame_alpha.get_read_ptr(0),
                ctypes.POINTER(
                    ctypes.c_char *
                    (vs_frame_alpha.format.bytes_per_sample *
                     vs_frame_alpha.width * vs_frame_alpha.height)))[0]
            alpha_image = Qt.QImage(alpha_data_pointer, vs_frame.width,
                                    vs_frame.height,
                                    vs_frame_alpha.get_stride(0),
                                    Qt.QImage.Format_Alpha8)

            result_image = Qt.QImage(vs_frame.width, vs_frame.height,
                                     Qt.QImage.Format_ARGB32_Premultiplied)
            painter = Qt.QPainter(result_image)
            painter.setCompositionMode(Qt.QPainter.CompositionMode_Source)
            painter.drawImage(0, 0, frame_image)
            painter.setCompositionMode(
                Qt.QPainter.CompositionMode_DestinationIn)
            painter.drawImage(0, 0, alpha_image)
            painter.end()

            result_pixmap = Qt.QPixmap.fromImage(result_image)

        return result_pixmap
    def render_raw_videoframe(
            self,
            vs_frame: vs.VideoFrame,
            vs_frame_alpha: Optional[vs.VideoFrame] = None) -> Qt.QImage:
        # powerful spell. do not touch
        frame_data_pointer = ctypes.cast(
            vs_frame.get_read_ptr(0),
            ctypes.POINTER(ctypes.c_char * (vs_frame.format.bytes_per_sample *
                                            vs_frame.width * vs_frame.height)))
        frame_image = Qt.QImage(frame_data_pointer.contents,
                                vs_frame.width, vs_frame.height,
                                vs_frame.get_stride(0), Qt.QImage.Format_RGB32)

        if vs_frame_alpha is None:
            return frame_image

        alpha_data_pointer = ctypes.cast(
            vs_frame_alpha.get_read_ptr(0),
            ctypes.POINTER(ctypes.c_char *
                           (vs_frame_alpha.format.bytes_per_sample *
                            vs_frame_alpha.width * vs_frame_alpha.height)))
        alpha_image = Qt.QImage(alpha_data_pointer.contents, vs_frame.width,
                                vs_frame.height, vs_frame_alpha.get_stride(0),
                                Qt.QImage.Format_Alpha8)

        result_image = Qt.QImage(vs_frame.width, vs_frame.height,
                                 Qt.QImage.Format_ARGB32_Premultiplied)
        painter = Qt.QPainter(result_image)
        painter.setCompositionMode(Qt.QPainter.CompositionMode_Source)
        painter.drawImage(0, 0, frame_image)
        painter.setCompositionMode(Qt.QPainter.CompositionMode_DestinationIn)
        painter.drawImage(0, 0, alpha_image)
        if self.main.CHECKERBOARD_ENABLED:
            painter.setCompositionMode(
                Qt.QPainter.CompositionMode_DestinationOver)
            painter.drawImage(0, 0, self.checkerboard)
        painter.end()

        return result_image
 def extract_value(vs_frame: vs.VideoFrame, plane: int,
                   pos: Qt.QPoint) -> Union[int, float]:
     fmt = vs_frame.format
     stride = vs_frame.get_stride(plane)
     if fmt.sample_type == vs.FLOAT and fmt.bytes_per_sample == 2:
         ptr = ctypes.cast(
             vs_frame.get_read_ptr(plane),
             ctypes.POINTER(ctypes.c_char * (stride * vs_frame.height)))
         offset = pos.y() * stride + pos.x() * 2
         val = unpack('e', ptr.contents[offset:(offset +
                                                2)])[0]  # type: ignore
         return cast(float, val)
     else:
         ptr = ctypes.cast(
             vs_frame.get_read_ptr(plane),
             ctypes.POINTER(
                 self.data_types[fmt.sample_type][fmt.bytes_per_sample]
                 * (  # type:ignore
                     stride * vs_frame.height)))
         logical_stride = stride // fmt.bytes_per_sample
         idx = pos.y() * logical_stride + pos.x()
         return ptr.contents[idx]  # type: ignore
Beispiel #10
0
def extract_plane(buffer: Buffer, offset: int, frame: VideoFrame,
                  planeno: int):
    """
    Extracts the plane with the VapourSynth R37+ array-API.

    :param buffer:  Target buffer
    :param offset:  Where to write it
    :param frame:   The frame
    :param planeno: The plane number
    :return: The extracted image.
    """
    arr = frame.get_read_array(planeno)
    length = len(arr)

    if length + offset > len(buffer):
        raise BufferError("Buffer too short.")

    buffer[offset:offset + length] = arr

    return len(arr)
Beispiel #11
0
 def disable_rff(n: int, f: vs.VideoFrame) -> vs.VideoFrame:
     f = f.copy()
     f.props["PVSFlagRff"] = 0
     return f
Beispiel #12
0
 def frame_to_np(frame: vs.VideoFrame) -> np.dstack:
     """
     Alternative to cv2.imread() that will directly read images to a numpy array.
     :param frame: VapourSynth frame from a clip
     """
     return np.dstack([np.asarray(frame.get_read_array(i)) for i in range(frame.format.num_planes)])
Beispiel #13
0
    def write_subs(self, n: int, f: vs.VideoFrame, clip: vs.VideoNode,
                   sub: str) -> vs.VideoNode:
        """
        Log scene changes to a file.

        Notes
        -----
        The file is formatted as <frame_number> 0 1
        if it's the last frame in the scene,
        1 0 if it's the first one

        Parameters
        ----------
        n:
            The frame number
        f:
            The frame properties
        clip:
            The input clip
        sub:
            The sub filename

        Returns
        -------
        vs.VideoNode
            The same clip as the input
        """
        if f.props["_SceneChangeNext"] == 1 or f.props["_SceneChangePrev"] == 1:
            img = Image.fromarray(np.array(f.get_read_array(0), copy=False))
            if not img.getextrema() == (0, 0):
                if f.props["_SceneChangePrev"] == 1:
                    frame_time = convert((n * clip.fps_den / clip.fps_num))
                    img = ImageOps.invert(img)
                    self.sub_count += 1
                    self.frame_num = n
                    ocr_out = tesserocr.image_to_text(
                        img,
                        lang=self.language,
                        psm=tesserocr.PSM.SINGLE_BLOCK,
                        path=self.tessdata,
                    )
                    with open(sub, "a") as sub_io:
                        sub_io.write(f"""
{self.sub_count}
{frame_time} -->
{ocr_out}
""")
                elif f.props["_SceneChangeNext"] == 1:
                    frame_time = convert(
                        ((n + 1) * clip.fps_den / clip.fps_num))
                    with open(sub, "r") as sub_io:
                        lines = sub_io.readlines()
                    with open(sub, "w") as sub_io:
                        for idx, line in enumerate(lines):
                            if (line.strip() == str(self.sub_count)
                                    and self.frame_num < n):
                                times = lines[idx + 1].strip()
                                lines[idx + 1] = f"{times} {frame_time}\n"
                            elif (line.strip() == str(self.sub_count - 1)
                                  and self.frame_num > n):
                                times = lines[idx + 1].strip()
                                lines[idx + 1] = f"{times} {frame_time}\n"

                        sub_io.writelines(lines)

        return clip