Skip to content

DCTMKV

stegobox.codec.DCTMKV

Bases: BaseCodec

This module implements DCT steganography of str in mkv videos.

with code shamelessly taken from nguyencuong1002/Video-Steganography

Source code in stegobox/codec/dct_mkv/dct_mkv.py
class DCTMKV(BaseCodec):
    """This module implements DCT steganography of str in mkv videos.

    with code shamelessly taken from
    [nguyencuong1002/Video-Steganography](https://github.com/nguyencuong1002/Video-Steganography)
    """

    def __init__(self) -> None:
        super().__init__()

    def encode(
        self, carrier: cv2.VideoCapture, payload: str
    ) -> tuple[list[numpy.ndarray], int, tuple[int, int]]:
        """Encoder requires the carrier video to be a videocapture
            and the payload to be a string.

        Args:
            carrier: Carrier video in format MKV. Read with `stegobox.io.video.read()`.
            payload: Payload (secret message) to be encoded.

        Returns:
            A list of encrypted collection of images.
            Video framerate.
            Video size.
        """

        # get frames from video
        video_to_frames(carrier)
        # choose frame to encode
        img_name = "frames/frame10.png"
        # img = io.image.read_cv2(img_name)
        img = cv2.imread(img_name, cv2.IMREAD_UNCHANGED)
        encoded_img = DCT().encode_image(img, payload)
        # io.image.write_cv2(encoded_img, img_name)
        cv2.imwrite(img_name, encoded_img)

        path = "./frames"
        # ignore .DS_Store
        files = [f for f in listdir(path) if not f.startswith(".")]

        # sort files in correct order
        files.sort(key=lambda x: int(x[5:-4]))  # x[5:-4] is the number
        img_array = []
        size = (0, 0)
        for f in files:
            filename = join(path, f)
            img = cv2.imread(filename, cv2.IMREAD_UNCHANGED)
            # img = io.image.read_cv2(filename)
            height, width, layers = img.shape
            size = (width, height)
            img_array.append(img)

        shutil.rmtree("frames")
        return img_array, carrier.get(cv2.CAP_PROP_FPS), size

    def decode(self, carrier: cv2.VideoCapture) -> str:
        """Decode the secret payload from the carrier video

        Args:
            carrier: Carrier video in format MKV. Read with `stegobox.io.video.read()`.

        Returns:
            str: The decoded payload (secret message).
        """
        video_to_frames(carrier)
        path = "frames/"
        files = [f for f in os.listdir(path) if not f.startswith(".")]
        hidden_text = ""
        for file in files:
            filename = os.path.join(path, file)
            # img = io.image.read_cv2(filename)
            img = cv2.imread(filename, cv2.IMREAD_UNCHANGED)
            hidden_text = DCT().decode_image(img)
            if hidden_text != "":
                break
        shutil.rmtree("frames")
        return hidden_text

encode(carrier, payload)

Encoder requires the carrier video to be a videocapture and the payload to be a string.

Parameters:

Name Type Description Default
carrier VideoCapture

Carrier video in format MKV. Read with stegobox.io.video.read().

required
payload str

Payload (secret message) to be encoded.

required

Returns:

Type Description
list[ndarray]

A list of encrypted collection of images.

int

Video framerate.

tuple[int, int]

Video size.

Source code in stegobox/codec/dct_mkv/dct_mkv.py
def encode(
    self, carrier: cv2.VideoCapture, payload: str
) -> tuple[list[numpy.ndarray], int, tuple[int, int]]:
    """Encoder requires the carrier video to be a videocapture
        and the payload to be a string.

    Args:
        carrier: Carrier video in format MKV. Read with `stegobox.io.video.read()`.
        payload: Payload (secret message) to be encoded.

    Returns:
        A list of encrypted collection of images.
        Video framerate.
        Video size.
    """

    # get frames from video
    video_to_frames(carrier)
    # choose frame to encode
    img_name = "frames/frame10.png"
    # img = io.image.read_cv2(img_name)
    img = cv2.imread(img_name, cv2.IMREAD_UNCHANGED)
    encoded_img = DCT().encode_image(img, payload)
    # io.image.write_cv2(encoded_img, img_name)
    cv2.imwrite(img_name, encoded_img)

    path = "./frames"
    # ignore .DS_Store
    files = [f for f in listdir(path) if not f.startswith(".")]

    # sort files in correct order
    files.sort(key=lambda x: int(x[5:-4]))  # x[5:-4] is the number
    img_array = []
    size = (0, 0)
    for f in files:
        filename = join(path, f)
        img = cv2.imread(filename, cv2.IMREAD_UNCHANGED)
        # img = io.image.read_cv2(filename)
        height, width, layers = img.shape
        size = (width, height)
        img_array.append(img)

    shutil.rmtree("frames")
    return img_array, carrier.get(cv2.CAP_PROP_FPS), size

decode(carrier)

Decode the secret payload from the carrier video

Parameters:

Name Type Description Default
carrier VideoCapture

Carrier video in format MKV. Read with stegobox.io.video.read().

required

Returns:

Name Type Description
str str

The decoded payload (secret message).

Source code in stegobox/codec/dct_mkv/dct_mkv.py
def decode(self, carrier: cv2.VideoCapture) -> str:
    """Decode the secret payload from the carrier video

    Args:
        carrier: Carrier video in format MKV. Read with `stegobox.io.video.read()`.

    Returns:
        str: The decoded payload (secret message).
    """
    video_to_frames(carrier)
    path = "frames/"
    files = [f for f in os.listdir(path) if not f.startswith(".")]
    hidden_text = ""
    for file in files:
        filename = os.path.join(path, file)
        # img = io.image.read_cv2(filename)
        img = cv2.imread(filename, cv2.IMREAD_UNCHANGED)
        hidden_text = DCT().decode_image(img)
        if hidden_text != "":
            break
    shutil.rmtree("frames")
    return hidden_text