155 lines
6.2 KiB
Python
155 lines
6.2 KiB
Python
|
import os
|
||
|
import glob
|
||
|
import json
|
||
|
import re
|
||
|
|
||
|
|
||
|
class SaveData:
|
||
|
def search_in_folder(self, folder, file_name = "MPENN_image_data_information.json"):
|
||
|
"""
|
||
|
Searches for a specific file named "MPENN_image_data_information.json" within a given folder.
|
||
|
|
||
|
:param folder: The folder path to search in.
|
||
|
:return: A list containing the path to the "MPENN_image_data_information.json" file if found, empty otherwise.
|
||
|
"""
|
||
|
# Validate input parameters
|
||
|
if not os.path.isdir(folder):
|
||
|
raise ValueError("The provided folder path does not exist or is not a directory.")
|
||
|
|
||
|
# Construct the full search path
|
||
|
search_path = os.path.join(folder, file_name)
|
||
|
|
||
|
# Use glob.glob to find the specified file
|
||
|
matching_file = glob.glob(search_path)
|
||
|
if len(matching_file) == 0:
|
||
|
matching_file = self.create(folder)
|
||
|
return matching_file
|
||
|
|
||
|
def create(self, folder):
|
||
|
"""
|
||
|
Create a .json file in the given folder path.
|
||
|
|
||
|
:param folder: Path of the folder where the .json file will be created.
|
||
|
"""
|
||
|
# Validating folder path
|
||
|
if not isinstance(folder, str) or not folder:
|
||
|
raise ValueError("Folder path must be a non-empty string.")
|
||
|
|
||
|
# Ensuring the folder exists
|
||
|
os.makedirs(folder, exist_ok=True)
|
||
|
|
||
|
# Generating a JSON file name with a placeholder approach
|
||
|
file_name = "MPENN_image_data_information.json"
|
||
|
file_path = os.path.join(folder, file_name)
|
||
|
|
||
|
# Creating and writing to the JSON file
|
||
|
try:
|
||
|
with open(file_path, 'w') as json_file:
|
||
|
json.dump({}, json_file) # Creating an empty JSON object
|
||
|
return file_path
|
||
|
except OSError as e:
|
||
|
raise OSError(f"Failed to create file in {folder}. Error: {e}")
|
||
|
|
||
|
def append_to_json_file(self, image_path, resolution, labeled, rectangles, filename):
|
||
|
"""
|
||
|
Appends a new record to an existing .json file or creates a file if it doesn't exist.
|
||
|
|
||
|
:param image_path: A string representing the path to the image.
|
||
|
:param resolution: A list or tuple with two integers representing the image's resolution.
|
||
|
:param labeled: A boolean indicating if the image is labeled.
|
||
|
:param rectangles: A list of lists, where each inner list represents rectangle information.
|
||
|
:param filename: A string representing the name of the output .json file.
|
||
|
"""
|
||
|
rectangles = self.calculate_missing_coordinates_for_each(rectangles)
|
||
|
# New entry to add
|
||
|
|
||
|
|
||
|
new_entry = {
|
||
|
"Image_path": image_path,
|
||
|
"resolution": resolution,
|
||
|
"labeled": str(labeled),
|
||
|
"rectangle": rectangles
|
||
|
}
|
||
|
|
||
|
try:
|
||
|
# Try to read the existing file
|
||
|
with open(filename, 'r') as file:
|
||
|
# Load the JSON data from the file
|
||
|
data = json.load(file)
|
||
|
# Ensure the data is a list to hold multiple entries
|
||
|
if not isinstance(data, list):
|
||
|
data = [data] # Convert to list if it's a single dictionary
|
||
|
except FileNotFoundError:
|
||
|
# If the file doesn't exist, start a new list
|
||
|
data = []
|
||
|
|
||
|
# Append the new entry
|
||
|
data.append(new_entry)
|
||
|
|
||
|
# Write the updated list back to the file
|
||
|
with open(filename, 'w') as file:
|
||
|
json.dump(data, file, indent=4)
|
||
|
|
||
|
def calculate_missing_coordinates_for_each(self, rectangles):
|
||
|
"""
|
||
|
Calculate missing coordinates for each rectangle set in
|
||
|
the provided list of rectangles, considering the new format wherein
|
||
|
coordinates are provided as a single tuple.
|
||
|
|
||
|
Args:
|
||
|
- rectangles (List[List]): Input list containing rectangle identifiers, their coordinates in a single tuple, and other information.
|
||
|
Example: [[id, (top_left_x, top_left_y, bottom_right_x, bottom_right_y), ...]]
|
||
|
|
||
|
Returns:
|
||
|
- List[List]: Updated list with added missing coordinate lists for each rectangle.
|
||
|
"""
|
||
|
updated_rectangles = []
|
||
|
|
||
|
for rectangle in rectangles:
|
||
|
# Assuming the structure is [rectangle_id, (top_left_x, top_left_y, bottom_right_x, bottom_right_y), other_info...]
|
||
|
rectangle_id, coords, *others = rectangle
|
||
|
|
||
|
# Unpack coords
|
||
|
top_left_x, top_left_y, bottom_right_x, bottom_right_y = coords
|
||
|
|
||
|
# Calculate missing coordinates: top right (x2, y1) and bottom left (x1, y2)
|
||
|
top_right = (bottom_right_x, top_left_y)
|
||
|
bottom_left = (top_left_x, bottom_right_y)
|
||
|
|
||
|
# Ensure the order is [rectangle_id, [top_left], [top_right], [bottom_right], [bottom_left], other_info...]
|
||
|
top_left = (top_left_x, top_left_y)
|
||
|
bottom_right = (bottom_right_x, bottom_right_y)
|
||
|
|
||
|
updated_rectangle = [rectangle_id, top_left, top_right, bottom_right, bottom_left] + others
|
||
|
updated_rectangles.append(updated_rectangle)
|
||
|
|
||
|
return updated_rectangles
|
||
|
|
||
|
def find_highest_image_number(self, json_data):
|
||
|
"""
|
||
|
Search through the provided JSON data for the highest number in the "Image_path".
|
||
|
|
||
|
Args:
|
||
|
- j_data (List[Dict]): The input JSON data loaded into a Python data structure.
|
||
|
|
||
|
Returns:
|
||
|
- int: The highest number found in the "Image_path"; returns -1 if no numbers are found.
|
||
|
"""
|
||
|
highest_number = -1
|
||
|
with open(json_data, 'r') as file:
|
||
|
# Load the JSON data from the file
|
||
|
j_data = json.load(file)
|
||
|
pattern = re.compile(r'\d+')
|
||
|
|
||
|
for item in j_data:
|
||
|
if "Image_path" in item:
|
||
|
# Extract numbers from "Image_path"
|
||
|
numbers = pattern.findall(item["Image_path"])
|
||
|
for number in numbers:
|
||
|
# Convert found numbers to integers and track the highest
|
||
|
current_number = int(number)
|
||
|
if current_number > highest_number:
|
||
|
highest_number = current_number
|
||
|
highest_number+= 1
|
||
|
return highest_number
|