-
-
Notifications
You must be signed in to change notification settings - Fork 16.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug in the process_batch function in val.py #11300
Comments
@kimberlykang thank you for your report and valuable contribution to YOLOv5. You are correct that the matches are sorted only by IoU, and then filtered by label. While it is expected that the label filtering would remove low IoU matches, there may be cases where the same label is used for detections with different IoU scores. Therefore, we will modify the process_batch function to first sort by IoU score, then by label, to ensure that only the highest IoU detection for each label is kept. We appreciate your willingness to submit a PR and will review it promptly. Please let us know if you have any further questions or suggestions. |
@glenn-jocher I think what the process_batch function need is another sort by IoU. matches = matches[matches[:, 2].argsort()[::-1]] # line 1
matches = matches[np.unique(matches[:, 1], return_index=True)[1]] # line 2
# matches = matches[matches[:, 2].argsort()[::-1]] # line 3
matches = matches[np.unique(matches[:, 0], return_index=True)[1]] # line 4 From the above code in line 1, In line 2, ar = np.asanyarray(ar).flatten()
optional_indices = return_index or return_inverse
if optional_indices:
perm = ar.argsort(kind='mergesort' if return_index else 'quicksort')
aux = ar[perm] Finally Due to this reason above, I think what it needs is to just uncomment the line 3 so that after |
👋 Hello there! We wanted to give you a friendly reminder that this issue has not had any recent activity and may be closed soon, but don't worry - you can always reopen it if needed. If you still have any questions or concerns, please feel free to let us know how we can help. For additional resources and information, please see the links below:
Feel free to inform us of any other issues you discover or feature requests that come to mind in the future. Pull Requests (PRs) are also always welcomed! Thank you for your contributions to YOLO 🚀 and Vision AI ⭐ |
@kimberlykang Thank you for the detailed explanation. Your insights are valuable. We have taken note of your suggestion, and we agree that adding another sort by IoU after the |
@glenn-jocher matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 1], return_index=True)[1]]
matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 0], return_index=True)[1]] However! In the matches = matches[iou[matches[:, 0], matches[:, 1]].argsort()[::-1]]
matches = matches[np.unique(matches[:, 1], return_index=True)[1]]
matches = matches[np.unique(matches[:, 0], return_index=True)[1]] Is this an oversight on your part? |
Hello! Thanks for pointing this out. It seems like the |
Hello @glenn-jocher! I have a similar question to @Love-syntacticSugar In the YOLOv5 source code, within matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 1], return_index=True)[1]]
matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 0], return_index=True)[1]] However, in matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 1], return_index=True)[1]]
# matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 0], return_index=True)[1]] If these two parts should be keep the same? |
Hello @Tim-Agro, Thank you for your detailed observation and for bringing this to our attention! To address your question, the Here's the corrected code for matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 1], return_index=True)[1]]
matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 0], return_index=True)[1]] This ensures that after filtering unique detection indices, the matches are sorted again by IoU before filtering unique label indices, maintaining the highest IoU detections. If you haven't already, please verify that this issue persists with the latest versions of If you encounter any further issues or have additional questions, please don't hesitate to ask. Your contributions and insights are invaluable to the YOLO community and the Ultralytics team! 😊 |
Hi @glenn-jocher, thank you for your comments. Upon thoroughly reviewing the purpose of these four lines and considering the answer @Terry-Zheng from issue #12543, I discovered that line 3 should be commented out. This is because a high IOU does not indicate a high confidence value.
Therefore, to ensure consistency in between val.py and metrics.py, line 3 should be commented out in both files. matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 1], return_index=True)[1]]
# matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 0], return_index=True)[1]] |
Hi @Tim-Agro, Thank you for your detailed analysis and for referencing the discussion from issue #12543. Your insights are very much appreciated! You are correct that a high IoU does not necessarily correlate with high confidence. The intention behind commenting out the third line is to ensure that detections are matched based on confidence rather than IoU after the initial sorting and unique operations. This approach aligns with the logic that detections are sorted in descending order of confidence after Non-Maximum Suppression (NMS), ensuring that each ground truth box selects the detection with the highest confidence. To maintain consistency between Here is the consistent code snippet for both files: matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 1], return_index=True)[1]]
# matches = matches[matches[:, 2].argsort()[::-1]]
matches = matches[np.unique(matches[:, 0], return_index=True)[1]] We encourage you to verify that this issue persists with the latest versions of Thank you once again for your valuable feedback and for helping improve YOLOv5. If you have any further questions or suggestions, please feel free to share. Your contributions are invaluable to the YOLO community and the Ultralytics team! 😊 |
Search before asking
YOLOv5 Component
No response
Bug
In the process_batch function, detections are filtered by IoU and detected class. This filtered detections are named
matches
and the following procedures are performedmatches
by IoU.The expected outcome of the above is to leave unique detection results with high IoU. However in some cases, results with lower IoU are not filtered out and become the final result, because of the lack of sort between 2 and 3
There is not sort because
matches
are already filtered by IoU threshold and the calculation of AP does not care about IoU?Environment
No response
Minimal Reproducible Example
Additional
No response
Are you willing to submit a PR?
The text was updated successfully, but these errors were encountered: