ultralytics 8.3.69 New Results to_sql() method for SQL format (#18921)

Signed-off-by: Glenn Jocher <glenn.jocher@ultralytics.com>
Co-authored-by: UltralyticsAssistant <web@ultralytics.com>
Co-authored-by: Glenn Jocher <glenn.jocher@ultralytics.com>
This commit is contained in:
Muhammad Rizwan Munawar 2025-01-29 03:49:30 +05:00 committed by GitHub
parent 813511a232
commit 748c380fc5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 84 additions and 7 deletions

View file

@ -1,6 +1,6 @@
# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
__version__ = "8.3.68"
__version__ = "8.3.69"
import os

View file

@ -937,6 +937,75 @@ class Results(SimpleClass):
return json.dumps(self.summary(normalize=normalize, decimals=decimals), indent=2)
def to_sql(self, table_name="results", normalize=False, decimals=5, db_path="results.db"):
"""
Converts detection results to an SQL-compatible format.
This method serializes the detection results into a format compatible with SQL databases.
It includes information about detected objects such as bounding boxes, class names, confidence scores,
and optionally segmentation masks, keypoints or oriented bounding boxes.
Args:
table_name (str): Name of the SQL table where the data will be inserted. Defaults to "detection_results".
normalize (bool): Whether to normalize the bounding box coordinates by the image dimensions.
If True, coordinates will be returned as float values between 0 and 1. Defaults to False.
decimals (int): Number of decimal places to round the bounding boxes values to. Defaults to 5.
db_path (str): Path to the SQLite database file. Defaults to "results.db".
Examples:
>>> results = model("path/to/image.jpg")
>>> results[0].to_sql()
>>> print("SQL data written successfully.")
"""
import json
import sqlite3
# Convert results to a list of dictionaries
data = self.summary(normalize=normalize, decimals=decimals)
if not data:
LOGGER.warning("⚠️ No results to save to SQL. Results dict is empty")
return
# Connect to the SQLite database
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Create table if it doesn't exist
columns = (
"id INTEGER PRIMARY KEY AUTOINCREMENT, class_name TEXT, confidence REAL, "
"box TEXT, masks TEXT, kpts TEXT, obb TEXT"
)
cursor.execute(f"CREATE TABLE IF NOT EXISTS {table_name} ({columns})")
# Insert data into the table
for i, item in enumerate(data):
detect, obb = None, None # necessary to reinit these variables inside for loop to avoid duplication
class_name = item.get("name")
box = item.get("box", {})
# Serialize the box as JSON for 'detect' and 'obb' based on key presence
if all(key in box for key in ["x1", "y1", "x2", "y2"]) and not any(key in box for key in ["x3", "x4"]):
detect = json.dumps(box)
if all(key in box for key in ["x1", "y1", "x2", "y2", "x3", "x4"]):
obb = json.dumps(box)
cursor.execute(
f"INSERT INTO {table_name} (class_name, confidence, box, masks, kpts, obb) VALUES (?, ?, ?, ?, ?, ?)",
(
class_name,
item.get("confidence"),
detect,
json.dumps(item.get("segments", {}).get("x", [])),
json.dumps(item.get("keypoints", {}).get("x", [])),
obb,
),
)
# Commit and close the connection
conn.commit()
conn.close()
LOGGER.info(f"✅ Detection results successfully written to SQL table '{table_name}' in database '{db_path}'.")
class Boxes(BaseTensor):
"""

View file

@ -173,10 +173,10 @@ def benchmark(
df = pd.DataFrame(y, columns=["Format", "Status❔", "Size (MB)", key, "Inference time (ms/im)", "FPS"])
name = model.model_name
s = f"\nBenchmarks complete for {name} on {data} at imgsz={imgsz} ({time.time() - t0:.2f}s)\n{df.fillna('-')}\n"
dt = time.time() - t0
legend = "Benchmarks legend: - ✅ Success - ❎ Export passed but validation failed - ❌️ Export failed"
s = f"\nBenchmarks complete for {name} on {data} at imgsz={imgsz} ({dt:.2f}s)\n{legend}\n{df.fillna('-')}\n"
LOGGER.info(s)
LOGGER.info("Status legends:")
LOGGER.info("✅ - Benchmark passed | ❎ - Export passed but validation failed | ❌️ - Export failed")
with open("benchmarks.log", "a", errors="ignore", encoding="utf-8") as f:
f.write(s)