Skip to content

Commit

Permalink
feat(jobs): add c clef extraction job
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasmarchd01 committed Jun 28, 2024
1 parent f1b0042 commit 8013bd4
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 0 deletions.
4 changes: 4 additions & 0 deletions rodan-main/code/rodan/jobs/extract_c_clefs/__init__.py
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")
67 changes: 67 additions & 0 deletions rodan-main/code/rodan/jobs/extract_c_clefs/base.py
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 rodan-main/code/rodan/jobs/extract_c_clefs/extract_c_clefs.py
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

0 comments on commit 8013bd4

Please sign in to comment.