-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
crack mask into 3 directions; compatible to jpg and JPG
- Loading branch information
1 parent
5be3cef
commit b320bee
Showing
5 changed files
with
226 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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." | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |