Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
UltralyticsAssistant committed Aug 11, 2024
1 parent ba861d8 commit f7905ee
Show file tree
Hide file tree
Showing 9 changed files with 1,486 additions and 1,427 deletions.
80 changes: 42 additions & 38 deletions YOLO/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,57 +17,61 @@ import UIKit
/// The main application delegate, handling global app behavior and configuration.
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var window: UIWindow?

/// Called when the app finishes launching, used here to set global app settings.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Disable screen dimming and auto-lock to keep the app active during long operations.
UIApplication.shared.isIdleTimerDisabled = true
/// Called when the app finishes launching, used here to set global app settings.
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Disable screen dimming and auto-lock to keep the app active during long operations.
UIApplication.shared.isIdleTimerDisabled = true

// Enable battery monitoring to allow the app to adapt its behavior based on battery level.
UIDevice.current.isBatteryMonitoringEnabled = true
// Enable battery monitoring to allow the app to adapt its behavior based on battery level.
UIDevice.current.isBatteryMonitoringEnabled = true

// Store the app version and build version in UserDefaults for easy access elsewhere in the app.
if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String,
let buildVersion = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
UserDefaults.standard.set("\(appVersion) (\(buildVersion))", forKey: "app_version")
}
// Store the app version and build version in UserDefaults for easy access elsewhere in the app.
if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String,
let buildVersion = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
{
UserDefaults.standard.set("\(appVersion) (\(buildVersion))", forKey: "app_version")
}

// Store the device's UUID in UserDefaults for identification purposes.
if let uuid = UIDevice.current.identifierForVendor?.uuidString {
UserDefaults.standard.set(uuid, forKey: "uuid")
}
// Store the device's UUID in UserDefaults for identification purposes.
if let uuid = UIDevice.current.identifierForVendor?.uuidString {
UserDefaults.standard.set(uuid, forKey: "uuid")
}

// Ensure UserDefaults changes are immediately saved.
UserDefaults.standard.synchronize()
// Ensure UserDefaults changes are immediately saved.
UserDefaults.standard.synchronize()

return true
}
func applicationDidBecomeActive(_ application: UIApplication) {
NotificationCenter.default.post(name: .settingsChanged, object: nil)
}
return true
}

func applicationDidBecomeActive(_ application: UIApplication) {
NotificationCenter.default.post(name: .settingsChanged, object: nil)
}
}

extension Notification.Name {
static let settingsChanged = Notification.Name("settingsChanged")
static let settingsChanged = Notification.Name("settingsChanged")
}

/// Extension to CALayer to add functionality for generating screenshots of any layer.
extension CALayer {
var screenShot: UIImage? {
// Begin a new image context, using the device's screen scale to ensure high-resolution output.
UIGraphicsBeginImageContextWithOptions(frame.size, false, UIScreen.main.scale)
defer {
UIGraphicsEndImageContext()
} // Ensure the image context is cleaned up correctly.
var screenShot: UIImage? {
// Begin a new image context, using the device's screen scale to ensure high-resolution output.
UIGraphicsBeginImageContextWithOptions(frame.size, false, UIScreen.main.scale)
defer {
UIGraphicsEndImageContext()
} // Ensure the image context is cleaned up correctly.

if let context = UIGraphicsGetCurrentContext() {
// Render the layer into the current context.
render(in: context)
// Attempt to generate an image from the current context.
return UIGraphicsGetImageFromCurrentImageContext()
}
return nil // Return nil if the operation fails.
if let context = UIGraphicsGetCurrentContext() {
// Render the layer into the current context.
render(in: context)
// Attempt to generate an image from the current context.
return UIGraphicsGetImageFromCurrentImageContext()
}
return nil // Return nil if the operation fails.
}
}
153 changes: 78 additions & 75 deletions YOLO/Utilities/BoundingBoxView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,92 +14,95 @@ import UIKit

/// Manages the visualization of bounding boxes and associated labels for object detection results.
class BoundingBoxView {
/// The layer that draws the bounding box around a detected object.
let shapeLayer: CAShapeLayer
/// The layer that draws the bounding box around a detected object.
let shapeLayer: CAShapeLayer

/// The layer that displays the label and confidence score for the detected object.
let textLayer: CATextLayer
/// The layer that displays the label and confidence score for the detected object.
let textLayer: CATextLayer

/// The layer that displays the inner text within the bounding box.
let innerTextLayer: CATextLayer
/// The layer that displays the inner text within the bounding box.
let innerTextLayer: CATextLayer

/// Initializes a new BoundingBoxView with configured shape and text layers.
init() {
shapeLayer = CAShapeLayer()
shapeLayer.fillColor = UIColor.clear.cgColor // No fill to only show the bounding outline
shapeLayer.lineWidth = 4 // Set the stroke line width
shapeLayer.isHidden = true // Initially hidden; shown when a detection occurs
/// Initializes a new BoundingBoxView with configured shape and text layers.
init() {
shapeLayer = CAShapeLayer()
shapeLayer.fillColor = UIColor.clear.cgColor // No fill to only show the bounding outline
shapeLayer.lineWidth = 4 // Set the stroke line width
shapeLayer.isHidden = true // Initially hidden; shown when a detection occurs

textLayer = CATextLayer()
textLayer.isHidden = true // Initially hidden; shown with label when a detection occurs
textLayer.contentsScale = UIScreen.main.scale // Ensure the text is sharp on retina displays
textLayer.fontSize = 14 // Set font size for the label text
textLayer.font = UIFont(name: "Avenir", size: textLayer.fontSize) // Use Avenir font for labels
textLayer.alignmentMode = .center // Center-align the text within the layer
textLayer = CATextLayer()
textLayer.isHidden = true // Initially hidden; shown with label when a detection occurs
textLayer.contentsScale = UIScreen.main.scale // Ensure the text is sharp on retina displays
textLayer.fontSize = 14 // Set font size for the label text
textLayer.font = UIFont(name: "Avenir", size: textLayer.fontSize) // Use Avenir font for labels
textLayer.alignmentMode = .center // Center-align the text within the layer

innerTextLayer = CATextLayer()
innerTextLayer.isHidden = true // Initially hidden; shown with label when a detection occurs
innerTextLayer.contentsScale = UIScreen.main.scale // Ensure the text is sharp on retina displays
innerTextLayer.fontSize = 12 // Set font size for the inner text
innerTextLayer.font = UIFont(name: "Avenir", size: innerTextLayer.fontSize) // Use Avenir font for inner text
innerTextLayer.alignmentMode = .left // Left-align the text within the layer
innerTextLayer.isWrapped = true // Wrap the text to fit within the layer
}

/// Adds the bounding box, text, and inner text layers to a specified parent layer.
/// - Parameter parent: The CALayer to which the bounding box, text, and inner text layers will be added.
func addToLayer(_ parent: CALayer) {
parent.addSublayer(shapeLayer)
parent.addSublayer(textLayer)
parent.addSublayer(innerTextLayer)
}
innerTextLayer = CATextLayer()
innerTextLayer.isHidden = true // Initially hidden; shown with label when a detection occurs
innerTextLayer.contentsScale = UIScreen.main.scale // Ensure the text is sharp on retina displays
innerTextLayer.fontSize = 12 // Set font size for the inner text
innerTextLayer.font = UIFont(name: "Avenir", size: innerTextLayer.fontSize) // Use Avenir font for inner text
innerTextLayer.alignmentMode = .left // Left-align the text within the layer
innerTextLayer.isWrapped = true // Wrap the text to fit within the layer
}

/// Updates the bounding box, label, and inner text to be visible with specified properties.
/// - Parameters:
/// - frame: The CGRect frame defining the bounding box's size and position.
/// - label: The text label to display (e.g., object class and confidence).
/// - color: The color of the bounding box stroke and label background.
/// - alpha: The opacity level for the bounding box stroke and label background.
/// - innerTexts: The text to display inside the bounding box.
func show(frame: CGRect, label: String, color: UIColor, alpha: CGFloat, innerTexts: String) {
CATransaction.setDisableActions(true) // Disable implicit animations
/// Adds the bounding box, text, and inner text layers to a specified parent layer.
/// - Parameter parent: The CALayer to which the bounding box, text, and inner text layers will be added.
func addToLayer(_ parent: CALayer) {
parent.addSublayer(shapeLayer)
parent.addSublayer(textLayer)
parent.addSublayer(innerTextLayer)
}

let path = UIBezierPath(roundedRect: frame, cornerRadius: 6.0) // Rounded rectangle for the bounding box
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = color.withAlphaComponent(alpha).cgColor // Apply color and alpha to the stroke
shapeLayer.isHidden = false // Make the shape layer visible
/// Updates the bounding box, label, and inner text to be visible with specified properties.
/// - Parameters:
/// - frame: The CGRect frame defining the bounding box's size and position.
/// - label: The text label to display (e.g., object class and confidence).
/// - color: The color of the bounding box stroke and label background.
/// - alpha: The opacity level for the bounding box stroke and label background.
/// - innerTexts: The text to display inside the bounding box.
func show(frame: CGRect, label: String, color: UIColor, alpha: CGFloat, innerTexts: String) {
CATransaction.setDisableActions(true) // Disable implicit animations

textLayer.string = label // Set the label text
textLayer.backgroundColor = color.withAlphaComponent(alpha).cgColor // Apply color and alpha to the background
textLayer.isHidden = false // Make the text layer visible
textLayer.foregroundColor = UIColor.white.withAlphaComponent(alpha).cgColor // Set text color
let path = UIBezierPath(roundedRect: frame, cornerRadius: 6.0) // Rounded rectangle for the bounding box
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = color.withAlphaComponent(alpha).cgColor // Apply color and alpha to the stroke
shapeLayer.isHidden = false // Make the shape layer visible

// Calculate the text size and position based on the label content
let attributes = [NSAttributedString.Key.font: textLayer.font as Any]
let textRect = label.boundingRect(with: CGSize(width: 400, height: 100),
options: .truncatesLastVisibleLine,
attributes: attributes, context: nil)
let textSize = CGSize(width: textRect.width + 12, height: textRect.height) // Add padding to the text size
let textOrigin = CGPoint(x: frame.origin.x - 2, y: frame.origin.y - textSize.height - 2) // Position above the bounding box
textLayer.frame = CGRect(origin: textOrigin, size: textSize) // Set the text layer frame
textLayer.string = label // Set the label text
textLayer.backgroundColor = color.withAlphaComponent(alpha).cgColor // Apply color and alpha to the background
textLayer.isHidden = false // Make the text layer visible
textLayer.foregroundColor = UIColor.white.withAlphaComponent(alpha).cgColor // Set text color

if !innerTexts.isEmpty {
innerTextLayer.string = innerTexts // Set the inner text
innerTextLayer.backgroundColor = UIColor.clear.cgColor // No background color
innerTextLayer.isHidden = false // Make the inner text layer visible
innerTextLayer.foregroundColor = UIColor.red.cgColor // Set text color
innerTextLayer.frame = CGRect(x: frame.origin.x + 4, y: frame.origin.y + 4, width: frame.width / 2 - 8, height: frame.height - 8)
// Set the inner text layer frame
} else {
innerTextLayer.isHidden = true // Hide the inner text layer if innerTexts is empty
}
// Calculate the text size and position based on the label content
let attributes = [NSAttributedString.Key.font: textLayer.font as Any]
let textRect = label.boundingRect(
with: CGSize(width: 400, height: 100),
options: .truncatesLastVisibleLine,
attributes: attributes, context: nil)
let textSize = CGSize(width: textRect.width + 12, height: textRect.height) // Add padding to the text size
let textOrigin = CGPoint(x: frame.origin.x - 2, y: frame.origin.y - textSize.height - 2) // Position above the bounding box
textLayer.frame = CGRect(origin: textOrigin, size: textSize) // Set the text layer frame

if !innerTexts.isEmpty {
innerTextLayer.string = innerTexts // Set the inner text
innerTextLayer.backgroundColor = UIColor.clear.cgColor // No background color
innerTextLayer.isHidden = false // Make the inner text layer visible
innerTextLayer.foregroundColor = UIColor.red.cgColor // Set text color
innerTextLayer.frame = CGRect(
x: frame.origin.x + 4, y: frame.origin.y + 4, width: frame.width / 2 - 8,
height: frame.height - 8)
// Set the inner text layer frame
} else {
innerTextLayer.isHidden = true // Hide the inner text layer if innerTexts is empty
}

/// Hides the bounding box, text, and inner text layers.
func hide() {
shapeLayer.isHidden = true
textLayer.isHidden = true
innerTextLayer.isHidden = true
}
}

/// Hides the bounding box, text, and inner text layers.
func hide() {
shapeLayer.isHidden = true
textLayer.isHidden = true
innerTextLayer.isHidden = true
}
}
Loading

0 comments on commit f7905ee

Please sign in to comment.