Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
949bc82
Add threshold configuration methods to YOLO and YOLOView classes
john-rocky Aug 6, 2025
dcb0775
Auto-format by https://ultralytics.com/actions
UltralyticsAssistant Aug 6, 2025
de36c24
Merge branch 'main' into feature/add-threshold-configuration
glenn-jocher Aug 7, 2025
7dceba4
Merge branch 'main' into feature/add-threshold-configuration
john-rocky Aug 7, 2025
35dc290
Merge branch 'main' into feature/add-threshold-configuration
john-rocky Aug 7, 2025
b2ae01b
Merge branch 'main' into feature/add-threshold-configuration
glenn-jocher Aug 7, 2025
0f9351f
Auto-format by https://ultralytics.com/actions
UltralyticsAssistant Aug 7, 2025
31131a0
Update format.yml
glenn-jocher Aug 7, 2025
476a228
Merge branch 'main' into feature/add-threshold-configuration
glenn-jocher Aug 7, 2025
a123d2e
Refactor YOLO.swift to simplify predictor creation code
john-rocky Aug 11, 2025
048d3fe
Simplify threshold configuration code
john-rocky Aug 11, 2025
230fc90
Auto-format by https://ultralytics.com/actions
UltralyticsAssistant Aug 11, 2025
33e6b53
Fix ObjectDetector for loops to use results.count instead of hardcode…
john-rocky Aug 11, 2025
fe268b1
Auto-format by https://ultralytics.com/actions
UltralyticsAssistant Aug 11, 2025
2beb450
Merge branch 'main' into feature/add-threshold-configuration
john-rocky Aug 12, 2025
e71fbca
Merge branch 'main' into feature/add-threshold-configuration
john-rocky Aug 26, 2025
f183e86
Merge branch 'main' into feature/add-threshold-configuration
john-rocky Aug 26, 2025
e67a5e2
Remove unnecessary comments in YOLOCamera example
john-rocky Aug 26, 2025
001baf1
Merge branch 'main' into feature/add-threshold-configuration
glenn-jocher Aug 26, 2025
07f310e
Merge branch 'main' into feature/add-threshold-configuration
glenn-jocher Sep 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 57 additions & 1 deletion Sources/YOLO/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,63 @@ class CameraViewController: UIViewController {
}
```

With just a few lines of code, you can integrate real-time, YOLO-based inference into your application’s camera feed. For more advanced use cases, explore the customization options available for these components.
With just a few lines of code, you can integrate real-time, YOLO-based inference into your application's camera feed. For more advanced use cases, explore the customization options available for these components.

### Threshold Configuration

Both `YOLO` and `YOLOView`/`YOLOCamera` classes provide methods to configure detection thresholds:

#### YOLO Class Methods

```swift
// Set individual thresholds
model.setNumItemsThreshold(100) // Maximum number of detections (default: 30)
model.setConfidenceThreshold(0.5) // Confidence threshold 0.0-1.0 (default: 0.25)
model.setIouThreshold(0.6) // IoU threshold for NMS 0.0-1.0 (default: 0.4)

// Or set all thresholds at once
model.setThresholds(numItems: 100, confidence: 0.5, iou: 0.6)

// Get current threshold values
let numItems = model.getNumItemsThreshold() // Returns Int?
let confidence = model.getConfidenceThreshold() // Returns Double?
let iou = model.getIouThreshold() // Returns Double?
```

#### YOLOView/YOLOCamera Methods

```swift
// For UIKit (YOLOView)
yoloView.setNumItemsThreshold(50)
yoloView.setConfidenceThreshold(0.3)
yoloView.setIouThreshold(0.5)

// Or set all at once
yoloView.setThresholds(numItems: 50, confidence: 0.3, iou: 0.5)

// Get current values
let numItems = yoloView.getNumItemsThreshold() // Returns Int
let confidence = yoloView.getConfidenceThreshold() // Returns Double
let iou = yoloView.getIouThreshold() // Returns Double

// For SwiftUI (YOLOCamera) - set during initialization
YOLOCamera(
modelPathOrName: "yolo11n",
task: .detect,
cameraPosition: .back
)
.onAppear {
// Access the underlying view if needed for threshold configuration
// Note: Direct threshold configuration for YOLOCamera may require
// additional implementation or accessing the underlying YOLOView
}
```

**Note:**

- `numItemsThreshold`: Controls the maximum number of detections returned
- `confidenceThreshold`: Filters out detections below this confidence level
- `iouThreshold`: Controls Non-Maximum Suppression overlap threshold

## ⚙️ How to Obtain YOLO Core ML Models

Expand Down
69 changes: 69 additions & 0 deletions Sources/YOLO/YOLO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,75 @@ public class YOLO {
}
}
}

// MARK: - Threshold Configuration Methods

/// Sets the maximum number of detection items to include in results.
/// - Parameter numItems: The maximum number of items to include (default is 30).
public func setNumItemsThreshold(_ numItems: Int) {
if let basePredictor = predictor as? BasePredictor {
basePredictor.setNumItemsThreshold(numItems: numItems)
}
}

/// Gets the current maximum number of detection items.
/// - Returns: The current threshold value, or nil if not applicable.
public func getNumItemsThreshold() -> Int? {
return (predictor as? BasePredictor)?.numItemsThreshold
}

/// Sets the confidence threshold for filtering results.
/// - Parameter confidence: The confidence threshold value (0.0 to 1.0, default is 0.25).
public func setConfidenceThreshold(_ confidence: Double) {
guard confidence >= 0.0 && confidence <= 1.0 else {
print("Warning: Confidence threshold should be between 0.0 and 1.0")
return
}
if let basePredictor = predictor as? BasePredictor {
basePredictor.setConfidenceThreshold(confidence: confidence)
}
}

/// Gets the current confidence threshold.
/// - Returns: The current confidence threshold value, or nil if not applicable.
public func getConfidenceThreshold() -> Double? {
return (predictor as? BasePredictor)?.confidenceThreshold
}

/// Sets the IoU (Intersection over Union) threshold for non-maximum suppression.
/// - Parameter iou: The IoU threshold value (0.0 to 1.0, default is 0.4).
public func setIouThreshold(_ iou: Double) {
guard iou >= 0.0 && iou <= 1.0 else {
print("Warning: IoU threshold should be between 0.0 and 1.0")
return
}
if let basePredictor = predictor as? BasePredictor {
basePredictor.setIouThreshold(iou: iou)
}
}

/// Gets the current IoU threshold.
/// - Returns: The current IoU threshold value, or nil if not applicable.
public func getIouThreshold() -> Double? {
return (predictor as? BasePredictor)?.iouThreshold
}

/// Sets all thresholds at once.
/// - Parameters:
/// - numItems: The maximum number of items to include.
/// - confidence: The confidence threshold value (0.0 to 1.0).
/// - iou: The IoU threshold value (0.0 to 1.0).
public func setThresholds(numItems: Int? = nil, confidence: Double? = nil, iou: Double? = nil) {
if let numItems = numItems {
setNumItemsThreshold(numItems)
}
if let confidence = confidence {
setConfidenceThreshold(confidence)
}
if let iou = iou {
setIouThreshold(iou)
}
}

public func callAsFunction(_ uiImage: UIImage, returnAnnotatedImage: Bool = true) -> YOLOResult {
let ciImage = CIImage(image: uiImage)!
Expand Down
74 changes: 74 additions & 0 deletions Sources/YOLO/YOLOView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,80 @@ public class YOLOView: UIView, VideoCaptureDelegate {
public func resume() {
videoCapture.start()
}

// MARK: - Threshold Configuration Methods

/// Sets the maximum number of detection items to include in results.
/// - Parameter numItems: The maximum number of items to include (default is 30).
public func setNumItemsThreshold(_ numItems: Int) {
sliderNumItems.value = Float(numItems)
if let predictor = videoCapture.predictor as? BasePredictor {
predictor.setNumItemsThreshold(numItems: numItems)
}
}

/// Gets the current maximum number of detection items.
/// - Returns: The current threshold value.
public func getNumItemsThreshold() -> Int {
return Int(sliderNumItems.value)
}

/// Sets the confidence threshold for filtering results.
/// - Parameter confidence: The confidence threshold value (0.0 to 1.0, default is 0.25).
public func setConfidenceThreshold(_ confidence: Double) {
guard confidence >= 0.0 && confidence <= 1.0 else {
print("Warning: Confidence threshold should be between 0.0 and 1.0")
return
}
sliderConf.value = Float(confidence)
labelSliderConf.text = String(format: "%.2f Confidence Threshold", confidence)
if let predictor = videoCapture.predictor as? BasePredictor {
predictor.setConfidenceThreshold(confidence: confidence)
}
}

/// Gets the current confidence threshold.
/// - Returns: The current confidence threshold value.
public func getConfidenceThreshold() -> Double {
return Double(sliderConf.value)
}

/// Sets the IoU (Intersection over Union) threshold for non-maximum suppression.
/// - Parameter iou: The IoU threshold value (0.0 to 1.0, default is 0.4).
public func setIouThreshold(_ iou: Double) {
guard iou >= 0.0 && iou <= 1.0 else {
print("Warning: IoU threshold should be between 0.0 and 1.0")
return
}
sliderIoU.value = Float(iou)
labelSliderIoU.text = String(format: "%.2f IoU Threshold", iou)
if let predictor = videoCapture.predictor as? BasePredictor {
predictor.setIouThreshold(iou: iou)
}
}

/// Gets the current IoU threshold.
/// - Returns: The current IoU threshold value.
public func getIouThreshold() -> Double {
return Double(sliderIoU.value)
}

/// Sets all thresholds at once.
/// - Parameters:
/// - numItems: The maximum number of items to include.
/// - confidence: The confidence threshold value (0.0 to 1.0).
/// - iou: The IoU threshold value (0.0 to 1.0).
public func setThresholds(numItems: Int? = nil, confidence: Double? = nil, iou: Double? = nil) {
if let numItems = numItems {
setNumItemsThreshold(numItems)
}
if let confidence = confidence {
setConfidenceThreshold(confidence)
}
if let iou = iou {
setIouThreshold(iou)
}
}

func setUpBoundingBoxViews() {
// Ensure all bounding box views are initialized up to the maximum allowed.
Expand Down