diff --git a/Copy_of_Image_Processing.ipynb b/Copy_of_Image_Processing.ipynb new file mode 100644 index 0000000..838c3e0 --- /dev/null +++ b/Copy_of_Image_Processing.ipynb @@ -0,0 +1,398 @@ +{ + "cells": [ + { + "cell_type": "code", + "source": [ + "import cv2\n", + "import matplotlib.pyplot as plt\n", + "import os\n", + "import glob # Import the glob library\n", + "\n", + "from google.colab import drive\n", + "drive.mount('/content/drive')\n", + "\n", + "# --- CONFIGURATION PARAMETERS ---\n", + "# Define the size of the patch to save (in pixels)\n", + "PATCH_SIZE = 64\n", + "BW, BH = PATCH_SIZE, PATCH_SIZE\n", + "\n", + "# Define the paths\n", + "template_path = '/content/drive/MyDrive/PCB_DATASET/PCB_DATASET/PCB_USED/04.JPG'\n", + "folder_path = '/content/drive/MyDrive/PCB_DATASET/PCB_DATASET/images/Missing_hole/04_missing_hole'\n", + "out_dir = \"/content/drive/MyDrive/PCB_DATASET/PCB_DATASET/Missing_hole_defects\"\n", + "\n", + "# Ensure the output directory exists\n", + "os.makedirs(out_dir, exist_ok=True)\n", + "\n", + "# Global counter for saved patches - MUST be initialized outside the loop\n", + "global_patch_id = 0\n", + "\n", + "# Define the area constraints for defect detection\n", + "MIN_AREA = 0\n", + "MAX_AREA = 1500\n", + "\n", + "\n", + "# Read template PCB 01 image\n", + "rgb_template_img = cv2.imread(template_path)\n", + "plt.figure(figsize=(10,6))\n", + "plt.imshow(rgb_template_img, cmap=\"gray\")\n", + "\n", + "# Calculate the resized dimensions (1/4th of original)\n", + "a = int(rgb_template_img.shape[0]/4)\n", + "b = int(rgb_template_img.shape[1]/4)\n", + "\n", + "# Read template PCB 01 image as grayscale\n", + "template_img = cv2.imread(template_path, 0)\n", + "# display the grayscale template PCB image\n", + "plt.figure(figsize=(10,6))\n", + "plt.imshow(template_img, cmap=\"gray\")\n", + "\n", + "# Resize template image of PCB\n", + "template_img_resize = cv2.resize(template_img, (b,a))\n", + "plt.figure(figsize=(10,6))\n", + "plt.imshow(template_img_resize, cmap=\"gray\")\n", + "\n", + "# Gaussian blur\n", + "blur_template_img = cv2.GaussianBlur(template_img_resize, (3,3),0)\n", + "# display the blurred image\n", + "plt.figure(figsize=(10,6))\n", + "plt.imshow(blur_template_img, cmap=\"gray\")\n", + "\n", + "# Adaptive thresholding\n", + "template_adap_thresh = cv2.adaptiveThreshold(blur_template_img, 255,\n", + " cv2. ADAPTIVE_THRESH_MEAN_C,\n", + " cv2.THRESH_BINARY, 15, 5)\n", + "# display the thresholded image\n", + "plt.figure(figsize=(10,6))\n", + "plt.imshow(template_adap_thresh, cmap=\"gray\")\n", + "# Note: Initial display code for template is removed here to keep the final script cleaner,\n", + "# but it can be re-added before the loop if needed for verification.\n", + "\n", + "\n", + "# Use glob to find all files ending with '.jpg' in the specified folder\n", + "image_files = glob.glob(os.path.join(folder_path, '*.jpg'))\n", + "\n", + "print(f\"Found {len(image_files)} images in the folder.\")\n", + "print(f\"Defect area filter range: {MIN_AREA} < Area < {MAX_AREA}\")\n", + "\n", + "\n", + "\n", + "# Iterate over each image file path found\n", + "for image_path in image_files:\n", + " # 1. Read and prepare test image\n", + " bgr_test_img = cv2.imread(image_path)\n", + " filename = os.path.basename(image_path)\n", + "\n", + " # Check if the image was loaded successfully\n", + " if bgr_test_img is None:\n", + " print(f\"Skipping file: {filename} (Not a readable image).\")\n", + " continue\n", + "\n", + " # Convert BGR to RGB for matplotlib display (if needed)\n", + " rgb_test_img = cv2.cvtColor(bgr_test_img, cv2.COLOR_BGR2RGB) # Not used below, but good practice\n", + " # 2. Display the original test PCB image\n", + " plt.figure(figsize=(10,6))\n", + " plt.imshow(rgb_test_img, cmap = \"gray\")\n", + " plt.title(f\"Original Test PCB Image: {filename}\")\n", + "\n", + " # Read grayscale\n", + " test_img = cv2.imread(image_path, 0)\n", + "\n", + " # Resize, Blur, and Threshold the test image\n", + " test_img_resize = cv2.resize(test_img, (b, a))\n", + " # 3. Display the grayscale resized test PCB image\n", + " plt.figure(figsize=(10,6))\n", + " plt.imshow(test_img_resize, cmap=\"gray\")\n", + " plt.title(f\"Resized Grayscale PCB Image: {filename} ({b}x{a})\")\n", + " blur_test_img = cv2.GaussianBlur(test_img_resize, (3,3),0)\n", + "\n", + " test_adap_thresh = cv2.adaptiveThreshold(blur_test_img, 255,\n", + " cv2. ADAPTIVE_THRESH_MEAN_C,\n", + " cv2.THRESH_BINARY, 15, 5)\n", + "\n", + " plt.figure(figsize=(10,6))\n", + " plt.imshow(test_adap_thresh, cmap=\"gray\")\n", + "\n", + " # 2. Difference Imaging (Core Defect Detection)\n", + " sub_img = cv2.subtract(test_adap_thresh, template_adap_thresh)\n", + " plt.figure(figsize=(10,6))\n", + " plt.imshow(sub_img)\n", + " final_img = cv2.medianBlur(sub_img, 3) # Noise reduction\n", + " plt.figure(figsize=(10,6))\n", + " plt.imshow(final_img, cmap=\"gray\")\n", + "\n", + " # 3. Find Contours\n", + " # Using RETR_EXTERNAL focuses on the outline of defect blobs\n", + " # Note: final_img is the mask image used for finding contours\n", + "\n", + " orig = test_img_resize\n", + " mask_img = final_img\n", + " _, thresh = cv2.threshold(mask_img, 127, 255, cv2.THRESH_BINARY)\n", + " contours, _ = cv2.findContours(thresh, cv2.RETR_LIST,\n", + " cv2.CHAIN_APPROX_SIMPLE) # CHANGE ***\n", + "\n", + " current_defects_count = 0\n", + " orig = test_img_resize # The source image for cropping\n", + " h_img, w_img = final_img.shape[:2]\n", + "\n", + "\n", + " # 4. Filter Contours and Save Patches (MUST be inside the image loop)\n", + " for cnt in contours:\n", + " area = cv2.contourArea(cnt)\n", + "\n", + " # Apply the defect area filter to ensure quality and control quantity\n", + " if MIN_AREA < area < MAX_AREA:\n", + " current_defects_count += 1\n", + "\n", + " # Get bounding box coordinates\n", + " x, y, w, h = cv2.boundingRect(cnt)\n", + "\n", + " # Center of defect\n", + " cx = x + w // 2\n", + " cy = y + h // 2\n", + "\n", + " # Fixed PATCh_SIZE x PATCh_SIZE box centered on defect\n", + " x0 = cx - BW // 2\n", + " y0 = cy - BH // 2\n", + " x1 = x0 + BW\n", + " y1 = y0 + BH\n", + "\n", + " # Clip coordinates to image bounds\n", + " x0 = max(0, x0)\n", + " y0 = max(0, y0)\n", + " x1 = min(w_img, x1)\n", + " y1 = min(h_img, y1)\n", + "\n", + " # Crop patch from ORIGINAL resized image\n", + " patch = orig[y0:y1, x0:x1]\n", + "\n", + " # Ensure patch is the full desired size\n", + " if patch.shape[0] != BH or patch.shape[1] != BW:\n", + " continue\n", + "\n", + " # Save patch\n", + " base_name = os.path.splitext(filename)[0]\n", + " # Use global_patch_id for unique sequential naming across ALL files\n", + " out_path = os.path.join(out_dir, f\"defect_{base_name}_{global_patch_id:04d}.png\")\n", + " cv2.imwrite(out_path, patch)\n", + "\n", + " # Increment the global counter\n", + " global_patch_id += 1\n", + "\n", + " print(f\"Processed {filename}: Found {current_defects_count} defects (Total saved: {global_patch_id})\")\n", + "\n", + "print(f\"\\n--- Processing Complete ---\")\n", + "print(f\"Total patches saved to {out_dir}: {global_patch_id}\")" + ], + "metadata": { + "id": "PC8H10uNrks8" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "86xolD1rmA3D" + }, + "outputs": [], + "source": [ + "import cv2\n", + "import matplotlib.pyplot as plt\n", + "import os\n", + "import glob # Import the glob library\n", + "\n", + "from google.colab import drive\n", + "drive.mount('/content/drive')\n", + "\n", + "# --- CONFIGURATION PARAMETERS ---\n", + "# Define the size of the patch to save (in pixels)\n", + "PATCH_SIZE = 64\n", + "BW, BH = PATCH_SIZE, PATCH_SIZE\n", + "\n", + "# Define the paths\n", + "template_path = '/content/drive/MyDrive/PCB_DATASET/PCB_DATASET/PCB_USED/12.JPG'\n", + "folder_path = '/content/drive/MyDrive/PCB_DATASET/PCB_DATASET/images/Spur/12_spur'\n", + "out_dir = \"/content/drive/MyDrive/PCB_DATASET/PCB_DATASET/Spur_defects\"\n", + "\n", + "# Ensure the output directory exists\n", + "os.makedirs(out_dir, exist_ok=True)\n", + "\n", + "# Global counter for saved patches - MUST be initialized outside the loop\n", + "global_patch_id = 0\n", + "\n", + "# Define the area constraints for defect detection\n", + "MIN_AREA = 0\n", + "MAX_AREA = 300\n", + "\n", + "\n", + "# Read template PCB 01 image\n", + "rgb_template_img = cv2.imread(template_path)\n", + "plt.figure(figsize=(10,6))\n", + "plt.imshow(rgb_template_img, cmap=\"gray\")\n", + "\n", + "# Calculate the resized dimensions (1/4th of original)\n", + "a = int(rgb_template_img.shape[0]/4)\n", + "b = int(rgb_template_img.shape[1]/4)\n", + "\n", + "# Read template PCB 01 image as grayscale\n", + "template_img = cv2.imread(template_path, 0)\n", + "# display the grayscale template PCB image\n", + "plt.figure(figsize=(10,6))\n", + "plt.imshow(template_img, cmap=\"gray\")\n", + "\n", + "# Resize template image of PCB\n", + "template_img_resize = cv2.resize(template_img, (b,a))\n", + "plt.figure(figsize=(10,6))\n", + "plt.imshow(template_img_resize, cmap=\"gray\")\n", + "\n", + "# Gaussian blur\n", + "blur_template_img = cv2.GaussianBlur(template_img_resize, (3,3),0)\n", + "# display the blurred image\n", + "plt.figure(figsize=(10,6))\n", + "plt.imshow(blur_template_img, cmap=\"gray\")\n", + "\n", + "# Adaptive thresholding\n", + "template_adap_thresh = cv2.adaptiveThreshold(blur_template_img, 255,\n", + " cv2.ADAPTIVE_THRESH_MEAN_C,\n", + " cv2.THRESH_BINARY, 25, 5)\n", + "# display the thresholded image\n", + "plt.figure(figsize=(10,6))\n", + "plt.imshow(template_adap_thresh, cmap=\"gray\")\n", + "# Note: Initial display code for template is removed here to keep the final script cleaner,\n", + "# but it can be re-added before the loop if needed for verification.\n", + "\n", + "\n", + "# Use glob to find all files ending with '.jpg' in the specified folder\n", + "image_files = glob.glob(os.path.join(folder_path, '*.jpg'))\n", + "\n", + "print(f\"Found {len(image_files)} images in the folder.\")\n", + "print(f\"Defect area filter range: {MIN_AREA} < Area < {MAX_AREA}\")\n", + "\n", + "\n", + "\n", + "# Iterate over each image file path found\n", + "for image_path in image_files:\n", + " # 1. Read and prepare test image\n", + " bgr_test_img = cv2.imread(image_path)\n", + " filename = os.path.basename(image_path)\n", + "\n", + " # Check if the image was loaded successfully\n", + " if bgr_test_img is None:\n", + " print(f\"Skipping file: {filename} (Not a readable image).\")\n", + " continue\n", + "\n", + " # Convert BGR to RGB for matplotlib display (if needed)\n", + " rgb_test_img = cv2.cvtColor(bgr_test_img, cv2.COLOR_BGR2RGB) # Not used below, but good practice\n", + " # 2. Display the original test PCB image\n", + " plt.figure(figsize=(10,6))\n", + " plt.imshow(rgb_test_img, cmap = \"gray\")\n", + " plt.title(f\"Original Test PCB Image: {filename}\")\n", + "\n", + " # Read grayscale\n", + " test_img = cv2.imread(image_path, 0)\n", + "\n", + " # Resize, Blur, and Threshold the test image\n", + " test_img_resize = cv2.resize(test_img, (b, a))\n", + " # 3. Display the grayscale resized test PCB image\n", + " plt.figure(figsize=(10,6))\n", + " plt.imshow(test_img_resize, cmap=\"gray\")\n", + " plt.title(f\"Resized Grayscale PCB Image: {filename} ({b}x{a})\")\n", + " blur_test_img = cv2.GaussianBlur(test_img_resize, (3,3),0)\n", + "\n", + " test_adap_thresh = cv2.adaptiveThreshold(blur_test_img, 255,\n", + " cv2. ADAPTIVE_THRESH_MEAN_C,\n", + " cv2.THRESH_BINARY, 25, 5)\n", + "\n", + " plt.figure(figsize=(10,6))\n", + " plt.imshow(test_adap_thresh, cmap=\"gray\")\n", + "\n", + " # 2. Difference Imaging (Core Defect Detection)\n", + " sub_img = cv2.subtract(test_adap_thresh, template_adap_thresh)\n", + " plt.figure(figsize=(10,6))\n", + " plt.imshow(sub_img)\n", + " final_img = cv2.medianBlur(sub_img, 3) # Noise reduction\n", + " plt.figure(figsize=(10,6))\n", + " plt.imshow(final_img, cmap=\"gray\")\n", + "\n", + " # 3. Find Contours\n", + " # Using RETR_EXTERNAL focuses on the outline of defect blobs\n", + " # Note: final_img is the mask image used for finding contours\n", + "\n", + " orig = test_img_resize\n", + " mask_img = final_img\n", + " _, thresh = cv2.threshold(mask_img, 127, 255, cv2.THRESH_BINARY)\n", + " contours, _ = cv2.findContours(thresh, cv2.RETR_LIST,\n", + " cv2.CHAIN_APPROX_SIMPLE) # CHANGE ***\n", + "\n", + " current_defects_count = 0\n", + " orig = test_img_resize # The source image for cropping\n", + " h_img, w_img = final_img.shape[:2]\n", + "\n", + "\n", + " # 4. Filter Contours and Save Patches (MUST be inside the image loop)\n", + " for cnt in contours:\n", + " area = cv2.contourArea(cnt)\n", + "\n", + " # Apply the defect area filter to ensure quality and control quantity\n", + " if MIN_AREA < area < MAX_AREA:\n", + " current_defects_count += 1\n", + "\n", + " # Get bounding box coordinates\n", + " x, y, w, h = cv2.boundingRect(cnt)\n", + "\n", + " # Center of defect\n", + " cx = x + w // 2\n", + " cy = y + h // 2\n", + "\n", + " # Fixed PATCh_SIZE x PATCh_SIZE box centered on defect\n", + " x0 = cx - BW // 2\n", + " y0 = cy - BH // 2\n", + " x1 = x0 + BW\n", + " y1 = y0 + BH\n", + "\n", + " # Clip coordinates to image bounds\n", + " x0 = max(0, x0)\n", + " y0 = max(0, y0)\n", + " x1 = min(w_img, x1)\n", + " y1 = min(h_img, y1)\n", + "\n", + " # Crop patch from ORIGINAL resized image\n", + " patch = orig[y0:y1, x0:x1]\n", + "\n", + " # Ensure patch is the full desired size\n", + " if patch.shape[0] != BH or patch.shape[1] != BW:\n", + " continue\n", + "\n", + " # Save patch\n", + " base_name = os.path.splitext(filename)[0]\n", + " # Use global_patch_id for unique sequential naming across ALL files\n", + " out_path = os.path.join(out_dir, f\"defect_{base_name}_{global_patch_id:04d}.png\")\n", + " cv2.imwrite(out_path, patch)\n", + "\n", + " # Increment the global counter\n", + " global_patch_id += 1\n", + "\n", + " print(f\"Processed {filename}: Found {current_defects_count} defects (Total saved: {global_patch_id})\")\n", + "\n", + "print(f\"\\n--- Processing Complete ---\")\n", + "print(f\"Total patches saved to {out_dir}: {global_patch_id}\")" + ] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file