AutoAnchor improved initialization robustness
diff --git a/utils/autoanchor.py b/utils/autoanchor.py
index 51d4de306ef..a631c21a3b2 100644
--- a/utils/autoanchor.py
+++ b/utils/autoanchor.py
@@ -125,15 +125,17 @@ def print_results(k, verbose=True):
     wh = wh0[(wh0 >= 2.0).any(1)]  # filter > 2 pixels
     # wh = wh * (npr.rand(wh.shape[0], 1) * 0.9 + 0.1)  # multiply by random scale 0-1
 
-    # Kmeans calculation
-    LOGGER.info(f'{PREFIX}Running kmeans for {n} anchors on {len(wh)} points...')
-    s = wh.std(0)  # sigmas for whitening
-    k = kmeans(wh / s, n, iter=30)[0] * s  # points
-    if len(k) != n:  # kmeans may return fewer points than requested if wh is insufficient or too similar
-        LOGGER.warning(f'{PREFIX}WARNING: scipy.cluster.vq.kmeans returned only {len(k)} of {n} requested points')
+    # Kmeans init
+    try:
+        LOGGER.info(f'{PREFIX}Running kmeans for {n} anchors on {len(wh)} points...')
+        assert n <= len(wh)  # apply overdetermined constraint
+        s = wh.std(0)  # sigmas for whitening
+        k = kmeans(wh / s, n, iter=30)[0] * s  # points
+        assert n == len(k)  # kmeans may return fewer points than requested if wh is insufficient or too similar
+    except Exception:
+        LOGGER.warning(f'{PREFIX}WARNING: switching strategies from kmeans to random init')
         k = np.sort(npr.rand(n * 2)).reshape(n, 2) * img_size  # random init
-    wh = torch.tensor(wh, dtype=torch.float32)  # filtered
-    wh0 = torch.tensor(wh0, dtype=torch.float32)  # unfiltered
+    wh, wh0 = (torch.tensor(x, dtype=torch.float32) for x in (wh, wh0))
     k = print_results(k, verbose=False)
 
     # Plot

Resolves https://github.com/ultralytics/yolov5/issues/6809#issuecomment-1054338046

## 🛠️ PR Summary

<sub>Made with ❤️ by [Ultralytics Actions](https://github.com/ultralytics/actions)<sub>

### 🌟 Summary
Refinement of anchor box initialization in YOLOv5's autoanchor utility to handle edge cases.

### 📊 Key Changes
- 🔄 Switch from unconditional k-means initialization to conditional with fallback strategy.
- 🚸 Added assertions to ensure k-means is applied only when the algorithm can determine the requested number of anchors.
- 🔒 In case of an exception (e.g., if k-means fails to return the desired number of anchors), the initialization switches to a random strategy.
- ✂️ Changed how `wh` (width-height tensor) and `wh0` (unfiltered width-height tensor) are created, now using a generator expression for brevity and readability.

### 🎯 Purpose & Impact
- 🛡️ **Purpose:** To improve the reliability of anchor box initialization by adding constraints and fallback mechanisms.
- 🏃‍♂️ **Impact**: Users should experience more consistent performance, especially in cases where k-means clustering previously fell short, resulting in a better object detection model training experience.