-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(jobs): add c clef extraction job
- Loading branch information
1 parent
f1b0042
commit 8013bd4
Showing
3 changed files
with
151 additions
and
0 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,4 @@ | ||
__version__ = "1.0.0" | ||
from rodan.jobs import module_loader | ||
|
||
module_loader("rodan.jobs.extract_c_clefs.base") |
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,67 @@ | ||
from rodan.jobs.base import RodanTask | ||
from .extract_c_clefs import * | ||
import cv2 as cv | ||
import os | ||
import json | ||
import logging | ||
|
||
logger = logging.getLogger("rodan") | ||
|
||
|
||
class ExtractCClefs(RodanTask): | ||
name = "Extract C Clefs" | ||
author = "Lucas March" | ||
description = "Finds the C clefs from a generated XML file from the interactive classifier and exports them to seperate images." | ||
enabled = True | ||
category = "Image Processing" | ||
interactive = False | ||
settings = { | ||
"title": "Settings", | ||
"type": "object", | ||
"job_queue": "Python3", | ||
} | ||
input_port_types = ( | ||
{ | ||
"name": "PNG Image", | ||
"minimum": 1, | ||
"maximum": 1, | ||
"resource_types": ["image/rgba+png"], | ||
}, | ||
{ | ||
"name": "XML file", | ||
"minimum": 1, | ||
"maximum": 1, | ||
"resource_types": ["application/gamera+xml"], | ||
}, | ||
) | ||
output_port_types = ( | ||
{ | ||
"name": "C Clef", | ||
"minimum": 1, | ||
"maximum": 20, | ||
"is_list": True, | ||
"resource_types": ["image/rgba+png"], | ||
}, | ||
) | ||
|
||
def run_my_task(self, inputs, settings, outputs): | ||
logger.info("Running C Clef Extraction") | ||
|
||
image_path = inputs["PNG Image"][0]["resource_path"] | ||
image_name = inputs["PNG Image"][0]["resource_name"] | ||
xml_path = inputs["XML file"][0]["resource_path"] | ||
|
||
image = load_image(image_path) | ||
xml = load_xml(xml_path) | ||
coords = extract_coords(xml) | ||
if not coords: | ||
raise Exception("No C Clefs found in XML File.") | ||
cropped_images = crop_images(image, coords) | ||
output_base_path = outputs["C Clef"][0]["resource_folder"] | ||
logger.info(f"output base path {output_base_path}") | ||
for i, cropped_image in enumerate(cropped_images): | ||
index = i + 1 # Start indexing from 1 | ||
output_path = f"{output_base_path}{image_name}_{index}.png" | ||
save_image(cropped_image, output_path) | ||
|
||
return True |
80 changes: 80 additions & 0 deletions
80
rodan-main/code/rodan/jobs/extract_c_clefs/extract_c_clefs.py
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,80 @@ | ||
import argparse | ||
import os | ||
import cv2 | ||
import numpy as np | ||
import xml.etree.ElementTree as ET | ||
from typing import List, Tuple, Optional | ||
|
||
|
||
def crop_images( | ||
image: np.ndarray, coords: List[Tuple[int, int, int, int]] | ||
) -> List[np.ndarray]: | ||
""" | ||
Crop the image based on the coordinates. | ||
Args: | ||
image (np.ndarray): The image to crop. | ||
coords (List[Tuple[int, int, int, int]]): List of tuples (ulx, uly, lrx, lry) for cropping. | ||
Returns: | ||
List[np.ndarray]: List of cropped image regions as numpy arrays. | ||
""" | ||
crops = [] | ||
for ulx, uly, lrx, lry in coords: | ||
crop = image[uly:lry, ulx:lrx] | ||
crops.append(crop) | ||
return crops | ||
|
||
|
||
def save_image(image: np.ndarray, output_path: str) -> None: | ||
""" | ||
Save the image to the specified path. | ||
Args: | ||
image (np.ndarray): The image to save. | ||
output_path (str): The path to save the image. | ||
""" | ||
cv2.imwrite(output_path, image) | ||
print(f"Cropped image saved to {output_path}") | ||
|
||
|
||
def load_image(path: str) -> np.ndarray: | ||
""" | ||
Load an image from the specified path. | ||
Args: | ||
path (str): Path to the image file. | ||
Returns: | ||
np.ndarray: The loaded image. | ||
""" | ||
return cv2.imread(path, cv2.IMREAD_COLOR) | ||
|
||
|
||
def load_xml(path: str) -> ET.Element: | ||
""" | ||
Load an XML file from the specified path. | ||
Args: | ||
path (str): Path to the XML file. | ||
Returns: | ||
ET.Element: The root element of the parsed XML. | ||
""" | ||
tree = ET.parse(path) | ||
return tree.getroot() | ||
|
||
|
||
def extract_coords(xml: ET.Element) -> List[Optional[Tuple[int, int, int, int]]]: | ||
""" | ||
Extract bounding box coordinates from the XML element. | ||
Args: | ||
xml (ET.Element): The root element of the parsed XML. | ||
Returns: | ||
List[Optional[Tuple[int, int, int, int]]]: List of tuples (ulx, uly, lrx, lry) for cropping. | ||
""" | ||
coords_list = [] | ||
for glyph in xml.findall(".//glyph"): | ||
for id_tag in glyph.findall(".//id"): | ||
if id_tag.attrib["name"] == "clef.c": | ||
ulx = int(glyph.attrib["ulx"]) | ||
uly = int(glyph.attrib["uly"]) | ||
ncols = int(glyph.attrib["ncols"]) | ||
nrows = int(glyph.attrib["nrows"]) | ||
lrx = ulx + ncols | ||
lry = uly + nrows | ||
coords_list.append((ulx, uly, lrx, lry)) | ||
return coords_list |