Skip to content

Commit

Permalink
crack mask into 3 directions; compatible to jpg and JPG
Browse files Browse the repository at this point in the history
  • Loading branch information
cnpcshangbo committed Apr 21, 2024
1 parent 5be3cef commit b320bee
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 11 deletions.
96 changes: 96 additions & 0 deletions DirectoryImageMaskProcessor_23directions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
from PIL import Image
import os
from red23connected_components import CrackClassifier


class DirectoryImageMaskProcessor_23directions:
def __init__(self, input_directory):
self.input_directory = input_directory
parent_directory = os.path.dirname(input_directory)
# self.red_output_directory = os.path.join(parent_directory, "red_crack_masks")
# self.green_output_directory = os.path.join(
# parent_directory, "green_spall_masks"
# )
# self.horizontal_masks_directory = os.path.join(
# parent_directory, "horizontal_crack_masks"
# )
# self.vertical_masks_directory = os.path.join(
# parent_directory, "vertical_crack_masks"
# )
# self.diagonal_masks_directory = os.path.join(
# parent_directory, "diagonal_crack_masks"
# )
self.output_directory = os.path.join(parent_directory, "3masks")

def process_directory(self):
# Ensure the output directories exist
# os.makedirs(self.red_output_directory, exist_ok=True)
# os.makedirs(self.green_output_directory, exist_ok=True)
# os.makedirs(self.horizontal_crack_masks, exist_ok=True)
# os.makedirs(self.vertical_crack_masks, exist_ok=True)
# os.makedirs(self.diagonal_crack_masks, exist_ok=True)

image_files = [
f
for f in os.listdir(self.input_directory)
if f.lower().endswith(("png", "jpg", "jpeg"))
]
total_images = len(image_files)
print(f"Found {total_images} images to process.")

for idx, image_file in enumerate(image_files, start=1):
print(f"Processing image {idx}/{total_images}: {image_file}")
self.process_image(image_file)

print("All images processed successfully.")

def process_image(self, image_file):
# Load and convert the image
image_path = os.path.join(self.input_directory, image_file)
output_directory_w_filename = os.path.join(self.output_directory, image_file)
CrackClassifier.classify_and_save_cracks(
image_path, output_directory_w_filename
)
# image = Image.open(image_path).convert("RGBA")

# # Split the loaded image into separate channels
# r, g, b, a = image.split()

# # Create and save the red and green masks
# self.create_and_save_mask(
# r, image_file, self.red_output_directory, mask_type="red"
# )
# self.create_and_save_mask(
# g, image_file, self.green_output_directory, mask_type="green"
# )

def create_and_save_mask(self, channel, image_file, output_directory, mask_type):
# Create a mask from the given channel
mask = Image.merge(
"RGBA",
(
channel if mask_type == "red" else Image.new("L", channel.size, 0),
channel if mask_type == "green" else Image.new("L", channel.size, 0),
Image.new("L", channel.size, 0),
channel,
),
)

# Define the full path for the mask
mask_path = os.path.join(output_directory, image_file)

# Save the mask
mask.save(mask_path)
print(f"Saved {mask_type} mask: {mask_path}")


# Example usage
if __name__ == "__main__":
input_directory = "images_folder" # Adjust this path to your folder of images

processor = DirectoryImageMaskProcessor(input_directory)
processor.process_directory()

print(
f"Processing complete. Check the parent directory of '{input_directory}' for the 'red_crack_masks' and 'green_spall_masks' folders."
)
34 changes: 29 additions & 5 deletions crack23directions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
from pathlib import Path

from DirectoryImageMaskProcessor_1 import DirectoryImageMaskProcessor
from DirectoryImageMaskProcessor_23directions import (
DirectoryImageMaskProcessor_23directions,
)


class CrackMaskProcessor:
Expand Down Expand Up @@ -42,6 +45,9 @@ def ensure_directories_exist(self):
def get_crack_spall_mask_path(self):
return self.mask_directory

def get_red_crack_mask_path(self):
return self.mask_directory.replace("crackmask", "red_crack_masks")

def get_and_ensure_3masks_directory(self):
# Replace 'crackmask' with '3masks' in the mask_directory path
masks_directory = self.mask_directory.replace("crackmask", "3masks")
Expand All @@ -55,6 +61,17 @@ def get_and_ensure_3masks_directory(self):


# Main part of the script
def extract_crack(crack_spall_mask_path):
input_directory = crack_spall_mask_path

processor_extract_crack = DirectoryImageMaskProcessor(input_directory)
processor_extract_crack.process_directory()

print(
f"Processing complete. Check the parent directory of '{input_directory}' for the results."
)


if __name__ == "__main__":
script_dir = Path(__file__).parent.absolute()
config_ini_path = script_dir / "config.ini"
Expand All @@ -66,15 +83,22 @@ def get_and_ensure_3masks_directory(self):
crack_spall_mask_path = processor.get_crack_spall_mask_path()
print(f"Crack/Spall Mask Path: {crack_spall_mask_path}")

# Extracting red crack images into a seperate file
# extract_crack(crack_spall_mask_path)

# Get red_crack_masks directory path
red_crack_mask_path = processor.get_red_crack_mask_path()
print(f"red_crack_mask Path: {red_crack_mask_path}")

masks_directory_path = processor.get_and_ensure_3masks_directory()
print(f"'3masks' Directory Path: {masks_directory_path}")

# Extracting red crack images into a seperate file
input_directory = crack_spall_mask_path
# Extracting three directions of cracks into three files
input_directory = red_crack_mask_path

processor = DirectoryImageMaskProcessor(input_directory)
processor.process_directory()
processor_extract_3 = DirectoryImageMaskProcessor_23directions(input_directory)
processor_extract_3.process_directory()

print(
f"Processing complete. Check the parent directory of '{input_directory}' for the results."
f"Processing complete. Check the parent directory of '{masks_directory_path}' for the results."
)
24 changes: 19 additions & 5 deletions crackmask2spalloverlay.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,27 @@ def main():
# Iterate over the files in the mask directory
for mask_name in os.listdir(mask_dir):
# Extract the image name from the filename
raw_name = mask_name.split(".")[0] + ".JPG"

raw_name_base = mask_name.split(".")[0]
raw_name_jpg = f"{raw_name_base}.jpg"
raw_name_JPG = f"{raw_name_base}.JPG"

# Check for the existence of the raw image file with both extensions
raw_path_jpg = os.path.join(raw_dir, raw_name_jpg)
raw_path_JPG = os.path.join(raw_dir, raw_name_JPG)

if os.path.exists(raw_path_jpg):
raw_path = raw_path_jpg
elif os.path.exists(raw_path_JPG):
raw_path = raw_path_JPG
else:
print(f"Error: Raw image file not found for {mask_name}. Skipping...")
continue

# Load the mask and raw images
mask = cv2.imread(os.path.join(mask_dir, mask_name), cv2.IMREAD_GRAYSCALE)
raw = cv2.imread(os.path.join(raw_dir, raw_name))
raw = cv2.imread(raw_path)
if mask is None or raw is None:
print(f"Error reading {mask_name} or {raw_name}. Skipping...")
print(f"Error reading {mask_name} or {raw_path}. Skipping...")
continue
print(raw.shape)
print(mask.shape)
Expand All @@ -39,7 +53,7 @@ def main():
# raw[mask == 38] = [0, 0, 255]
raw[mask == 75] = [0, 0, 255]
# Save the overlaid image to the output directory
spall_overlaid_image_path = os.path.join(spall_overlay_directory, raw_name)
spall_overlaid_image_path = os.path.join(spall_overlay_directory, os.path.basename(raw_path))
cv2.imwrite(spall_overlaid_image_path, raw)
print(f"Saved {spall_overlaid_image_path}")

Expand Down
2 changes: 1 addition & 1 deletion cracksegmentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
--model "{model_path}" \
--images "{raw_directory}" \
--output "{mask_directory}" \
--extension 'JPG'
--extension jpg png JPG
"""

os.system(command)
81 changes: 81 additions & 0 deletions red23connected_components.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import numpy as np
from skimage.measure import label, regionprops
from PIL import Image, ImageDraw
import os


class CrackClassifier:
def __init__(self):
pass

@classmethod
def classify_and_save_cracks(cls, red_mask_image_path, output_folder):
# Load the red mask image
red_mask = Image.open(red_mask_image_path)

# Convert to numpy array and get the alpha channel as the mask
red_mask_np = np.array(red_mask)
alpha_channel = red_mask_np[
:, :, 3
] # Assuming the alpha channel is the last one

# Label connected components
labeled_mask = label(alpha_channel)

# Analyze properties of labeled regions
regions = regionprops(labeled_mask)

# Placeholder for categorized cracks
vertical_cracks = []
horizontal_cracks = []
diagonal_cracks = []

# Classify based on orientation and aspect ratio
for props in regions:
y0, x0, y1, x1 = props.bbox
region_height = y1 - y0
region_width = x1 - x0
aspect_ratio = region_width / float(region_height)

if aspect_ratio > 2:
horizontal_cracks.extend(props.coords)
elif aspect_ratio < 0.5:
vertical_cracks.extend(props.coords)
else:
# Diagonal classification can be refined as needed
orientation = props.orientation
if -np.pi / 4 <= orientation <= np.pi / 4:
horizontal_cracks.extend(props.coords)
else:
diagonal_cracks.extend(props.coords)

# Create the output directory if it doesn't exist
if not os.path.exists(output_folder):
os.makedirs(output_folder)

# Image shape needed for mask creation
image_shape = alpha_channel.shape

# Save masks for each type of crack
cls._save_crack_mask(
vertical_cracks, f"{output_folder}/vertical_crack_mask.png", image_shape
)
cls._save_crack_mask(
horizontal_cracks, f"{output_folder}/horizontal_crack_mask.png", image_shape
)
cls._save_crack_mask(
diagonal_cracks, f"{output_folder}/diagonal_crack_mask.png", image_shape
)

@staticmethod
def _save_crack_mask(coords_list, mask_path, image_shape):
# Create an empty image with transparent background
crack_mask = Image.new("RGBA", (image_shape[1], image_shape[0]), (0, 0, 0, 0))
draw = ImageDraw.Draw(crack_mask)

# Draw each pixel for the classified cracks
for coord in coords_list:
draw.point((coord[1], coord[0]), fill=(255, 0, 0, 255)) # (x, y)

# Save the mask
crack_mask.save(mask_path)

0 comments on commit b320bee

Please sign in to comment.