import numpy as np from PIL import Image import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import pandas as pd import os from pathlib import Path # Path settings original_image_path = r"G:\Users\Chipistil\Desktop\High-throughput-T2NP-Memristor-based-Dual-clock-edge-sampling-TRNG\AHU Black Swan.png" encrypted_image_path = r"G:\Users\Chipistil\Desktop\High-throughput-T2NP-Memristor-based-Dual-clock-edge-sampling-TRNG\AHU Black Swan_encrypted_image.png" output_dir = r"G:\Users\Chipistil\Desktop\High-throughput-T2NP-Memristor-based-Dual-clock-edge-sampling-TRNG\Dual-Image Encryption Verification\01_Statistical Analysis\03_3D_pixel_distribution" plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False def generate_3d_pixel_distribution(image_path, output_image_path, output_data_path, sample_size=10000): if not Path(image_path).exists(): print(f"Error: Input file {image_path} does not exist") return False try: img = Image.open(image_path) img_array = np.array(img) height, width, channels = img_array.shape if channels != 3: print(f"Error: Image is not in RGB format, number of channels: {channels}") return False pixels = img_array.reshape(-1, 3) if pixels.shape[0] > sample_size: indices = np.random.choice(pixels.shape[0], sample_size, replace=False) sampled_pixels = pixels[indices] else: sampled_pixels = pixels fig = plt.figure(figsize=(12, 10)) ax = fig.add_subplot(111, projection='3d') ax.scatter( sampled_pixels[:, 0], sampled_pixels[:, 1], sampled_pixels[:, 2], c=sampled_pixels / 255.0, alpha=0.5, s=1 ) ax.set_xlabel('Red Channel (R)', fontsize=14) ax.set_ylabel('Green Channel (G)', fontsize=14) ax.set_zlabel('Blue Channel (B)', fontsize=14) image_name = os.path.basename(image_path) ax.set_title(f'{image_name} 3D Pixel Space Distribution', fontsize=16) ax.set_xlim(0, 255) ax.set_ylim(0, 255) ax.set_zlim(0, 255) output_dir_path = os.path.dirname(output_image_path) if output_dir_path and not os.path.exists(output_dir_path): os.makedirs(output_dir_path) plt.tight_layout() plt.savefig(output_image_path, dpi=300, bbox_inches='tight') plt.close() print(f"3D pixel distribution map saved to: {output_image_path}") pixel_df = pd.DataFrame(pixels, columns=['R', 'G', 'B']) data_output_dir = os.path.dirname(output_data_path) if data_output_dir and not os.path.exists(data_output_dir): os.makedirs(data_output_dir) pixel_df.to_excel(output_data_path, index=False) print(f"Pixel data saved to: {output_data_path}") return True except Exception as e: print(f"Error processing image: {e}") return False def generate_single_channel_histogram(image_path, channel, output_image_path, output_data_path): if not Path(image_path).exists(): print(f"Error: Input file {image_path} does not exist") return False try: img = Image.open(image_path) img_array = np.array(img) height, width, channels = img_array.shape if channels != 3: print(f"Error: Image is not in RGB format, number of channels: {channels}") return False channel_data = img_array[:, :, channel] x = np.arange(width) y = np.arange(height) x, y = np.meshgrid(x, y) fig = plt.figure(figsize=(12, 10)) ax = fig.add_subplot(111, projection='3d') channel_names = ['R', 'G', 'B'] colormaps = ['Reds', 'Greens', 'Blues'] surf = ax.plot_surface(x, y, channel_data, cmap=colormaps[channel], alpha=0.8) ax.set_xlabel('X-axis (Pixel Column)', fontsize=14) ax.set_ylabel('Y-axis (Pixel Row)', fontsize=14) ax.set_zlabel(f'{channel_names[channel]} Channel Value (0-255)', fontsize=14) image_name = os.path.basename(image_path) ax.set_title(f'{image_name} {channel_names[channel]} Channel 3D Pixel Distribution', fontsize=16) ax.set_xlim(0, width) ax.set_ylim(0, height) ax.set_zlim(0, 255) fig.colorbar(surf, ax=ax, shrink=0.5, aspect=5) output_dir_path = os.path.dirname(output_image_path) if output_dir_path and not os.path.exists(output_dir_path): os.makedirs(output_dir_path) plt.tight_layout() plt.savefig(output_image_path, dpi=300, bbox_inches='tight') plt.close() print(f"{channel_names[channel]} channel pixel distribution map saved to: {output_image_path}") try: max_pixels = 10000 if channel_data.size > max_pixels: flat_data = channel_data.flatten() indices = np.random.choice(flat_data.shape[0], max_pixels, replace=False) sampled_data = flat_data[indices] coords = np.array(np.unravel_index(indices, channel_data.shape)).T channel_df = pd.DataFrame({ 'X Coordinate': coords[:, 1], 'Y Coordinate': coords[:, 0], channel_names[channel]: sampled_data }) else: x_coords, y_coords = np.meshgrid(np.arange(width), np.arange(height)) channel_df = pd.DataFrame({ 'X Coordinate': x_coords.flatten(), 'Y Coordinate': y_coords.flatten(), channel_names[channel]: channel_data.flatten() }) data_output_dir = os.path.dirname(output_data_path) if data_output_dir and not os.path.exists(data_output_dir): os.makedirs(data_output_dir) channel_df.to_excel(output_data_path, index=False) print(f"{channel_names[channel]} channel pixel data saved to: {output_data_path}") except PermissionError: print(f"⚠️ Warning: Cannot save {channel_names[channel]} channel pixel data, permission denied") except Exception as e: print(f"⚠️ Warning: Error saving {channel_names[channel]} channel pixel data: {e}") return True except Exception as e: print(f"Error processing channel {channel}: {e}") return False def main(): print("Starting image processing...") print(f"Original image path: {original_image_path}") print(f"Encrypted image path: {encrypted_image_path}") print(f"Output directory: {output_dir}") if not os.path.exists(output_dir): print(f"Output directory does not exist, creating directory: {output_dir}") os.makedirs(output_dir) print("\nProcessing original image single channel 3D distribution...") if os.path.exists(original_image_path): print(f"Reading image: {os.path.basename(original_image_path)}") print(f"Output directory: {output_dir}") for channel in range(3): channel_names = ['R', 'G', 'B'] channel_output_image = os.path.join(output_dir, f"original_{channel_names[channel]}_channel_3d_distribution.png") channel_output_data = os.path.join(output_dir, f"original_{channel_names[channel]}_channel_data.xlsx") print(f" Processing {channel_names[channel]} channel...") success = generate_single_channel_histogram(original_image_path, channel, channel_output_image, channel_output_data) if success: print(f" ✅ Original image {channel_names[channel]} channel processing completed") else: print(f" ❌ Original image {channel_names[channel]} channel processing failed") else: print(f"❌ Error: Original image {original_image_path} does not exist") print("Please check if the original image path is correct") print("\nProcessing encrypted image single channel 3D distribution...") if os.path.exists(encrypted_image_path): print(f"Reading image: {os.path.basename(encrypted_image_path)}") print(f"Output directory: {output_dir}") for channel in range(3): channel_names = ['R', 'G', 'B'] channel_output_image = os.path.join(output_dir, f"encrypted_{channel_names[channel]}_channel_3d_distribution.png") channel_output_data = os.path.join(output_dir, f"encrypted_{channel_names[channel]}_channel_data.xlsx") print(f" Processing {channel_names[channel]} channel...") success = generate_single_channel_histogram(encrypted_image_path, channel, channel_output_image, channel_output_data) if success: print(f" ✅ Encrypted image {channel_names[channel]} channel processing completed") else: print(f" ❌ Encrypted image {channel_names[channel]} channel processing failed") else: print(f"❌ Error: Encrypted image {encrypted_image_path} does not exist") print("Please check if the encrypted image path is correct") print("\nProcessing completed!") if __name__ == "__main__": main()