diff --git a/Untitled1.ipynb b/Untitled1.ipynb new file mode 100644 index 0000000..11ae5a3 --- /dev/null +++ b/Untitled1.ipynb @@ -0,0 +1 @@ +{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[],"mount_file_id":"1Hi1q37BQmZjp7hNKV5nKFEnAHGDt4UJ6","authorship_tag":"ABX9TyMBvTg5ACXmjvG27VVQWfmE"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":1000,"output_embedded_package_id":"18pqUFiLx-etkSEycYauUnnkreKbVHmI7"},"id":"c4fGXzVCgMlc","executionInfo":{"status":"ok","timestamp":1766762127328,"user_tz":-330,"elapsed":108320,"user":{"displayName":"Aradhya Stuti","userId":"13084479309528900862"}},"outputId":"62d9ab7b-da85-4d8b-fa97-f0eac2c6b247"},"outputs":[{"output_type":"display_data","data":{"text/plain":"Output hidden; open in https://colab.research.google.com to view."},"metadata":{}}],"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/4'\n","out_dir = \"/content/drive/MyDrive/PCB_DATASET/PCB_DATASET/Missing_hole_4defects\"\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}\")"]},{"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/01.JPG'\n","folder_path = '/content/drive/MyDrive/PCB_DATASET/PCB_DATASET/images/Spur/1'\n","out_dir = \"/content/drive/MyDrive/PCB_DATASET/PCB_DATASET/Spur_1defects\"\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 = 1\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":{"base_uri":"https://localhost:8080/","height":1000,"output_embedded_package_id":"1BMivZVQlj5yg6Cy3MGt5gdQ6LZ3DQbrt"},"id":"HEXIWQHchMbj","executionInfo":{"status":"ok","timestamp":1766762221799,"user_tz":-330,"elapsed":94295,"user":{"displayName":"Aradhya Stuti","userId":"13084479309528900862"}},"outputId":"35f63010-2dca-41cb-dd3d-4cf1a3f421a5"},"execution_count":null,"outputs":[{"output_type":"display_data","data":{"text/plain":"Output hidden; open in https://colab.research.google.com to view."},"metadata":{}}]},{"cell_type":"code","source":["%cd /content/AI_PCB_Defect_Detection_Classification_System\n"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"cyoahIlbtRON","executionInfo":{"status":"ok","timestamp":1766870923586,"user_tz":-330,"elapsed":21,"user":{"displayName":"Aradhya Stuti","userId":"13084479309528900862"}},"outputId":"6b52c656-5b90-4ca4-94ed-458bd2b70912"},"execution_count":75,"outputs":[{"output_type":"stream","name":"stdout","text":["/content/AI_PCB_Defect_Detection_Classification_System\n"]}]},{"cell_type":"code","source":["!git checkout my-branch\n"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"mQhHAJJCtt03","executionInfo":{"status":"ok","timestamp":1766870936838,"user_tz":-330,"elapsed":66,"user":{"displayName":"Aradhya Stuti","userId":"13084479309528900862"}},"outputId":"80c9838d-9a11-4236-b639-776e23546ce0"},"execution_count":76,"outputs":[{"output_type":"stream","name":"stdout","text":["Branch 'my-branch' set up to track remote branch 'my-branch' from 'origin'.\n","Switched to a new branch 'my-branch'\n"]}]},{"cell_type":"code","source":["!git branch\n"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"hnEZhqRttx4C","executionInfo":{"status":"ok","timestamp":1766870953291,"user_tz":-330,"elapsed":132,"user":{"displayName":"Aradhya Stuti","userId":"13084479309528900862"}},"outputId":"d0083afc-6b86-402e-de5e-ba776cf4c7c3"},"execution_count":77,"outputs":[{"output_type":"stream","name":"stdout","text":[" main\u001b[m\n","* \u001b[32mmy-branch\u001b[m\n"]}]},{"cell_type":"code","source":["!ls /content\n"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"cnfjurj8t0gQ","executionInfo":{"status":"ok","timestamp":1766870963358,"user_tz":-330,"elapsed":64,"user":{"displayName":"Aradhya Stuti","userId":"13084479309528900862"}},"outputId":"9c0f8cb5-49c7-49ba-f2d8-babd7e50a8b6"},"execution_count":78,"outputs":[{"output_type":"stream","name":"stdout","text":["AI_PCB_Defect_Detection_Classification_System\n","drive\n","PCB-DEFECT-DETECTION-AND-CLASSIFICATION\n","sample_data\n"]}]},{"cell_type":"code","source":["!cp /content/drive/MyDrive/Colab Notebooks/Untitled1.ipynb .\n"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"CAsBzu3It5oP","executionInfo":{"status":"ok","timestamp":1766871012416,"user_tz":-330,"elapsed":71,"user":{"displayName":"Aradhya Stuti","userId":"13084479309528900862"}},"outputId":"6b20a369-5883-4856-aaa2-946bc3cff6ce"},"execution_count":80,"outputs":[{"output_type":"stream","name":"stdout","text":["cp: cannot stat '/content/drive/MyDrive/Colab': No such file or directory\n","cp: cannot stat 'Notebooks/Untitled1.ipynb': No such file or directory\n"]}]}]} \ No newline at end of file diff --git a/images/defect_01_spur_06_0008.png b/images/defect_01_spur_06_0008.png new file mode 100644 index 0000000..777b39f Binary files /dev/null and b/images/defect_01_spur_06_0008.png differ diff --git a/images/defect_01_spur_07_0003.png b/images/defect_01_spur_07_0003.png new file mode 100644 index 0000000..fb80eaa Binary files /dev/null and b/images/defect_01_spur_07_0003.png differ diff --git a/images/defect_04_missing_hole_02_0022.png b/images/defect_04_missing_hole_02_0022.png new file mode 100644 index 0000000..5de35d3 Binary files /dev/null and b/images/defect_04_missing_hole_02_0022.png differ diff --git a/images/defect_04_missing_hole_02_0023.png b/images/defect_04_missing_hole_02_0023.png new file mode 100644 index 0000000..635ede3 Binary files /dev/null and b/images/defect_04_missing_hole_02_0023.png differ