Files
2025-11-22 11:18:28 +08:00

207 lines
6.1 KiB
Python

import torch
import cv2
import numpy as np
from PIL import Image
import io
def invert_colors(image):
"""Invert image colors (1.0 - image)."""
return 1.0 - image
def xor_operation(image, key):
"""Apply XOR operation to image pixels with given key."""
# Convert normalized [0,1] image to uint8 [0,255] for bitwise operations
images_uint8 = (image * 255).to(torch.uint8)
# Apply XOR operation for basic encryption/obfuscation
processed_images = images_uint8 ^ key
# Convert back to normalized float32 [0,1]
return processed_images.to(torch.float32) / 255.0
def encrypt_image(image, operation):
"""Apply encryption/obfuscation operation to image."""
if operation == "invert":
processed_image = invert_colors(image)
elif operation == "xor-16":
processed_image = xor_operation(image, 16)
elif operation == "xor-32":
processed_image = xor_operation(image, 32)
elif operation == "xor-64":
processed_image = xor_operation(image, 64)
elif operation == "xor-128":
processed_image = xor_operation(image, 128)
else:
processed_image = image
return processed_image
def _single_image_to_bytes(image, format="image/png"):
"""Convert single image (numpy array) to bytes."""
# Convert to uint8
if image.dtype != np.uint8:
image = np.clip(image * 255, 0, 255).astype(np.uint8)
# Convert to PIL image
image_pil = Image.fromarray(image)
# Save to memory as bytes
buffer = io.BytesIO()
image_pil.save(buffer, format=format.split("/")[-1])
buffer.seek(0)
return buffer.read()
def image_to_bytes(image, format="image/png") -> bytes:
"""Convert image (tensor or numpy) to bytes."""
# Handle tensor input
if isinstance(image, torch.Tensor):
image = image.detach().cpu().numpy()
# Remove batch dimension
if image.ndim == 4:
image = image[0]
return _single_image_to_bytes(image, format)
def bytes_to_image(image_bytes):
"""Convert bytes to image tensor with alpha mask."""
nparr = np.frombuffer(image_bytes, np.uint8)
result = cv2.imdecode(nparr, cv2.IMREAD_UNCHANGED)
channels = cv2.split(result)
# Handle alpha channel if present
if len(channels) > 3:
mask = channels[3].astype(np.float32) / 255.0 # Normalize alpha to [0,1]
mask = torch.from_numpy(mask)
else:
# Create solid white mask for images without alpha
mask = torch.ones(channels[0].shape, dtype=torch.float32, device="cpu")
result = _convert_color(result)
result = result.astype(np.float32) / 255.0 # Normalize RGB to [0,1]
new_images = torch.from_numpy(result)[None,] # Add batch dimension
return new_images, mask
def _convert_color(image):
"""Convert BGR/BGRA image to RGB format."""
# OpenCV loads images as BGR, convert to RGB for consistency
if len(image.shape) > 2 and image.shape[2] >= 4:
return cv2.cvtColor(image, cv2.COLOR_BGRA2RGB) # BGRA to RGB (drop alpha)
return cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # BGR to RGB
def image_batch_to_bytes_list(images, format="image/png"):
"""Convert batch of images to list of bytes."""
if isinstance(images, torch.Tensor):
images = images.detach().cpu().numpy()
bytes_list = []
# Handle batch dimension
if images.ndim == 4:
for i in range(images.shape[0]):
image = images[i]
image_bytes = _single_image_to_bytes(image, format)
bytes_list.append(image_bytes)
elif images.ndim == 3:
# Single image
image_bytes = _single_image_to_bytes(images, format)
bytes_list.append(image_bytes)
return bytes_list
def bytes_list_to_image_batch(bytes_list):
"""Convert list of bytes to batch of images with masks."""
images = []
masks = []
for image_bytes in bytes_list:
image, mask = bytes_to_image(image_bytes)
images.append(image)
masks.append(mask)
# Concatenate all images into a batch
if len(images) > 0:
images_batch = torch.cat(images, dim=0)
masks_batch = torch.stack(masks, dim=0)
return images_batch, masks_batch
else:
# Return empty tensors if no images
return torch.empty(0), torch.empty(0)
def tensor_to_bytes(tensor):
"""Convert raw tensor to bytes (serialized tensor data)."""
# Handle tensor input
if isinstance(tensor, torch.Tensor):
tensor = tensor.detach().cpu()
else:
tensor = torch.from_numpy(tensor)
# Remove batch dimension if present
if tensor.ndim == 4 and tensor.shape[0] == 1:
tensor = tensor[0]
# Serialize tensor to bytes
buffer = io.BytesIO()
torch.save(tensor, buffer)
buffer.seek(0)
return buffer.read()
def bytes_to_tensor(tensor_bytes):
"""Convert bytes back to tensor (deserialize tensor data)."""
buffer = io.BytesIO(tensor_bytes)
# Load tensor
tensor = torch.load(buffer)
# Add batch dimension if not present
if tensor.ndim == 3:
tensor = tensor.unsqueeze(0)
return tensor
def tensor_batch_to_bytes_list(tensors):
"""Convert batch of tensors to list of bytes."""
if isinstance(tensors, torch.Tensor):
tensors = tensors.detach().cpu()
else:
tensors = torch.from_numpy(tensors)
bytes_list = []
# Handle batch dimension
if tensors.ndim == 4:
for i in range(tensors.shape[0]):
tensor = tensors[i]
tensor_bytes = tensor_to_bytes(tensor)
bytes_list.append(tensor_bytes)
elif tensors.ndim == 3:
# Single tensor
tensor_bytes = tensor_to_bytes(tensors)
bytes_list.append(tensor_bytes)
return bytes_list
def bytes_list_to_tensor_batch(bytes_list):
"""Convert list of bytes to batch of tensors."""
tensors = []
for tensor_bytes in bytes_list:
tensor = bytes_to_tensor(tensor_bytes)
tensors.append(tensor)
# Concatenate all tensors into a batch
if len(tensors) > 0:
tensors_batch = torch.cat(tensors, dim=0)
return tensors_batch
else:
# Return empty tensor if no tensors
return torch.empty(0)