From 7e9e2fca09cee498f5d871e6e380a277563b3778 Mon Sep 17 00:00:00 2001 From: Sajeer Date: Sat, 28 Sep 2024 08:48:02 +0530 Subject: [PATCH 1/3] Multi model integration --- ai_model/output/mitm_attack.py | 109 +++++++++++++++++++++++++++++++++ ai_model/output/res.py | 2 +- ai_model/output/run.py | 1 - 3 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 ai_model/output/mitm_attack.py diff --git a/ai_model/output/mitm_attack.py b/ai_model/output/mitm_attack.py new file mode 100644 index 0000000..be1df69 --- /dev/null +++ b/ai_model/output/mitm_attack.py @@ -0,0 +1,109 @@ +import os +import numpy as np +from PIL import Image +import torch +from torchvision import transforms +import torchvision.models as models +from art.attacks.evasion import MomentumIterativeMethod +from art.estimators.classification import PyTorchClassifier +import torch.nn as nn + +from res import evaluate_image + + +def denormalize(tensor, mean, std): + mean = torch.tensor(mean).view(1, -1, 1, 1).to(tensor.device) + std = torch.tensor(std).view(1, -1, 1, 1).to(tensor.device) + tensor = tensor * std + mean + return tensor + +def protect_image_mitm(image_path, output_folder, target_class_idx=1, level_count=5, current_count=0): + try: + org_id, org_prob = evaluate_image(image_path) + # Load the image without resizing or cropping to retain aspect ratio + image = Image.open(image_path).convert('RGB') + # Preprocess the image without resizing + preprocess = transforms.Compose([ + transforms.ToTensor(), + transforms.Normalize( + mean=[0.485, 0.456, 0.406], # ResNet50 mean + std=[0.229, 0.224, 0.225] # ResNet50 std + ), + ]) + input_tensor = preprocess(image) + input_batch = input_tensor.unsqueeze(0) # Add batch dimension + + # Move input to device + device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + input_batch = input_batch.to(device) + + # Get input shape (channels, height, width) + _, channels, height, width = input_batch.shape + + # Load pre-trained ResNet50 model + model_pytorch = models.resnet50(pretrained=True) + model_pytorch.eval() + model_pytorch = model_pytorch.to(device) + + # Define loss function + loss_fn = nn.CrossEntropyLoss() + + # Create PyTorchClassifier with variable input shape + classifier = PyTorchClassifier( + model=model_pytorch, + loss=loss_fn, + input_shape=(channels, height, width), + nb_classes=1000, + preprocessing=(0, 1), + clip_values=(0, 1) + ) + + # Create target label (as numpy array) + target_label = np.array([target_class_idx]) + + # Create the Momentum Iterative Method attack + attack = MomentumIterativeMethod( + estimator=classifier, + eps=0.15, # Total perturbation (adjust as needed) + eps_step=0.01, # Step size per iteration + max_iter=200, # Number of iterations + targeted=True + ) + + # Apply adversarial perturbation + adversarial_image = attack.generate(x=input_batch.cpu().numpy(), y=target_label) + + + # Convert adversarial image back to tensor + adversarial_image_tensor = torch.from_numpy(adversarial_image[0]).to(device) + + # Denormalize the image + mean = [0.485, 0.456, 0.406] + std = [0.229, 0.224, 0.225] + adversarial_image_tensor = denormalize(adversarial_image_tensor.unsqueeze(0), mean, std) + adversarial_image_tensor = torch.clamp(adversarial_image_tensor, 0, 1) + adversarial_image_tensor = adversarial_image_tensor.squeeze(0) + + # Move to CPU and convert to PIL Image + adversarial_image_tensor = adversarial_image_tensor.cpu() + adversarial_pil = transforms.ToPILImage()(adversarial_image_tensor) + + # Save the adversarial image + # filename = os.path.basename(image_path) + # output_path = os.path.join(output_folder, filename) + adversarial_pil.save(output_folder) + current_id, current_prob = evaluate_image(output_folder) + if current_id != org_id or current_count > level_count: + print("The image is protected") + print(current_id) + print(current_prob) + return current_id, current_prob + else: + print("Current Probability: ", current_id) + print("Current Probability: ", current_prob) + print("Original Probability: ", org_prob) + current_count += 1 + return protect_image_mitm(image_path, output_folder, level_count, current_count) + except Exception as e: + print(f"Error processing image {image_path}: {e}") + return None diff --git a/ai_model/output/res.py b/ai_model/output/res.py index 9a6ad4c..fc72f89 100644 --- a/ai_model/output/res.py +++ b/ai_model/output/res.py @@ -47,4 +47,4 @@ def evaluate_image(filename): # Show top categories per image topx_prob, topx_catid = torch.topk(probabilities, 1) for i in range(topx_prob.size(0)): - return categories[topx_catid[i]], topx_prob[i].item() \ No newline at end of file + return categories[topx_catid[i]], topx_prob[i].item() diff --git a/ai_model/output/run.py b/ai_model/output/run.py index 186769a..dc7f7bd 100644 --- a/ai_model/output/run.py +++ b/ai_model/output/run.py @@ -2,7 +2,6 @@ import os import json import shutil -from flip_pixel import flip_random_pixels from poison_image import protect_image from res import evaluate_image From 9863b898eb5f099cd5aafc6af05213f6789b3400 Mon Sep 17 00:00:00 2001 From: Sajeer Date: Sat, 28 Sep 2024 08:52:00 +0530 Subject: [PATCH 2/3] Multi model integration --- ai_model/output/flip_pixel.py | 5 +- ai_model/output/mitm_attack.py | 44 ++++++++++-------- ai_model/output/object_detection.py | 17 ++++--- ai_model/output/poison_image.py | 33 ++++++++----- ai_model/output/res.py | 59 ++++++++++++----------- ai_model/output/run.py | 72 +++++++++++++++++++---------- ai_model/output/unet.py | 64 ++++++++++++++----------- 7 files changed, 177 insertions(+), 117 deletions(-) diff --git a/ai_model/output/flip_pixel.py b/ai_model/output/flip_pixel.py index c9670e4..54e1782 100644 --- a/ai_model/output/flip_pixel.py +++ b/ai_model/output/flip_pixel.py @@ -2,10 +2,11 @@ from PIL import Image import numpy as np + def flip_random_pixels(image_path, output_path, flip_percentage=0.001): # Open the image img = Image.open(image_path) - img = img.convert('RGB') # Ensure it's in RGB format + img = img.convert("RGB") # Ensure it's in RGB format # Convert image to numpy array for pixel manipulation img_array = np.array(img) @@ -30,4 +31,4 @@ def flip_random_pixels(image_path, output_path, flip_percentage=0.001): # Save the new image flipped_img.save(output_path) - print(f"Saved flipped image at {output_path}") \ No newline at end of file + print(f"Saved flipped image at {output_path}") diff --git a/ai_model/output/mitm_attack.py b/ai_model/output/mitm_attack.py index be1df69..5fab49a 100644 --- a/ai_model/output/mitm_attack.py +++ b/ai_model/output/mitm_attack.py @@ -17,24 +17,29 @@ def denormalize(tensor, mean, std): tensor = tensor * std + mean return tensor -def protect_image_mitm(image_path, output_folder, target_class_idx=1, level_count=5, current_count=0): + +def protect_image_mitm( + image_path, output_folder, target_class_idx=1, level_count=5, current_count=0 +): try: org_id, org_prob = evaluate_image(image_path) # Load the image without resizing or cropping to retain aspect ratio - image = Image.open(image_path).convert('RGB') + image = Image.open(image_path).convert("RGB") # Preprocess the image without resizing - preprocess = transforms.Compose([ - transforms.ToTensor(), - transforms.Normalize( - mean=[0.485, 0.456, 0.406], # ResNet50 mean - std=[0.229, 0.224, 0.225] # ResNet50 std - ), - ]) + preprocess = transforms.Compose( + [ + transforms.ToTensor(), + transforms.Normalize( + mean=[0.485, 0.456, 0.406], # ResNet50 mean + std=[0.229, 0.224, 0.225], # ResNet50 std + ), + ] + ) input_tensor = preprocess(image) input_batch = input_tensor.unsqueeze(0) # Add batch dimension # Move input to device - device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") input_batch = input_batch.to(device) # Get input shape (channels, height, width) @@ -55,7 +60,7 @@ def protect_image_mitm(image_path, output_folder, target_class_idx=1, level_coun input_shape=(channels, height, width), nb_classes=1000, preprocessing=(0, 1), - clip_values=(0, 1) + clip_values=(0, 1), ) # Create target label (as numpy array) @@ -64,23 +69,24 @@ def protect_image_mitm(image_path, output_folder, target_class_idx=1, level_coun # Create the Momentum Iterative Method attack attack = MomentumIterativeMethod( estimator=classifier, - eps=0.15, # Total perturbation (adjust as needed) - eps_step=0.01, # Step size per iteration - max_iter=200, # Number of iterations - targeted=True + eps=0.15, # Total perturbation (adjust as needed) + eps_step=0.01, # Step size per iteration + max_iter=200, # Number of iterations + targeted=True, ) # Apply adversarial perturbation adversarial_image = attack.generate(x=input_batch.cpu().numpy(), y=target_label) - # Convert adversarial image back to tensor adversarial_image_tensor = torch.from_numpy(adversarial_image[0]).to(device) # Denormalize the image mean = [0.485, 0.456, 0.406] std = [0.229, 0.224, 0.225] - adversarial_image_tensor = denormalize(adversarial_image_tensor.unsqueeze(0), mean, std) + adversarial_image_tensor = denormalize( + adversarial_image_tensor.unsqueeze(0), mean, std + ) adversarial_image_tensor = torch.clamp(adversarial_image_tensor, 0, 1) adversarial_image_tensor = adversarial_image_tensor.squeeze(0) @@ -103,7 +109,9 @@ def protect_image_mitm(image_path, output_folder, target_class_idx=1, level_coun print("Current Probability: ", current_prob) print("Original Probability: ", org_prob) current_count += 1 - return protect_image_mitm(image_path, output_folder, level_count, current_count) + return protect_image_mitm( + image_path, output_folder, level_count, current_count + ) except Exception as e: print(f"Error processing image {image_path}: {e}") return None diff --git a/ai_model/output/object_detection.py b/ai_model/output/object_detection.py index b101531..d9ee230 100644 --- a/ai_model/output/object_detection.py +++ b/ai_model/output/object_detection.py @@ -3,12 +3,18 @@ from PIL import Image import requests import sys + + def detect_object(image_path): image = image_path # you can specify the revision tag if you don't want the timm dependency - processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50", revision="no_timm") - model = DetrForObjectDetection.from_pretrained("facebook/detr-resnet-50", revision="no_timm") + processor = DetrImageProcessor.from_pretrained( + "facebook/detr-resnet-50", revision="no_timm" + ) + model = DetrForObjectDetection.from_pretrained( + "facebook/detr-resnet-50", revision="no_timm" + ) inputs = processor(images=image, return_tensors="pt") outputs = model(**inputs) @@ -16,7 +22,9 @@ def detect_object(image_path): # convert outputs (bounding boxes and class logits) to COCO API # let's only keep detections with score > 0.9 target_sizes = torch.tensor([image.size[::-1]]) - results = processor.post_process_object_detection(outputs, target_sizes=target_sizes, threshold=0.9)[0] + results = processor.post_process_object_detection( + outputs, target_sizes=target_sizes, threshold=0.9 + )[0] if len(results["boxes"]) > 0: first_box = results["boxes"][0].tolist() @@ -24,6 +32,3 @@ def detect_object(image_path): return first_box else: return None - - - \ No newline at end of file diff --git a/ai_model/output/poison_image.py b/ai_model/output/poison_image.py index b9408f7..ea1289c 100644 --- a/ai_model/output/poison_image.py +++ b/ai_model/output/poison_image.py @@ -1,7 +1,13 @@ import os import numpy as np from PIL import Image -from art.attacks.evasion import ProjectedGradientDescent, DeepFool, SaliencyMapMethod, UniversalPerturbation, MomentumIterativeMethod +from art.attacks.evasion import ( + ProjectedGradientDescent, + DeepFool, + SaliencyMapMethod, + UniversalPerturbation, + MomentumIterativeMethod, +) from art.estimators.classification import TensorFlowV2Classifier from res import evaluate_image import tensorflow as tf @@ -10,7 +16,7 @@ def protect_image(image_path, output_folder, level_count=40, current_count=0): # Load and preprocess image org_id, org_prob = evaluate_image(image_path) - image = Image.open(image_path).convert('RGB') + image = Image.open(image_path).convert("RGB") # Resize image to 224x224 to match ResNet50's input size image = image.resize((224, 224)) @@ -22,21 +28,23 @@ def protect_image(image_path, output_folder, level_count=40, current_count=0): image_np = np.expand_dims(image_np, axis=0) # Load pretrained ResNet50 model - model = tf.keras.applications.ResNet50(weights='imagenet', input_shape=(224, 224, 3)) + model = tf.keras.applications.ResNet50( + weights="imagenet", input_shape=(224, 224, 3) + ) # Wrap the model for ART (Adversarial Robustness Toolbox) classifier = TensorFlowV2Classifier( model=model, nb_classes=1000, input_shape=(224, 224, 3), - loss_object=tf.keras.losses.CategoricalCrossentropy() + loss_object=tf.keras.losses.CategoricalCrossentropy(), ) # Create a stronger PGD attack method attack = DeepFool( classifier=classifier, max_iter=1000, # Increased iterations - epsilon=1e-2 # Increased step size for stronger perturbations + epsilon=1e-2, # Increased step size for stronger perturbations ) output_path = perform_attack(attack, output_folder, image_np) @@ -54,12 +62,13 @@ def protect_image(image_path, output_folder, level_count=40, current_count=0): current_count += 1 return protect_image(output_path, output_folder, level_count, current_count) -def perform_attack(attack, output_folder,image_np): - adversarial_image = attack.generate(x=image_np) + +def perform_attack(attack, output_folder, image_np): + adversarial_image = attack.generate(x=image_np) # Postprocess and save image - adversarial_image = np.squeeze(adversarial_image) * 255.0 - adversarial_image = np.clip(adversarial_image, 0, 255).astype(np.uint8) - adversarial_pil = Image.fromarray(adversarial_image) - adversarial_pil.save(output_folder) - return output_folder + adversarial_image = np.squeeze(adversarial_image) * 255.0 + adversarial_image = np.clip(adversarial_image, 0, 255).astype(np.uint8) + adversarial_pil = Image.fromarray(adversarial_image) + adversarial_pil.save(output_folder) + return output_folder diff --git a/ai_model/output/res.py b/ai_model/output/res.py index fc72f89..966e802 100644 --- a/ai_model/output/res.py +++ b/ai_model/output/res.py @@ -1,50 +1,57 @@ import sys import torch -#model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet18', pretrained=True) + +# model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet18', pretrained=True) # or any of these variants # model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet34', pretrained=True) # model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet101', pretrained=True) -#model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet152', pretrained=True) +# model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet152', pretrained=True) # Download an example image from the pytorch website -#import urllib -#url, filename = ("https://github.com/pytorch/hub/raw/master/images/dog.jpg", "dog.jpg") -#try: urllib.URLopener().retrieve(url, filename) -#except: urllib.request.urlretrieve(url, filename) +# import urllib +# url, filename = ("https://github.com/pytorch/hub/raw/master/images/dog.jpg", "dog.jpg") +# try: urllib.URLopener().retrieve(url, filename) +# except: urllib.request.urlretrieve(url, filename) from PIL import Image from torchvision import transforms + + def evaluate_image(filename): - model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet50', pretrained=True) + model = torch.hub.load("pytorch/vision:v0.10.0", "resnet50", pretrained=True) model.eval() - input_image = Image.open(filename).convert('RGB') - - preprocess = transforms.Compose([ - transforms.Resize(256), - transforms.CenterCrop(224), - transforms.ToTensor(), - transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), - ]) + input_image = Image.open(filename).convert("RGB") + + preprocess = transforms.Compose( + [ + transforms.Resize(256), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), + ] + ) input_tensor = preprocess(input_image) - input_batch = input_tensor.unsqueeze(0) # create a mini-batch as expected by the model + input_batch = input_tensor.unsqueeze( + 0 + ) # create a mini-batch as expected by the model -# move the input and model to GPU for speed if available -#if torch.cuda.is_available(): -# input_batch = input_batch.to('cuda') -# model.to('cuda') + # move the input and model to GPU for speed if available + # if torch.cuda.is_available(): + # input_batch = input_batch.to('cuda') + # model.to('cuda') with torch.no_grad(): output = model(input_batch) -# Tensor of shape 1000, with confidence scores over ImageNet's 1000 classes -#print(output[0]) -# The output has unnormalized scores. To get probabilities, you can run a softmax on it. + # Tensor of shape 1000, with confidence scores over ImageNet's 1000 classes + # print(output[0]) + # The output has unnormalized scores. To get probabilities, you can run a softmax on it. probabilities = torch.nn.functional.softmax(output[0], dim=0) -#print(probabilities) + # print(probabilities) -# Read the categories + # Read the categories with open("imagenet_classes.txt", "r") as f: categories = [s.strip() for s in f.readlines()] -# Show top categories per image + # Show top categories per image topx_prob, topx_catid = torch.topk(probabilities, 1) for i in range(topx_prob.size(0)): return categories[topx_catid[i]], topx_prob[i].item() diff --git a/ai_model/output/run.py b/ai_model/output/run.py index dc7f7bd..3a562b4 100644 --- a/ai_model/output/run.py +++ b/ai_model/output/run.py @@ -2,14 +2,29 @@ import os import json import shutil -from poison_image import protect_image + +from mitm_attack import protect_image_mitm from res import evaluate_image +from poison_image import protect_image + + +def process_image(image_path, output_image_path, protect_func): + if os.path.exists(output_image_path): + os.remove(output_image_path) + return protect_func(image_path, output_image_path) + def main(): parser = argparse.ArgumentParser(description="Process an image.") - parser.add_argument('--image', help="Path to the input image", default="images/dog.png") - parser.add_argument('--output_image_path', help="Path to save the output images",default="images") - parser.add_argument('--json_path', help="Path to save the JSON file",default="json") + parser.add_argument( + "--image", help="Path to the input image", default="images/dog.png" + ) + parser.add_argument( + "--output_image_path", help="Path to save the output images", default="images" + ) + parser.add_argument( + "--json_path", help="Path to save the JSON file", default="json" + ) args = parser.parse_args() if not args.image: @@ -28,7 +43,7 @@ def main(): # Define the level counts level_counts = [1, 2] - org_id,org_prb = evaluate_image(image_path) + org_id, org_prb = evaluate_image(image_path) base_url = "http://localhost:3000/files/" @@ -36,33 +51,40 @@ def main(): try: shutil.copy(image_path, destination) - print(f'File copied from {image_path} to {destination}') + print(f"File copied from {image_path} to {destination}") except Exception as e: - print(f'Error copying file: {e}') + print(f"Error copying file: {e}") - json_data = [ { - "imageName": f"{image_name}{image_extension}", - "downloadUrl": f"{base_url}{image_name}{image_extension}", - "detectionObject": org_id, - "detectionRate": org_prb - }] - + json_data = [ + { + "imageName": f"{image_name}{image_extension}", + "downloadUrl": f"{base_url}{image_name}{image_extension}", + "detectionObject": org_id, + "detectionRate": org_prb, + } + ] - for i, level_count in enumerate(level_counts, start=1): + protect_funcs = [protect_image, protect_image_mitm] + for i, protect_func in enumerate(protect_funcs, start=1): output_image_name = f"{image_name}_{i}{image_extension}" output_image_path = os.path.join(image_folder, output_image_name) - id, probability = protect_image(image_path, output_image_path, level_count=level_count, current_count=0) + current_id, current_prob = process_image( + image_path, output_image_path, protect_func + ) - json_data.append({ - "imageName": f"{image_name}{image_extension}", - "downloadUrl": f"{base_url}{output_image_name}", - "detectionRate": probability, - "detectionObject": id - }) + json_data.append( + { + "imageName": f"{image_name}{image_extension}", + "downloadUrl": output_image_path, + "detectedObject": current_id, + "detectionRate": current_prob, + } + ) - json_output_path = os.path.join(json_folder, f"output.json") - with open(json_output_path, 'w') as json_file: + json_output_path = os.path.join(json_folder, f"{image_name}.json") + with open(json_output_path, "w") as json_file: json.dump(json_data, json_file, indent=2) + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/ai_model/output/unet.py b/ai_model/output/unet.py index 400f9b5..5b912c7 100644 --- a/ai_model/output/unet.py +++ b/ai_model/output/unet.py @@ -4,6 +4,7 @@ import torchvision.transforms as T from PIL import Image + # Define the U-Net block with skip connections class UNetBlock(nn.Module): def __init__(self, in_channels, out_channels): @@ -16,85 +17,97 @@ def __init__(self, in_channels, out_channels): def forward(self, x, skip_connection=None): if skip_connection is not None: # Concatenate the skip connection - x = torch.cat([x, skip_connection], dim=1) # Concatenate along the channel dimension + x = torch.cat( + [x, skip_connection], dim=1 + ) # Concatenate along the channel dimension x = F.relu(self.bn1(self.conv1(x))) x = F.relu(self.bn2(self.conv2(x))) return x + # Full U-Net model with skip connections class UNet(nn.Module): def __init__(self): super(UNet, self).__init__() - + # Encoder (downsampling) self.enc1 = UNetBlock(3, 64) self.enc2 = UNetBlock(64, 128) - + # Decoder (upsampling) # After concatenation, the channel size is doubled, so adjust accordingly self.dec1_x1 = UNetBlock(128 + 64, 64) # 128 from enc2 + 64 from enc1 self.dec1_x2 = UNetBlock(128 + 64, 64) - + self.final_conv = nn.Conv2d(64, 3, kernel_size=1) - + def forward(self, x1, x2): # Encoder for the first image enc1_x1 = self.enc1(x1) # [batch, 64, h, w] enc2_x1 = self.enc2(F.max_pool2d(enc1_x1, 2)) # [batch, 128, h/2, w/2] - + # Encoder for the second image enc1_x2 = self.enc1(x2) # [batch, 64, h, w] enc2_x2 = self.enc2(F.max_pool2d(enc1_x2, 2)) # [batch, 128, h/2, w/2] - + # Combine features from both images with skip connections dec1_x1 = self.dec1_x1(F.interpolate(enc2_x1, scale_factor=2), enc1_x1) dec1_x2 = self.dec1_x2(F.interpolate(enc2_x2, scale_factor=2), enc1_x2) - + # Output combined out_x1 = self.final_conv(dec1_x1) out_x2 = self.final_conv(dec1_x2) - + # Blending both outputs blended_output = (out_x1 + out_x2) / 2 - + return blended_output + # Load and preprocess the images def load_image(image_path, image_size=(256, 256)): image = Image.open(image_path) - transform = T.Compose([ - T.Resize(image_size), - T.ToTensor() - ]) + transform = T.Compose([T.Resize(image_size), T.ToTensor()]) return transform(image).unsqueeze(0) # Add batch dimension + def save_image(tensor, path): tensor = tensor.squeeze(0).permute(1, 2, 0) # Remove batch and rearrange dimensions image = tensor.detach().numpy() image = (image * 255).astype("uint8") Image.fromarray(image).save(path) - superimpose_images("bird.jpeg", path, alpha1=0.3, alpha2=0.7, output_path='output.png') - -def superimpose_images(image1_path, image2_path, alpha1=0.1, alpha2=0.9, output_path='output.png'): + superimpose_images( + "bird.jpeg", path, alpha1=0.3, alpha2=0.7, output_path="output.png" + ) + + +def superimpose_images( + image1_path, image2_path, alpha1=0.1, alpha2=0.9, output_path="output.png" +): # Open both images - img1 = Image.open(image1_path).convert('RGBA') - img2 = Image.open(image2_path).convert('RGBA') + img1 = Image.open(image1_path).convert("RGBA") + img2 = Image.open(image2_path).convert("RGBA") # Resize the second image to match the size of the first img2 = img2.resize(img1.size) # Adjust alpha values (transparency) for each image - img1_with_alpha = Image.blend(img1, Image.new('RGBA', img1.size, (0, 0, 0, 0)), alpha1) - img2_with_alpha = Image.blend(img2, Image.new('RGBA', img2.size, (0, 0, 0, 0)), alpha2) + img1_with_alpha = Image.blend( + img1, Image.new("RGBA", img1.size, (0, 0, 0, 0)), alpha1 + ) + img2_with_alpha = Image.blend( + img2, Image.new("RGBA", img2.size, (0, 0, 0, 0)), alpha2 + ) # Superimpose the images blended_image = Image.alpha_composite(img1_with_alpha, img2_with_alpha) # Save the result blended_image.save(output_path) - blended_image.show() + blended_image.show() -def blend(org_path,new_path): + +def blend(org_path, new_path): # Sample usage image1 = load_image(org_path) image2 = load_image(new_path) @@ -107,9 +120,4 @@ def blend(org_path,new_path): # Convert the output back to an image and save it - save_image(output, "blended_output.jpg") - - - - From d6ef35837f186dff9c6b6b6866ef133d6ff1d70b Mon Sep 17 00:00:00 2001 From: Sajeer Date: Sat, 28 Sep 2024 08:57:27 +0530 Subject: [PATCH 3/3] Multi model integration --- ai_model/output/pixel_flipper/checker.py | 36 +++++++++++++++++++ ai_model/output/pixel_flipper/convince.py | 36 +++++++++++++++++++ .../output/pixel_flipper/pixel_manipulate.py | 32 +++++++++++++++++ ai_model/output/poison_image.py | 2 +- 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 ai_model/output/pixel_flipper/checker.py create mode 100644 ai_model/output/pixel_flipper/convince.py create mode 100644 ai_model/output/pixel_flipper/pixel_manipulate.py diff --git a/ai_model/output/pixel_flipper/checker.py b/ai_model/output/pixel_flipper/checker.py new file mode 100644 index 0000000..bd6d433 --- /dev/null +++ b/ai_model/output/pixel_flipper/checker.py @@ -0,0 +1,36 @@ +import sys +import torch +# model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet18', pretrained=True) +# model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet34', pretrained=True) +# model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet101', pretrained=True) +# model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet152', pretrained=True) + +from PIL import Image +from torchvision import transforms + +model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet152', pretrained=True) +model.eval() + + +def evaluate_image(filename): + input_image = filename + preprocess = transforms.Compose([ + transforms.Resize(256), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), + ]) + input_tensor = preprocess(input_image) + input_batch = input_tensor.unsqueeze(0) # create a mini-batch as expected by the model + + with torch.no_grad(): + output = model(input_batch) + probabilities = torch.nn.functional.softmax(output[0], dim=0) + + # Read the categories + with open("imagenet_classes.txt", "r") as f: + categories = [s.strip() for s in f.readlines()] + # Show top categories per image + topx_prob, topx_catid = torch.topk(probabilities, 1) + for i in range(topx_prob.size(0)): + return topx_catid, topx_prob diff --git a/ai_model/output/pixel_flipper/convince.py b/ai_model/output/pixel_flipper/convince.py new file mode 100644 index 0000000..c297c17 --- /dev/null +++ b/ai_model/output/pixel_flipper/convince.py @@ -0,0 +1,36 @@ +from checker import evaluate_image +from pixel_manipulate import flip_random_pixels +import sys +from PIL import Image +import torch + +x = 0 +y = 0 + +original_file = Image.open(sys.argv[1], "r") +prev_file = original_file +next_file = original_file + +# Round 1 - find and store initial classification +orig_cat_id, orig_score = evaluate_image(original_file) +with open("imagenet_classes.txt", "r") as f: + categories = [s.strip() for s in f.readlines()] + print(categories[orig_cat_id], orig_score.item()) + +cur_cat_id = orig_cat_id +prev_score = orig_score +new_score = orig_score + +while orig_cat_id == cur_cat_id: +#while new_score > float(orig_score.item()): + next_file = flip_random_pixels(prev_file) + print(x, y) + cur_cat_id, new_score = evaluate_image(next_file) + print("New score: " + str(new_score.item()) + " Old score: " + str(prev_score.item())) + if new_score.item() > prev_score.item(): + next_file = prev_file + else: + prev_score = new_score + +print("New category: " + categories[cur_cat_id]) +next_file.save("Output.jpg") diff --git a/ai_model/output/pixel_flipper/pixel_manipulate.py b/ai_model/output/pixel_flipper/pixel_manipulate.py new file mode 100644 index 0000000..8e0dee8 --- /dev/null +++ b/ai_model/output/pixel_flipper/pixel_manipulate.py @@ -0,0 +1,32 @@ +import random +from PIL import Image +import numpy as np + + +def flip_random_pixels(img, flip_percentage=0.01): + # Open the image + img = img.convert('RGB') # Ensure it's in RGB format + + # Convert image to numpy array for pixel manipulation + img_array = np.array(img) + + # Get image dimensions + height, width, _ = img_array.shape + num_pixels = height * width + + # Determine number of pixels to flip + num_flips = int(num_pixels * flip_percentage) + + # Randomly select pixels and flip them + for _ in range(num_flips): + x = random.randint(0, width - 1) + y = random.randint(0, height - 1) + + # Flip pixel values by inverting the RGB channels (255 - value) + img_array[y, x] = 255 - img_array[y, x] + + # Convert the numpy array back to an image + flipped_img = Image.fromarray(img_array) + + # Save the new image + return flipped_img diff --git a/ai_model/output/poison_image.py b/ai_model/output/poison_image.py index ea1289c..2b260cc 100644 --- a/ai_model/output/poison_image.py +++ b/ai_model/output/poison_image.py @@ -13,7 +13,7 @@ import tensorflow as tf -def protect_image(image_path, output_folder, level_count=40, current_count=0): +def protect_image(image_path, output_folder, level_count=5, current_count=0): # Load and preprocess image org_id, org_prob = evaluate_image(image_path) image = Image.open(image_path).convert("RGB")