bounding box annotation for bronchoscopy videos - #21
Conversation
…ee-text labeled bounding boxes, per-box color coding, color-preserving copy-to-next-frame, multi-frame save, duplicate-label prevention, CSV exporter, and edit-annotations support. #20
…unding box annotation view: Shows the current branch label (from a linked subsequence_classification task) below the canvas, updating as the slider is moved. Displays N/A for frames without a label. #20
| width = models.PositiveIntegerField() | ||
| height = models.PositiveIntegerField() | ||
| label = models.CharField(max_length=255, blank=True) | ||
| color = models.CharField(max_length=7) # hex color, e.g. '#e6194b' |
There was a problem hiding this comment.
I undestand that to not clutter the Labels table with user-inputed box names, you want to save the label and colour on the BronchoscopyBoundingBox. Yet, have you considered the alternative proposed by Karen to add new labels on-the-fly? It could enable recycling of already inputed labels in previous annotation tasks.
On a side note, but still related to my previouos comment, the labels selected when creating the task are not available for the user.
There was a problem hiding this comment.
I thought this would function the same way as for subsequence_classification, where new labels are added if not seen before. However, I do not see how this would make an impact anyway. A more robust solution could be to add a check for valid labels. E.g. only integers <5, separated by ",".
There was a problem hiding this comment.
This is the PR with the automatic new-label creation functionality I mentioned: #18
| y=int(box['y']), | ||
| width=int(box['width']), | ||
| height=int(box['height']), | ||
| label=box.get('label', ''), |
There was a problem hiding this comment.
Related to my previous comment on empty label texts
| g_BBx = pos.x; | ||
| g_BBy = pos.y; | ||
| var inside = isInsideBox(pos.x, pos.y); | ||
| if (inside.isInside) { |
There was a problem hiding this comment.
Update the "Box label" text box with the selected box label. It is reasonable to expect the user to be able to change the label of the last selected box.
There was a problem hiding this comment.
We have only one label text field. The value entered will be the code to the next drawn box, it will not update the name of an existing box. It the code is incorrect, the box needs the be deleted and redrawn after entering the correct label. We could add a new functionality to update the name of existing boxes, but that would require a few additions to the GUI.
|
I forgot to add that the behaviour of the application is as expected, according to the test instructions. Good job! |
…oscopy_bounding_box → bronchoscopy_boundingbox and (2) enforce non-empty box label. 1:Renames the app directory, static/template subdirectories, JS file, and exporter file, updating all references in settings, urls, views, apps.py, and the exporter import. URL namespace updated to match. 2:Adds frontend validation blocking box drawing when the label field is empty (red outline feedback for 1 s). Also sets blank=False on the model label field to enforce the constraint at the database level.
jpdefrutos
left a comment
There was a problem hiding this comment.
The commit fixes the naming of the application and the empty label field issue.
We discussed about using the automatic label creation proposed in #18
I will leave this PR open waiting for what do you prefer to do next. Either merge these changes, or change the design of the bounding box for bronchoscopy application :)
Replace the cycling fixed-palette approach with a hash-based color generation scheme aligned with PR #18 (feature/textbox-colored-labels): - Add stringToColor() using the polynomial hash + golden angle (137.508°) mapping to HSL hue, so similar labels get visually distinct colors - Add hslToHex() helper to produce well-saturated, consistent colors - Cache label→color in g_labelColorMap so the same label always gets the same color within and across sessions - Auto-create missing Label entries in the shared Label model (with RGB color) and link them to the task on save, if not already present - Drop BronchoscopyBoundingBox.color — color is now derived from the label name rather than stored per box
|
I removed the color from BronchoscopyBoundingBox, and rather use the color from existing Label entries. Using a similar approach to generate deterministic colours for labels as is done in feature/textbox-colored-labels (PR#18), however two improvements were needed. First, the color generator did make similar colors for similar labels, resulting in two bounding-boxes in the same frame having very similar colors. This was fixed by scattering neighbours in the polynomial hash. Second, trying to avoid light red colours, similar to the background. The same color generation strategy should also be used in feature/textbox-colored-labels. |
These color utilities were only available in bronchoscopy_boundingbox. Moving them to annotationweb.js (loaded globally via base.html) makes them accessible to all annotation types without any template changes.
save_boxes() crashed with a KeyError when a key frame had no boxes drawn on it: g_boxes only contains frames with boxes, but annotations iterates all key frames. Fix by skipping frames absent from boxes_data. Also wrap the entire view in transaction.atomic() so a failure cannot leave the DB in a partially-saved state.
The new functionality can be tested on a dataset from a CustusX patient with a bronchoscopy video acquired.
a) Check that the annotations from step 1 are read in and displayed (e.g. "Current branch: 1,1,2").
b) Check that you are able to draw bounding boxes with different names and with random colours.
c) Copy to next frame is working.
d) Check that the annotation file is created with one line per box per frame.