Python: проблемы стеганографии в процессе сохранения (cv2.imwrite) и чтения (cv2.imread) с использованием OpenCV

#python #python-3.x #opencv #watermark #steganography

#python #python-3.x #opencv #водяной знак #стеганография

Вопрос:

У меня есть код стеганографии, который скрывает изображение внутри другого изображения.

Я добавляю водяной знак в мое изображение с помощью этого кода.

Принцип очень прост.

Я использовал source_image и watermark_images для вставки водяного знака.

Это приведет к случайному распределению watermark_images .

введите описание изображения здесь

Сначала разбросайте x и y изображения водяного знака, используя случайные начальные значения.

А затем преобразуйте source_image в частотную область с помощью быстрого преобразования Фурье.

Наконец, объедините watermark_layer с частотной областью source_image .

введите описание изображения здесь

Этот процесс кодирования работает отлично. Однако в процессе декодирования возникает проблема.

Код декодирования собирает пиксели, разбросанные случайными семенами, в одном месте по тому же принципу.

Это результат декодирования:

введите описание изображения здесь

эта проблема, если я пытаюсь сохранить закодированное изображение (cv2.imwrite) и отозвать (cv2.imread), декодирование не работает.

Если я использую закодированный объект как есть, проблем нет. Поврежден ли пиксель во время процесса сохранения и отзыва?

это мой полный код:

 import cv2 as cv
import numpy as np
import random
import time


class Watermark:
    def __init__(self):
        self.watermark_image = cv.imread('../Watermark/google_logo.png')
        self.result_image_path = '../Watermark/result.jpg'
        self.random_seed = 2021
        self.alpha = 5

    def encoding(self, image_path):
        # Code Start
        start_time = time.time()

        # Read Image
        source_image = cv.imread(image_path)
        source_height, source_width, _ = source_image.shape
        watermark_height, watermark_width, _ = self.watermark_image.shape

        print('source height : ', source_height, ', source_width : ', source_width)
        print('watermark height : ', watermark_height, ', watermark width : ', watermark_width)

        # Convert image to frequency area with Fast Fourier Transform (image -> frequency)
        source_frequency = np.fft.fft2(source_image)

        # Get random seed
        y_random_indices, x_random_indices = list(range(source_height)), list(range(source_width))
        random.seed(self.random_seed)
        random.shuffle(x_random_indices)
        random.shuffle(y_random_indices)

        print('y random seed : ', y_random_indices)
        print('x random seed : ', x_random_indices)

        # Injection watermark
        watermark_layer = np.zeros(source_image.shape, dtype=np.uint8)
        for y in range(watermark_height):
            for x in range(watermark_width):
                watermark_layer[y_random_indices[y], x_random_indices[x]] = self.watermark_image[y, x]

        # Encoding frequency area   watermark layer
        result_frequency = source_frequency   self.alpha * watermark_layer

        # Apply Inverse Fast Fourier Transform (frequency -> image)
        result_image = np.fft.ifft2(result_frequency)
        result_image = np.real(result_image)
        result_image = result_image.astype(np.uint8)

        # Show elapsed time
        end_time = time.time()
        print('Encoding elapsed time : ', end_time - start_time, 'n')

        # Visualization
        cv.imshow('source_image', source_image)
        cv.imshow('watermark', self.watermark_image)
        cv.imshow('watermark_layer', watermark_layer)
        cv.imshow('result_image', result_image)

        # Save and Close
        cv.imwrite(self.result_image_path, result_image)
        cv.waitKey(0)
        cv.destroyAllWindows()

        return result_image

    def decoding(self, source_image_path, encoded_image):
        # Code Start
        start_time = time.time()

        # Read Image
        source_image = cv.imread(source_image_path)

        source_height, source_width, _ = source_image.shape
        print('original_height : ', source_height)
        print('original_width : ', source_width)

        encoded_height, encoded_width, _ = encoded_image.shape

        # Convert image to frequency area with Fast Fourier Transform (image -> frequency)
        source_frequency = np.fft.fft2(source_image)
        encoded_frequency = np.fft.fft2(encoded_image)

        # Convert frequency area to image (frequency -> image)
        watermark_layer = (source_frequency - encoded_frequency) / self.alpha
        watermark_layer = np.real(watermark_layer).astype(np.uint8)

        # Get random seed
        y_random_indices, x_random_indices = [list(range(encoded_height)), list(range(encoded_width))]
        random.seed(self.random_seed)
        random.shuffle(x_random_indices)
        random.shuffle(y_random_indices)

        print('y random seed : ', y_random_indices)
        print('x random seed : ', x_random_indices)

        # Restore watermark
        result_image = np.zeros(watermark_layer.shape, dtype=np.uint8)

        for y in range(encoded_height):
            for x in range(encoded_width):
                result_image[y, x] = watermark_layer[y_random_indices[y], x_random_indices[x]]

        # Show elapsed time
        end_time = time.time()
        print('Encoding elapsed time : ', end_time - start_time, 'n')

        # Visualization
        cv.imshow('original image', source_image)
        cv.imshow('target image', encoded_image)
        cv.imshow('watermark layer', watermark_layer)
        cv.imshow('result image', result_image)
        cv.waitKey(0)
        cv.destroyAllWindows()


if __name__ == '__main__':
    source_path = '../Watermark/jennie.jpg'

    # good work
    protected_image = Watermark().encoding(source_path)
    Watermark().decoding(source_path, protected_image)

    # doesn't work
    result_path = '../Watermark/result.jpg'
    result_image = cv.imread(result_path)
    Watermark().decoding(source_path, result_image)
 

Пожалуйста, дайте мне несколько советов.

Комментарии:

1. Вы пробовали использовать формат изображения без потерь, такой как png? Я не уверен, что сжатие jpg не мешает вашим начальным кодировкам

Ответ №1:

У Карлоса Мелуса есть хорошая точка зрения.

Ваш код не подходит для обработки изображений в формате jpg.

если вы используете формат png, это сработает хорошо.