From 76de0b0454e1e53f11c562d16f93f676cbbe3b10 Mon Sep 17 00:00:00 2001 From: TheKekening Date: Sat, 9 Sep 2023 13:59:50 +0100 Subject: [PATCH 1/9] PotatoAim's fourier stuff (Note to judges, I committed this because of technical difficulties on PotatoAims end) --- src/EE/fourier/How_To_Use.md | 60 +++++++++++ src/EE/fourier/fourier_transform_decoder.py | 43 ++++++++ src/EE/fourier/main.py | 106 ++++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 src/EE/fourier/How_To_Use.md create mode 100644 src/EE/fourier/fourier_transform_decoder.py create mode 100644 src/EE/fourier/main.py diff --git a/src/EE/fourier/How_To_Use.md b/src/EE/fourier/How_To_Use.md new file mode 100644 index 0000000..6451f44 --- /dev/null +++ b/src/EE/fourier/How_To_Use.md @@ -0,0 +1,60 @@ +# User Guide: How to Watermark Your Digital Art or Photography Using Fourier Transform + +## Introduction + +Hello, dear artist or photographer! Want to protect your magnificent creations with some tech magic? You're in the right place! This guide will walk you through watermarking your images using a technique called Fourier Transform. This method embeds the watermark into the frequency domain of the image, making it difficult to remove without specialized knowledge. In simpler terms, it's a robust way to safeguard your work without affecting its visual quality. + +--- + +## Requirements + +- Python installed on your computer +- The encoder and decoder scripts +- The image you want to watermark (in `.png`, `.jpg`, or `.tiff` formats) + +--- + +## Step-by-Step Instructions + +### Watermarking Your Image (Encoding) + +1. **Open the Terminal or Command Prompt** + - Navigate to the folder where the encoder script is located. + +2. **Run the Encoder Script** + - Type `python encoder.py` and press Enter. + +3. **Enter the Watermark Text** + - You'll be prompted to enter the text you want to use as a watermark. This could be your name, brand, or any other identifying info. + +4. **Select the Image File** + - You'll be prompted to provide the path to the image file you want to watermark. Enter the full path to the image. + +5. **Check for Success** + - If everything goes well, you'll see messages indicating that the watermark has been successfully embedded. The watermarked image will be saved in the same folder with the suffix `_watermarked`. + +### Verifying the Watermark (Decoding) + +1. **Open the Terminal or Command Prompt** + - Navigate to the folder where the decoder script is located. + +2. **Run the Decoder Script** + - Type `python decoder.py` and press Enter. + +3. **Enter the Original Watermark Text** + - You'll be prompted to enter the original text that was used for watermarking. Make sure to enter it exactly as you did during the encoding process. + +4. **Select the Watermarked Image File** + - You'll be prompted to provide the path to the watermarked image file. Enter the full path to the image. + +5. **Check for Success** + - If all goes well, the script will display the watermark text extracted from the image. It should match the text you originally entered. + +--- + +## Final Thoughts + +And there you have it! You've successfully watermarked your artwork using Fourier Transform methods. While this watermark is not visible, it's embedded in a technically complex way that makes it difficult to remove, providing an extra layer of security for your creations. + +Remember, this is not a 100% foolproof method, but it adds a layer of protection that can deter unauthorized use of your work. + diff --git a/src/EE/fourier/fourier_transform_decoder.py b/src/EE/fourier/fourier_transform_decoder.py new file mode 100644 index 0000000..50edaff --- /dev/null +++ b/src/EE/fourier/fourier_transform_decoder.py @@ -0,0 +1,43 @@ +from PIL import Image +import numpy as np + +def load_image(): + image_path = input("Enter the path to the watermarked image file: ") + try: + return Image.open(image_path) + except FileNotFoundError: + print("Image not found. Exiting.") + exit() + +def fourier_transform_color(image): + image_array = np.array(image) + red, green, blue = image_array[:,:,0], image_array[:,:,1], image_array[:,:,2] + red_freq = np.fft.fft2(red) + green_freq = np.fft.fft2(green) + blue_freq = np.fft.fft2(blue) + return red_freq, green_freq, blue_freq + +def extract_watermark(frequency_domain, watermark_length): + magnitude = np.abs(frequency_domain) + watermark_data = magnitude[0, 0:watermark_length] + print(f"Debug: Extracted data from magnitude: {watermark_data}") + watermark_text = ''.join([chr(int(round(x))) for x in watermark_data]) + return watermark_text + + + +def main(): + watermark_text = input("Enter the watermark text that was used for encoding: ") + image = load_image() + watermark_length = len(watermark_text) + + try: + loaded_red_freq_watermarked = np.load(f"red_freq_watermarked_{watermark_text}.npy") + watermark_text_red = extract_watermark(loaded_red_freq_watermarked, watermark_length) + print(f"Extracted watermark text from the red channel is: {watermark_text_red}") + except FileNotFoundError: + print("Frequency domain data not found. Exiting.") + exit() + +if __name__ == "__main__": + main() diff --git a/src/EE/fourier/main.py b/src/EE/fourier/main.py new file mode 100644 index 0000000..d94aa6f --- /dev/null +++ b/src/EE/fourier/main.py @@ -0,0 +1,106 @@ +from PIL import Image +import numpy as np + + +def get_watermark_text(): + return input("Enter the watermark text: ") + + +def load_image(): + image_path = input("Enter the path to the image file: ") + try: + return Image.open(image_path) + except FileNotFoundError: + print("Image not found. Please check the path and try again.") + return None +def shift_to_center(frequency_domain): + return np.fft.fftshift(frequency_domain) + +def shift_to_corners(frequency_domain): + return np.fft.ifftshift(frequency_domain) + + + +def fourier_transform_color(image): + image_array = np.array(image) + red, green, blue = image_array[:, :, 0], image_array[:, :, 1], image_array[:, :, 2] + red_freq = shift_to_center(np.fft.fft2(red)) + green_freq = shift_to_center(np.fft.fft2(green)) + blue_freq = shift_to_center(np.fft.fft2(blue)) + return red_freq, green_freq, blue_freq + + + +def embed_watermark_to_color_channel(magnitude, phase, watermark_array): + # Embed watermark into magnitude + magnitude[0:1, 0:watermark_array.shape[1]] = watermark_array + + # Print debug information + # print("Debug: Portion of magnitude where watermark is embedded:") + # print(magnitude[0:1, 0:watermark_array.shape[1]]) + print(f"Debug: Portion of magnitude where watermark is embedded:\n{magnitude[0:1, 0:watermark_array.shape[1]]}") + frequency_domain_watermarked = magnitude * np.exp(1j * phase) + + return frequency_domain_watermarked + + +def inverse_fourier_transform_color(red_freq, green_freq, blue_freq): + red = np.fft.ifft2(shift_to_corners(red_freq)) + green = np.fft.ifft2(shift_to_corners(green_freq)) + blue = np.fft.ifft2(shift_to_corners(blue_freq)) + color_image_array = np.stack([np.real(red), np.real(green), np.real(blue)], axis=2) + color_image_array = np.uint8(color_image_array) + return Image.fromarray(color_image_array, 'RGB') + + +def save_image(image, watermark_text): + try: + image.save(f"watermaked_{watermark_text}.tiff") + print(f"Watermarked image saved as 'watermaked_{watermark_text}.tiff'") + + except Exception as e: + print(f"Failed to save image: {e}") + +def main(): + watermark_text = get_watermark_text() + image = load_image() + + if image: + print(f"Successfully loaded image. Watermark text is: {watermark_text}") + + red_freq, green_freq, blue_freq = fourier_transform_color(image) + print("Successfully loaded image to frequency domain.") + + + watermark_array = np.array([[ord(char) for char in watermark_text]]) + + # Separate magnitude and phase for each color channel + red_magnitude, red_phase = np.abs(red_freq), np.angle(red_freq) + green_magnitude, green_phase = np.abs(green_freq), np.angle(green_freq) + blue_magnitude, blue_phase = np.abs(blue_freq), np.angle(blue_freq) + + # Embed the watermark and get the watermarked frequency domain + red_freq_watermarked = embed_watermark_to_color_channel(red_magnitude, red_phase, watermark_array) + green_freq_watermarked = embed_watermark_to_color_channel(green_magnitude, green_phase, watermark_array) + blue_freq_watermarked = embed_watermark_to_color_channel(blue_magnitude, blue_phase, watermark_array) + # Save the frequency domain data to disk + np.save(f"red_freq_watermarked_{watermark_text}.npy", red_freq_watermarked) + + print("Successfully embedded watermark into frequency domain.") + print(f"Debug: Red frequency domain after watermark: {np.abs(red_freq_watermarked)[0, 0:10]}") + + watermarked_image = inverse_fourier_transform_color( + red_freq_watermarked, green_freq_watermarked, blue_freq_watermarked + ) + print("Successfully transformed image back to spatial domain.") + + save_image(watermarked_image, watermark_text) + + loaded_image = Image.open(f"watermaked_{watermark_text}.tiff") + loaded_red_freq, _, _ = fourier_transform_color(loaded_image) + print(f"Debug: Loaded red frequency domain: {np.abs(loaded_red_freq)[0, 0:10]}") + else: + print("Failed to load image. Exiting.") + +if __name__ == "__main__": + main() \ No newline at end of file From c2f505e83394cf58564c5f1b6518873b90c50157 Mon Sep 17 00:00:00 2001 From: i-am-unknown-81514525 <74453352+i-am-unknown-81514525@users.noreply.github.com> Date: Sat, 9 Sep 2023 23:46:32 +0100 Subject: [PATCH 2/9] Remove encryption=None as an potential option --- src/EE/Stego/main.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/EE/Stego/main.py b/src/EE/Stego/main.py index 2d2de09..038af18 100644 --- a/src/EE/Stego/main.py +++ b/src/EE/Stego/main.py @@ -63,16 +63,10 @@ class Steganography(utils.LibraryBase): # noqa: E501 def __init__(self): super().__init__() - self.enc_input = [{"field": "Encryption Method", 'options': [{"name": "No encryption", "id": "none"}, - {"name": "AES-256", "id": "aes256"}], - 'type': 'select', 'id': 'en/dec'}, - {"field": "Message", 'type': 'text_large', 'id': 'msg'}, + self.enc_input = [{"field": "Message", 'type': 'text_large', 'id': 'msg'}, {"field": "Secret(Required to decrypt the image)", 'type': 'text_small', 'id': 'passcode'}, {"field": "Image", 'type': 'image_button', 'id': 'img'}] - self.dec_input = [{"field": "Encryption Method", 'options': [{"name": "No encryption", "id": "none"}, - {"name": "AES-256", "id": "aes256"}], - 'type': 'select', 'id': 'en/dec'}, - {"field": "Secret(Required to decrypt the image)", 'type': 'text_small', 'id': 'passcode'}, + self.dec_input = [{"field": "Secret(Required to decrypt the image)", 'type': 'text_small', 'id': 'passcode'}, {"field": "Image", 'type': 'image_button', 'id': 'img'}] self.enc_output = [{"type": "image_button", "id": "img_down"}] self.dec_output = [{"type": "msg", "id": "msg"}] From 96d193edabbad39e19dfcc1842da69224cd80008 Mon Sep 17 00:00:00 2001 From: Flonc Date: Sun, 10 Sep 2023 00:13:50 +0100 Subject: [PATCH 3/9] =?UTF-8?q?=F0=9F=9A=A7=20Some=20formatting=20(still?= =?UTF-8?q?=20needs=20docstrings)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/EE/fourier/fourier_transform_decoder.py | 19 +++++++---- src/EE/fourier/main.py | 36 ++++++++++++++------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/EE/fourier/fourier_transform_decoder.py b/src/EE/fourier/fourier_transform_decoder.py index 50edaff..edc9cd8 100644 --- a/src/EE/fourier/fourier_transform_decoder.py +++ b/src/EE/fourier/fourier_transform_decoder.py @@ -1,5 +1,6 @@ -from PIL import Image import numpy as np +from PIL import Image + def load_image(): image_path = input("Enter the path to the watermarked image file: ") @@ -9,35 +10,41 @@ def load_image(): print("Image not found. Exiting.") exit() + def fourier_transform_color(image): image_array = np.array(image) - red, green, blue = image_array[:,:,0], image_array[:,:,1], image_array[:,:,2] + red, green, blue = image_array[:, :, 0], image_array[:, :, 1], image_array[:, :, 2] red_freq = np.fft.fft2(red) green_freq = np.fft.fft2(green) blue_freq = np.fft.fft2(blue) return red_freq, green_freq, blue_freq + def extract_watermark(frequency_domain, watermark_length): magnitude = np.abs(frequency_domain) watermark_data = magnitude[0, 0:watermark_length] print(f"Debug: Extracted data from magnitude: {watermark_data}") - watermark_text = ''.join([chr(int(round(x))) for x in watermark_data]) + watermark_text = "".join([chr(int(round(x))) for x in watermark_data]) return watermark_text - def main(): watermark_text = input("Enter the watermark text that was used for encoding: ") image = load_image() watermark_length = len(watermark_text) try: - loaded_red_freq_watermarked = np.load(f"red_freq_watermarked_{watermark_text}.npy") - watermark_text_red = extract_watermark(loaded_red_freq_watermarked, watermark_length) + loaded_red_freq_watermarked = np.load( + f"red_freq_watermarked_{watermark_text}.npy" + ) + watermark_text_red = extract_watermark( + loaded_red_freq_watermarked, watermark_length + ) print(f"Extracted watermark text from the red channel is: {watermark_text_red}") except FileNotFoundError: print("Frequency domain data not found. Exiting.") exit() + if __name__ == "__main__": main() diff --git a/src/EE/fourier/main.py b/src/EE/fourier/main.py index d94aa6f..aaacb88 100644 --- a/src/EE/fourier/main.py +++ b/src/EE/fourier/main.py @@ -1,5 +1,5 @@ -from PIL import Image import numpy as np +from PIL import Image def get_watermark_text(): @@ -13,14 +13,16 @@ def load_image(): except FileNotFoundError: print("Image not found. Please check the path and try again.") return None + + def shift_to_center(frequency_domain): return np.fft.fftshift(frequency_domain) + def shift_to_corners(frequency_domain): return np.fft.ifftshift(frequency_domain) - def fourier_transform_color(image): image_array = np.array(image) red, green, blue = image_array[:, :, 0], image_array[:, :, 1], image_array[:, :, 2] @@ -30,15 +32,16 @@ def fourier_transform_color(image): return red_freq, green_freq, blue_freq - def embed_watermark_to_color_channel(magnitude, phase, watermark_array): # Embed watermark into magnitude - magnitude[0:1, 0:watermark_array.shape[1]] = watermark_array + magnitude[0:1, 0 : watermark_array.shape[1]] = watermark_array # Print debug information # print("Debug: Portion of magnitude where watermark is embedded:") # print(magnitude[0:1, 0:watermark_array.shape[1]]) - print(f"Debug: Portion of magnitude where watermark is embedded:\n{magnitude[0:1, 0:watermark_array.shape[1]]}") + print( + f"Debug: Portion of magnitude where watermark is embedded:\n{magnitude[0:1, 0:watermark_array.shape[1]]}" + ) frequency_domain_watermarked = magnitude * np.exp(1j * phase) return frequency_domain_watermarked @@ -50,7 +53,7 @@ def inverse_fourier_transform_color(red_freq, green_freq, blue_freq): blue = np.fft.ifft2(shift_to_corners(blue_freq)) color_image_array = np.stack([np.real(red), np.real(green), np.real(blue)], axis=2) color_image_array = np.uint8(color_image_array) - return Image.fromarray(color_image_array, 'RGB') + return Image.fromarray(color_image_array, "RGB") def save_image(image, watermark_text): @@ -61,6 +64,7 @@ def save_image(image, watermark_text): except Exception as e: print(f"Failed to save image: {e}") + def main(): watermark_text = get_watermark_text() image = load_image() @@ -71,7 +75,6 @@ def main(): red_freq, green_freq, blue_freq = fourier_transform_color(image) print("Successfully loaded image to frequency domain.") - watermark_array = np.array([[ord(char) for char in watermark_text]]) # Separate magnitude and phase for each color channel @@ -80,14 +83,22 @@ def main(): blue_magnitude, blue_phase = np.abs(blue_freq), np.angle(blue_freq) # Embed the watermark and get the watermarked frequency domain - red_freq_watermarked = embed_watermark_to_color_channel(red_magnitude, red_phase, watermark_array) - green_freq_watermarked = embed_watermark_to_color_channel(green_magnitude, green_phase, watermark_array) - blue_freq_watermarked = embed_watermark_to_color_channel(blue_magnitude, blue_phase, watermark_array) + red_freq_watermarked = embed_watermark_to_color_channel( + red_magnitude, red_phase, watermark_array + ) + green_freq_watermarked = embed_watermark_to_color_channel( + green_magnitude, green_phase, watermark_array + ) + blue_freq_watermarked = embed_watermark_to_color_channel( + blue_magnitude, blue_phase, watermark_array + ) # Save the frequency domain data to disk np.save(f"red_freq_watermarked_{watermark_text}.npy", red_freq_watermarked) print("Successfully embedded watermark into frequency domain.") - print(f"Debug: Red frequency domain after watermark: {np.abs(red_freq_watermarked)[0, 0:10]}") + print( + f"Debug: Red frequency domain after watermark: {np.abs(red_freq_watermarked)[0, 0:10]}" + ) watermarked_image = inverse_fourier_transform_color( red_freq_watermarked, green_freq_watermarked, blue_freq_watermarked @@ -102,5 +113,6 @@ def main(): else: print("Failed to load image. Exiting.") + if __name__ == "__main__": - main() \ No newline at end of file + main() From 3ae00d5b585f96ba281af01193da2b139164593a Mon Sep 17 00:00:00 2001 From: Flonc Date: Sun, 10 Sep 2023 00:13:50 +0100 Subject: [PATCH 4/9] =?UTF-8?q?=F0=9F=9A=A7=20Some=20formatting=20(still?= =?UTF-8?q?=20needs=20docstrings)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/EE/fourier/fourier_transform_decoder.py | 19 +++++++---- src/EE/fourier/main.py | 36 ++++++++++++++------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/EE/fourier/fourier_transform_decoder.py b/src/EE/fourier/fourier_transform_decoder.py index 50edaff..edc9cd8 100644 --- a/src/EE/fourier/fourier_transform_decoder.py +++ b/src/EE/fourier/fourier_transform_decoder.py @@ -1,5 +1,6 @@ -from PIL import Image import numpy as np +from PIL import Image + def load_image(): image_path = input("Enter the path to the watermarked image file: ") @@ -9,35 +10,41 @@ def load_image(): print("Image not found. Exiting.") exit() + def fourier_transform_color(image): image_array = np.array(image) - red, green, blue = image_array[:,:,0], image_array[:,:,1], image_array[:,:,2] + red, green, blue = image_array[:, :, 0], image_array[:, :, 1], image_array[:, :, 2] red_freq = np.fft.fft2(red) green_freq = np.fft.fft2(green) blue_freq = np.fft.fft2(blue) return red_freq, green_freq, blue_freq + def extract_watermark(frequency_domain, watermark_length): magnitude = np.abs(frequency_domain) watermark_data = magnitude[0, 0:watermark_length] print(f"Debug: Extracted data from magnitude: {watermark_data}") - watermark_text = ''.join([chr(int(round(x))) for x in watermark_data]) + watermark_text = "".join([chr(int(round(x))) for x in watermark_data]) return watermark_text - def main(): watermark_text = input("Enter the watermark text that was used for encoding: ") image = load_image() watermark_length = len(watermark_text) try: - loaded_red_freq_watermarked = np.load(f"red_freq_watermarked_{watermark_text}.npy") - watermark_text_red = extract_watermark(loaded_red_freq_watermarked, watermark_length) + loaded_red_freq_watermarked = np.load( + f"red_freq_watermarked_{watermark_text}.npy" + ) + watermark_text_red = extract_watermark( + loaded_red_freq_watermarked, watermark_length + ) print(f"Extracted watermark text from the red channel is: {watermark_text_red}") except FileNotFoundError: print("Frequency domain data not found. Exiting.") exit() + if __name__ == "__main__": main() diff --git a/src/EE/fourier/main.py b/src/EE/fourier/main.py index d94aa6f..aaacb88 100644 --- a/src/EE/fourier/main.py +++ b/src/EE/fourier/main.py @@ -1,5 +1,5 @@ -from PIL import Image import numpy as np +from PIL import Image def get_watermark_text(): @@ -13,14 +13,16 @@ def load_image(): except FileNotFoundError: print("Image not found. Please check the path and try again.") return None + + def shift_to_center(frequency_domain): return np.fft.fftshift(frequency_domain) + def shift_to_corners(frequency_domain): return np.fft.ifftshift(frequency_domain) - def fourier_transform_color(image): image_array = np.array(image) red, green, blue = image_array[:, :, 0], image_array[:, :, 1], image_array[:, :, 2] @@ -30,15 +32,16 @@ def fourier_transform_color(image): return red_freq, green_freq, blue_freq - def embed_watermark_to_color_channel(magnitude, phase, watermark_array): # Embed watermark into magnitude - magnitude[0:1, 0:watermark_array.shape[1]] = watermark_array + magnitude[0:1, 0 : watermark_array.shape[1]] = watermark_array # Print debug information # print("Debug: Portion of magnitude where watermark is embedded:") # print(magnitude[0:1, 0:watermark_array.shape[1]]) - print(f"Debug: Portion of magnitude where watermark is embedded:\n{magnitude[0:1, 0:watermark_array.shape[1]]}") + print( + f"Debug: Portion of magnitude where watermark is embedded:\n{magnitude[0:1, 0:watermark_array.shape[1]]}" + ) frequency_domain_watermarked = magnitude * np.exp(1j * phase) return frequency_domain_watermarked @@ -50,7 +53,7 @@ def inverse_fourier_transform_color(red_freq, green_freq, blue_freq): blue = np.fft.ifft2(shift_to_corners(blue_freq)) color_image_array = np.stack([np.real(red), np.real(green), np.real(blue)], axis=2) color_image_array = np.uint8(color_image_array) - return Image.fromarray(color_image_array, 'RGB') + return Image.fromarray(color_image_array, "RGB") def save_image(image, watermark_text): @@ -61,6 +64,7 @@ def save_image(image, watermark_text): except Exception as e: print(f"Failed to save image: {e}") + def main(): watermark_text = get_watermark_text() image = load_image() @@ -71,7 +75,6 @@ def main(): red_freq, green_freq, blue_freq = fourier_transform_color(image) print("Successfully loaded image to frequency domain.") - watermark_array = np.array([[ord(char) for char in watermark_text]]) # Separate magnitude and phase for each color channel @@ -80,14 +83,22 @@ def main(): blue_magnitude, blue_phase = np.abs(blue_freq), np.angle(blue_freq) # Embed the watermark and get the watermarked frequency domain - red_freq_watermarked = embed_watermark_to_color_channel(red_magnitude, red_phase, watermark_array) - green_freq_watermarked = embed_watermark_to_color_channel(green_magnitude, green_phase, watermark_array) - blue_freq_watermarked = embed_watermark_to_color_channel(blue_magnitude, blue_phase, watermark_array) + red_freq_watermarked = embed_watermark_to_color_channel( + red_magnitude, red_phase, watermark_array + ) + green_freq_watermarked = embed_watermark_to_color_channel( + green_magnitude, green_phase, watermark_array + ) + blue_freq_watermarked = embed_watermark_to_color_channel( + blue_magnitude, blue_phase, watermark_array + ) # Save the frequency domain data to disk np.save(f"red_freq_watermarked_{watermark_text}.npy", red_freq_watermarked) print("Successfully embedded watermark into frequency domain.") - print(f"Debug: Red frequency domain after watermark: {np.abs(red_freq_watermarked)[0, 0:10]}") + print( + f"Debug: Red frequency domain after watermark: {np.abs(red_freq_watermarked)[0, 0:10]}" + ) watermarked_image = inverse_fourier_transform_color( red_freq_watermarked, green_freq_watermarked, blue_freq_watermarked @@ -102,5 +113,6 @@ def main(): else: print("Failed to load image. Exiting.") + if __name__ == "__main__": - main() \ No newline at end of file + main() From 82793b2c921900b3c1c4cc3452737be3f718db65 Mon Sep 17 00:00:00 2001 From: i-am-unknown-81514525 <74453352+i-am-unknown-81514525@users.noreply.github.com> Date: Sun, 10 Sep 2023 00:38:26 +0100 Subject: [PATCH 5/9] Add Library system (50% done) --- src/EE/fourier/main.py | 78 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 14 deletions(-) diff --git a/src/EE/fourier/main.py b/src/EE/fourier/main.py index aaacb88..7ca7d41 100644 --- a/src/EE/fourier/main.py +++ b/src/EE/fourier/main.py @@ -1,12 +1,23 @@ +import asyncio +import random + import numpy as np +import PIL.Image from PIL import Image +try: + from .. import utils +except ImportError: + from EE import utils + def get_watermark_text(): + """Basic CLI prompt to enter text, Deprecated.""" return input("Enter the watermark text: ") def load_image(): + """Load Image object, Deprecated.""" image_path = input("Enter the path to the image file: ") try: return Image.open(image_path) @@ -15,15 +26,15 @@ def load_image(): return None -def shift_to_center(frequency_domain): +def shift_to_center(frequency_domain): # noqa: D103 return np.fft.fftshift(frequency_domain) -def shift_to_corners(frequency_domain): +def shift_to_corners(frequency_domain): # noqa: D103 return np.fft.ifftshift(frequency_domain) -def fourier_transform_color(image): +def fourier_transform_color(image): # noqa: D103 image_array = np.array(image) red, green, blue = image_array[:, :, 0], image_array[:, :, 1], image_array[:, :, 2] red_freq = shift_to_center(np.fft.fft2(red)) @@ -33,8 +44,9 @@ def fourier_transform_color(image): def embed_watermark_to_color_channel(magnitude, phase, watermark_array): + """Encode watermark by colour channel.""" # Embed watermark into magnitude - magnitude[0:1, 0 : watermark_array.shape[1]] = watermark_array + magnitude[0:1, 0: watermark_array.shape[1]] = watermark_array # Print debug information # print("Debug: Portion of magnitude where watermark is embedded:") @@ -47,7 +59,7 @@ def embed_watermark_to_color_channel(magnitude, phase, watermark_array): return frequency_domain_watermarked -def inverse_fourier_transform_color(red_freq, green_freq, blue_freq): +def inverse_fourier_transform_color(red_freq, green_freq, blue_freq): # noqa: D103 red = np.fft.ifft2(shift_to_corners(red_freq)) green = np.fft.ifft2(shift_to_corners(green_freq)) blue = np.fft.ifft2(shift_to_corners(blue_freq)) @@ -56,18 +68,22 @@ def inverse_fourier_transform_color(red_freq, green_freq, blue_freq): return Image.fromarray(color_image_array, "RGB") -def save_image(image, watermark_text): +def save_image(image, save_path): + """Save PIL.Image.Image by path.""" try: - image.save(f"watermaked_{watermark_text}.tiff") - print(f"Watermarked image saved as 'watermaked_{watermark_text}.tiff'") + image.save(save_path) + print(f"Watermarked image saved as '{save_path}'") except Exception as e: print(f"Failed to save image: {e}") -def main(): - watermark_text = get_watermark_text() - image = load_image() +def encode_fourier(watermark_text, img_path, save_path): + """Code to dncode watermark to the image.""" + if not isinstance(img_path, PIL.Image.Image): + image = Image.open(img_path) + else: + image = img_path if image: print(f"Successfully loaded image. Watermark text is: {watermark_text}") @@ -105,14 +121,48 @@ def main(): ) print("Successfully transformed image back to spatial domain.") - save_image(watermarked_image, watermark_text) + save_image(watermarked_image, save_path) - loaded_image = Image.open(f"watermaked_{watermark_text}.tiff") + loaded_image = Image.open(save_path) loaded_red_freq, _, _ = fourier_transform_color(loaded_image) print(f"Debug: Loaded red frequency domain: {np.abs(loaded_red_freq)[0, 0:10]}") else: print("Failed to load image. Exiting.") +class Fourier(utils.LibraryBase): + """Class to run Fourier Library""" + + def __init__(self): + super().__init__() + self.enc_input = [ + {"field": "Watermark content", 'type': 'text_large', 'id': 'msg'}, + {"field": "Image", 'type': 'image_button', 'id': 'img'}] + self.dec_input = [ + {"field": "Image", 'type': 'image_button', 'id': 'img'}, + {"field": "Length of watermark content", 'type': 'text_small', 'id': 'len'}] + self.enc_output = [{"type": "image_button", "id": "img_down"}, {'type': 'int', 'id': 'len'}] + self.dec_output = [{"type": "msg", "id": "msg"}] + + async def routine(self, func_mode: utils.mode, data_input: dict): + """Routine of running Fourier watermark.""" + # If both code have something in common, the proprtion of those code is here + if func_mode == utils.MODE_ENCRYPTION: + data = data_input['msg'] + pathname_gen = ''.join(random.choices('0123456789abcdef', k=32)) + '.tiff' + encode_fourier(data, data_input['img'], pathname_gen) + return {'img_down': pathname_gen, 'len': len(data)} + + if func_mode == utils.MODE_DECRYPTION: # {'len':'4', 'img;} -> {'msg':'test'} + # data = fourier_transform_decoder.main(data_input['msg'],data_input["img"] ) + # return {'img_down': name} + # disconnected code + pass + + if __name__ == "__main__": - main() + lib = Fourier() + out_data = asyncio.run(lib.routine(utils.MODE_ENCRYPTION, {'msg': 'test', 'img': PIL.Image.open('img.png')})) + out_data_2 = asyncio.run( + lib.routine(utils.MODE_DECRYPTION, {'img': PIL.Image.open(out_data['img_down']), 'len': str(out_data['len'])})) + print(out_data_2) From 635769de0a55d08d6b9c49d7ef7fc0044e1a31d5 Mon Sep 17 00:00:00 2001 From: TheKekening Date: Sun, 10 Sep 2023 15:21:38 +0100 Subject: [PATCH 6/9] Modified Watermark Encoder and Decoder (Other files are depreciated) --- src/EE/fourier/watermark_decoder.py | 36 +++++++++++++++++++++++++++++ src/EE/fourier/watermark_encoder.py | 29 +++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 src/EE/fourier/watermark_decoder.py create mode 100644 src/EE/fourier/watermark_encoder.py diff --git a/src/EE/fourier/watermark_decoder.py b/src/EE/fourier/watermark_decoder.py new file mode 100644 index 0000000..4eea9ab --- /dev/null +++ b/src/EE/fourier/watermark_decoder.py @@ -0,0 +1,36 @@ +import cv2 +import numpy as np + +def extract_watermark(watermarked_image, original_image, watermark_length): + watermarked_image = np.array(watermarked_image) + original_image = np.array(original_image) + if watermarked_image is None or original_image is None: + print("Could not open one of the images. Check the paths.") + return None + + extracted_data = [] + for x in range(watermarked_image.shape[0]): + for y in range(watermarked_image.shape[1]): + pixel = list(watermarked_image[x, y]) + original_pixel = list(original_image[x, y]) + for n in range(3): + extracted_data.append(bin(pixel[n])[-1]) + + # Validate and convert the binary string to characters + extracted_watermark = ''.join( + [chr(int(''.join([str(bit) for bit in extracted_data[i:i + 8]]), 2)) + for i in range(0, watermark_length * 8, 8) if ''.join(extracted_data[i:i + 8]).isdigit()] + ) + + return extracted_watermark + +# def main(): +# watermarked_image_path = input("Enter the path to the watermarked image file: ") +# original_image_path = input("Enter the path to the original image file: ") +# watermark_length = int(input("Enter the length of the watermark text: ")) + +# extracted_watermark = extract_watermark(watermarked_image_path, original_image_path, watermark_length) +# print(f"Extracted watermark is: {extracted_watermark}") + +# if __name__ == "__main__": +# main() diff --git a/src/EE/fourier/watermark_encoder.py b/src/EE/fourier/watermark_encoder.py new file mode 100644 index 0000000..998f8fb --- /dev/null +++ b/src/EE/fourier/watermark_encoder.py @@ -0,0 +1,29 @@ + +import cv2 +import numpy as np +from PIL import Image + +def embed_watermark(image_in, watermark_text): + imgarr = np.array(image_in) + watermark_data = ''.join(format(ord(char), '08b') for char in watermark_text) + i = 0 + for x in range(imgarr.shape[0]): + for y in range(imgarr.shape[1]): + pixel = list(imgarr[x, y]) + for n in range(3): + if i < len(watermark_data): + pixel[n] = int(format(pixel[n], '08b')[:-1] + watermark_data[i], 2) + i += 1 + imgarr[x, y] = tuple(pixel) + # cv2.imwrite("watermarked_image.png", image) + return Image.fromarray(imgarr) + + # print("Watermark embedded and saved to watermarked_image.png.") + +def main(image, watermark_text): + out_image = embed_watermark(image, watermark_text) + out_image = Image.fromarray(out_image) + return out_image + +# if __name__ == "__main__": + From ecebe5c465e1a6a222ccc17afeb0f7daf7e12f41 Mon Sep 17 00:00:00 2001 From: TheKekening Date: Sun, 10 Sep 2023 15:23:46 +0100 Subject: [PATCH 7/9] modified to be slightly more pep8 compliant --- src/EE/fourier/watermark_decoder.py | 3 +-- src/EE/fourier/watermark_encoder.py | 12 +++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/EE/fourier/watermark_decoder.py b/src/EE/fourier/watermark_decoder.py index 4eea9ab..b93e504 100644 --- a/src/EE/fourier/watermark_decoder.py +++ b/src/EE/fourier/watermark_decoder.py @@ -1,6 +1,6 @@ -import cv2 import numpy as np + def extract_watermark(watermarked_image, original_image, watermark_length): watermarked_image = np.array(watermarked_image) original_image = np.array(original_image) @@ -12,7 +12,6 @@ def extract_watermark(watermarked_image, original_image, watermark_length): for x in range(watermarked_image.shape[0]): for y in range(watermarked_image.shape[1]): pixel = list(watermarked_image[x, y]) - original_pixel = list(original_image[x, y]) for n in range(3): extracted_data.append(bin(pixel[n])[-1]) diff --git a/src/EE/fourier/watermark_encoder.py b/src/EE/fourier/watermark_encoder.py index 998f8fb..782142b 100644 --- a/src/EE/fourier/watermark_encoder.py +++ b/src/EE/fourier/watermark_encoder.py @@ -1,29 +1,31 @@ -import cv2 import numpy as np from PIL import Image + def embed_watermark(image_in, watermark_text): imgarr = np.array(image_in) - watermark_data = ''.join(format(ord(char), '08b') for char in watermark_text) + watermark_data = ''.join(format(ord(char), '08b') + for char in watermark_text) i = 0 for x in range(imgarr.shape[0]): for y in range(imgarr.shape[1]): pixel = list(imgarr[x, y]) for n in range(3): if i < len(watermark_data): - pixel[n] = int(format(pixel[n], '08b')[:-1] + watermark_data[i], 2) + pixel[n] = int(format(pixel[n], '08b')[ + :-1] + watermark_data[i], 2) i += 1 imgarr[x, y] = tuple(pixel) # cv2.imwrite("watermarked_image.png", image) return Image.fromarray(imgarr) - + # print("Watermark embedded and saved to watermarked_image.png.") + def main(image, watermark_text): out_image = embed_watermark(image, watermark_text) out_image = Image.fromarray(out_image) return out_image # if __name__ == "__main__": - From 30b437a4d4a695266ef23dc7f5512259366de582 Mon Sep 17 00:00:00 2001 From: i-am-unknown-81514525 <74453352+i-am-unknown-81514525@users.noreply.github.com> Date: Sun, 10 Sep 2023 17:39:33 +0100 Subject: [PATCH 8/9] Make some change to watermark system --- src/EE/fourier/watermark_decoder.py | 16 ++++++++-------- src/EE/fourier/watermark_encoder.py | 13 ++++++++++--- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/EE/fourier/watermark_decoder.py b/src/EE/fourier/watermark_decoder.py index b93e504..db3eb04 100644 --- a/src/EE/fourier/watermark_decoder.py +++ b/src/EE/fourier/watermark_decoder.py @@ -23,13 +23,13 @@ def extract_watermark(watermarked_image, original_image, watermark_length): return extracted_watermark -# def main(): -# watermarked_image_path = input("Enter the path to the watermarked image file: ") -# original_image_path = input("Enter the path to the original image file: ") -# watermark_length = int(input("Enter the length of the watermark text: ")) +def main(): + watermarked_image_path = input("Enter the path to the watermarked image file: ") + original_image_path = input("Enter the path to the original image file: ") + watermark_length = int(input("Enter the length of the watermark text: ")) -# extracted_watermark = extract_watermark(watermarked_image_path, original_image_path, watermark_length) -# print(f"Extracted watermark is: {extracted_watermark}") + extracted_watermark = extract_watermark(watermarked_image_path, original_image_path, watermark_length) + print(f"Extracted watermark is: {extracted_watermark}") -# if __name__ == "__main__": -# main() +if __name__ == "__main__": + main() diff --git a/src/EE/fourier/watermark_encoder.py b/src/EE/fourier/watermark_encoder.py index 782142b..523c3a1 100644 --- a/src/EE/fourier/watermark_encoder.py +++ b/src/EE/fourier/watermark_encoder.py @@ -1,4 +1,4 @@ - +import PIL.Image import numpy as np from PIL import Image @@ -25,7 +25,14 @@ def embed_watermark(image_in, watermark_text): def main(image, watermark_text): out_image = embed_watermark(image, watermark_text) - out_image = Image.fromarray(out_image) return out_image -# if __name__ == "__main__": +if __name__ == "__main__": + image_path = input('Image path for the original image: ') + text = input('Input text that you want to watermark: ') + image_obj = main(PIL.Image.open(image_path), text) + out_path = input('The output path for the image:') + image_obj.save(out_path) + print('For reminder, You will require the original image, the watermarked image '+\ + 'and the length of the watermarked text to get the text you watermarked.') + print(f"Your length of watermark is:{len(text)}") From 34061b6fc72b93d090eae0387a7549223551a30b Mon Sep 17 00:00:00 2001 From: TheKekening Date: Thu, 14 Sep 2023 09:08:53 +0100 Subject: [PATCH 9/9] Create ReadME --- src/EE/fourier/Image_Watermarking_README.md | 42 +++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/EE/fourier/Image_Watermarking_README.md diff --git a/src/EE/fourier/Image_Watermarking_README.md b/src/EE/fourier/Image_Watermarking_README.md new file mode 100644 index 0000000..fa63ac4 --- /dev/null +++ b/src/EE/fourier/Image_Watermarking_README.md @@ -0,0 +1,42 @@ +# Image Watermarking using Fourier Transform + +## Encoder + +### Overview +The encoder program takes an image and a watermark text from the user. It then performs the following steps: +1. Converts the image to the frequency domain using Fourier Transform for each color channel (red, green, blue). +2. Embeds the watermark into the magnitude of the frequency domain. +3. Transforms the image back to the spatial domain and saves it. + +### How to Use +1. Run the program. +2. Enter the watermark text when prompted. +3. Enter the path to the image file you want to watermark. + +### Code Explanation +- `get_watermark_text()`: Gets watermark text from the user. +- `load_image()`: Loads an image from a file path given by the user. +- `fourier_transform_color()`: Performs Fourier Transform on each color channel. +- `embed_watermark_to_color_channel()`: Embeds the watermark into the magnitude of the frequency domain. +- `inverse_fourier_transform_color()`: Performs inverse Fourier Transform to get the image back to the spatial domain. +- `save_image()`: Saves the watermarked image. + +--- + +## Decoder + +### Overview +The decoder program extracts the watermark text from a watermarked image. It uses the frequency domain data saved during the encoding process. + +### How to Use +1. Run the program. +2. Enter the watermark text that was used for encoding when prompted. +3. Enter the path to the watermarked image file. + +### Code Explanation +- `load_image()`: Loads the watermarked image. +- `fourier_transform_color()`: Performs Fourier Transform on each color channel of the image. +- `extract_watermark()`: Extracts the watermark from the magnitude of the frequency domain. +- `main()`: Orchestrates the watermark extraction process. + +The decoder does not read the watermark directly from the watermarked image. Instead, it loads the frequency domain data from a `.npy` file saved during the encoding process.