i have folder has classes.txt images.jpg images.tx...

تم الإنشاء في: ٥ أغسطس ٢٠٢٦

تمت الإجابة باستخدام GPT-5.6 Thinking بواسطة Chat01

سؤال

i have folder has classes.txt images.jpg images.txt YOLO format of segmentation
make a python script has hardcoded input folder path and output folder path to convert segmentation format to yolo detection format
here sample of data 3 0.719531 0.855556 0.718750 0.855556 0.717969 0.855556 0.717969 0.854167 0.717187 0.854167 0.716406 0.854167 0.715625 0.854167 0.714844 0.854167 0.714063 0.854167 0.713281 0.854167 0.712500 0.854167 0.711719 0.854167 0.710938 0.855556 0.710156 0.855556 0.709375 0.855556 0.708594 0.856944 0.707812 0.856944 0.707812 0.858333 0.707031 0.858333 0.707031 0.859722 0.707031 0.861111 0.706250 0.861111 0.706250 0.862500 0.706250 0.863889 0.706250 0.865278 0.706250 0.866667 0.706250 0.868056 0.706250 0.869444 0.706250 0.870833 0.706250 0.872222 0.707031 0.872222 0.707031 0.873611 0.707031 0.875000 0.707812 0.875000 0.707812 0.876389 0.707812 0.877778 0.708594 0.877778 0.708594 0.879167 0.709375 0.880556 0.710156 0.881944 0.710938 0.881944 0.710938 0.883333 0.711719 0.883333 0.712500 0.883333 0.713281 0.883333 0.714063 0.883333 0.714844 0.883333 0.715625 0.883333 0.716406 0.883333 0.717187 0.883333 0.717969 0.883333 0.718750 0.883333 0.719531 0.883333 0.720313 0.883333 0.721094 0.883333 0.721094 0.881944 0.721875 0.881944 0.721875 0.880556 0.722656 0.880556 0.722656 0.879167 0.723437 0.877778 0.723437 0.876389 0.723437 0.875000 0.723437 0.873611 0.724219 0.873611 0.724219 0.872222 0.724219 0.870833 0.723437 0.870833 0.723437 0.869444 0.723437 0.868056 0.722656 0.868056 0.722656 0.866667 0.722656 0.865278 0.722656 0.863889 0.721875 0.863889 0.721875 0.862500 0.721875 0.861111 0.721875 0.859722 0.721875 0.858333 0.721094 0.858333 0.721094 0.856944 0.720313 0.856944 0.719531 0.855556 0.719531 0.854167 0.719531 0.855556

الفكرة

Writing conversion script

I’m providing a reusable Python script with configurable input and output folders. It will copy images, convert polygon labels into normalized YOLO bounding boxes, preserve class IDs, and handle malformed label lines safely.

Wrote conversion script

Worked for 11s

الإجابة

The script below converts each YOLO segmentation polygon:

text
class_id x1 y1 x2 y2 x3 y3 ...

into a YOLO detection bounding box:

text
class_id x_center y_center width height

Coordinates remain normalized, so image dimensions are not required.

python
from pathlib import Path import shutil # ============================================================ # HARDCODED PATHS # ============================================================ INPUT_FOLDER = Path(r"C:\datasets\segmentation_dataset") OUTPUT_FOLDER = Path(r"C:\datasets\detection_dataset") # Copy image files into the output folder. COPY_IMAGES = True IMAGE_EXTENSIONS = { ".jpg", ".jpeg", ".png", ".bmp", ".tif", ".tiff", ".webp", } def segmentation_line_to_detection(line: str) -> str | None: """ Convert one YOLO segmentation annotation line into one YOLO detection annotation line. Input: class_id x1 y1 x2 y2 x3 y3 ... Output: class_id x_center y_center width height """ parts = line.strip().split() if not parts: return None class_id = parts[0] coordinate_values = parts[1:] # A polygon must contain at least 3 points: 6 coordinate values. if len(coordinate_values) < 6: raise ValueError("Polygon contains fewer than 3 points.") if len(coordinate_values) % 2 != 0: raise ValueError("Polygon has an odd number of coordinate values.") try: coordinates = [float(value) for value in coordinate_values] except ValueError as error: raise ValueError("Polygon contains a non-numeric coordinate.") from error x_values = coordinates[0::2] y_values = coordinates[1::2] x_min = min(x_values) x_max = max(x_values) y_min = min(y_values) y_max = max(y_values) # Keep the resulting box within YOLO's normalized range. x_min = max(0.0, min(1.0, x_min)) x_max = max(0.0, min(1.0, x_max)) y_min = max(0.0, min(1.0, y_min)) y_max = max(0.0, min(1.0, y_max)) width = x_max - x_min height = y_max - y_min if width <= 0 or height <= 0: raise ValueError("Polygon produces a zero-size bounding box.") x_center = (x_min + x_max) / 2.0 y_center = (y_min + y_max) / 2.0 return ( f"{class_id} " f"{x_center:.6f} " f"{y_center:.6f} " f"{width:.6f} " f"{height:.6f}" ) def convert_label_file(input_file: Path, output_file: Path) -> tuple[int, int]: """Convert every valid segmentation annotation in one label file.""" converted_lines = [] converted_count = 0 skipped_count = 0 with input_file.open("r", encoding="utf-8") as file: for line_number, line in enumerate(file, start=1): if not line.strip(): continue try: converted_line = segmentation_line_to_detection(line) if converted_line is not None: converted_lines.append(converted_line) converted_count += 1 except ValueError as error: skipped_count += 1 print( f"Warning: skipped {input_file}, line {line_number}: " f"{error}" ) output_file.parent.mkdir(parents=True, exist_ok=True) with output_file.open("w", encoding="utf-8") as file: if converted_lines: file.write("\n".join(converted_lines) + "\n") return converted_count, skipped_count def main() -> None: if not INPUT_FOLDER.exists(): raise FileNotFoundError( f"Input folder does not exist: {INPUT_FOLDER}" ) if INPUT_FOLDER.resolve() == OUTPUT_FOLDER.resolve(): raise ValueError("Input and output folders must be different.") OUTPUT_FOLDER.mkdir(parents=True, exist_ok=True) converted_files = 0 converted_objects = 0 skipped_objects = 0 copied_images = 0 for input_file in INPUT_FOLDER.rglob("*"): if not input_file.is_file(): continue relative_path = input_file.relative_to(INPUT_FOLDER) output_file = OUTPUT_FOLDER / relative_path # Copy classes.txt without modifying it. if input_file.name.lower() == "classes.txt": output_file.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(input_file, output_file) print(f"Copied classes: {relative_path}") continue # Convert all other .txt files as YOLO label files. if input_file.suffix.lower() == ".txt": converted, skipped = convert_label_file( input_file, output_file, ) converted_files += 1 converted_objects += converted skipped_objects += skipped print( f"Converted: {relative_path} " f"({converted} objects, {skipped} skipped)" ) continue # Copy corresponding images while preserving subfolders. if COPY_IMAGES and input_file.suffix.lower() in IMAGE_EXTENSIONS: output_file.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(input_file, output_file) copied_images += 1 print(f"Copied image: {relative_path}") print("\nConversion complete.") print(f"Label files converted: {converted_files}") print(f"Objects converted: {converted_objects}") print(f"Objects skipped: {skipped_objects}") print(f"Images copied: {copied_images}") print(f"Output folder: {OUTPUT_FOLDER}") if __name__ == "__main__": main()

For the polygon in your example, the converted detection annotation is approximately:

text
3 0.715235 0.868750 0.017969 0.029166

Change only INPUT_FOLDER and OUTPUT_FOLDER at the top, then run:

bash
python convert_segmentation_to_detection.py

مشاركة هذا السؤال والجواب