Skip to content

Add support for model prediction in Video toolbar#271

Open
wk9874 wants to merge 51 commits into
devfrom
wk9874/models/data_params
Open

Add support for model prediction in Video toolbar#271
wk9874 wants to merge 51 commits into
devfrom
wk9874/models/data_params

Conversation

@wk9874

@wk9874 wk9874 commented May 18, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds support for model predictions of single samples from the toolbar of the Video interface, to match what is available in time series.

Changes

  • Adds the modelPredictSample tool to toolbar in video mode as well as time series
  • Adds support in the backend (model baseclass and /samples/{sample_id}/models/{type) for passing dataParams for the selected sample to the backend (so that, eg, the frame number is available to the model)

To Test

Use scripts.setup to create the local Frame Project, then go into there and 'train' a model with the button in the top right. Once trained, open the sample, and use the model prediction in the toolbar. Should be an option to either predict on only one frame, or all frames. Predictions will be a box of width 50, height 50 at (0,0) with the id 'test'.

To clear previous predictions, press Clear at the top of the toolbar, then Save, then Clear again

To Dos

  • Noticed a formatting issue in the model schema form - checkbox and array element descriptions overfill the toolbar column when using the model predict sample tool, and no combination of widths / minWidth / maxWidth seemed to fix it. Currently have hardcoded the size to 2500, which makes it fit in the toolbar nicely, but means it looks odd in the predict modal. Need some help figuring out what is causing this issue Fixed by Josh, setting max width of toolbar
  • Inside modelPredictSample there is now some video specific logic, which I would like to remove ideally. This is because the dataParams stored inside sampleContext are not guaranteed to be correct when in video mode, and you need to access the frame from data directly to reconstruct the effectiveDataParams. Would prefer it to be that the dataParams in sampleContext is the single point of truth which both timeseries and video use Fixed by Abdullah
  • Unlike timeseries, video doesn't seem to update annotations automatically based on when setAnnotations is called from sampleContext. This means that once predictions are ready and returned from the backend, setAnnotations is called, but you dont see any new boxes until you refresh. Would be good to have it work similarly to time series and auto update if possible Fixed by abdullah
  • Remove temp model from temp.py and init.py once testing complete

Note Do not merge until #255 is merged

Closes #240
Closes #246

Base automatically changed from wk9874/models/245-model-prediction-untrained to dev May 20, 2026 09:23
@wk9874 wk9874 changed the base branch from dev to video/UI-cleanup May 20, 2026 09:41
@wk9874 wk9874 changed the base branch from video/UI-cleanup to dev May 20, 2026 09:46
@wk9874 wk9874 changed the base branch from dev to video/UI-cleanup May 20, 2026 09:47
@wk9874 wk9874 marked this pull request as draft May 20, 2026 09:52
@wk9874

wk9874 commented May 28, 2026

Copy link
Copy Markdown
Collaborator Author

Model prediction boxes appear to not be selectable for some reason:

toktagger_prediction_not_selectable.mp4

@abdullah-ukaea

Copy link
Copy Markdown
Collaborator

Model prediction boxes appear to not be selectable for some reason:

toktagger_prediction_not_selectable.mp4

for some reason I cannot reproduce this

model_predict_selection_bug.mp4

@abdullah-ukaea

abdullah-ukaea commented May 28, 2026

Copy link
Copy Markdown
Collaborator

If I have a model which creates a prediction over multiple frames, propagation of hand drawn annotations is disabled

model_predict_multiple.mp4
(not even sure what should happen here, so happy to be told that this is either expected behaviour, or is so insignificant that its not worth fixing!)

as discussed, this is actually working as expected based on how propagation is currently implemented. However now that model prediction is being integrated into toktagger I need to rethink how to only propagate hand drawn annotations and NOT propagate model predicted annotations.

This will be tackled in a separate follow up PR / needs to be documented in an issue

abdullah-ukaea and others added 2 commits May 29, 2026 16:23
…l edits, and prevent Annotorious programmatic redraw events from being mistaken for user edits
@abdullah-ukaea

abdullah-ukaea commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

could you give this branch another functional test to help me identify any bugs? I think I resolved the main reported bug now. @jblake42 @wk9874

@wk9874

wk9874 commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator Author

Yep the instance numbering bug when importing looks fixed now :) other two I think are future work, have raised issues #275 #276

Found another bug, but I think this is probably a bug in my model Predict tooling implementation - if you ask for a model prediction on one frame, then go to the next frame and ask for a prediction on that one, itll remove the prediction from the first frame... suspect when I wrote the model predict tool only timeseries existed, and so it removes previous annotations from the given model before adding new ones (which ofc means that in the video case, it removes predictions from all frames before writing new predictions for the next requested frame). I'll look into fixing this today

@abdullah-ukaea

Copy link
Copy Markdown
Collaborator

Yep the instance numbering bug when importing looks fixed now :) other two I think are future work, have raised issues #275 #276

Found another bug, but I think this is probably a bug in my model Predict tooling implementation - if you ask for a model prediction on one frame, then go to the next frame and ask for a prediction on that one, itll remove the prediction from the first frame... suspect when I wrote the model predict tool only timeseries existed, and so it removes previous annotations from the given model before adding new ones (which ofc means that in the video case, it removes predictions from all frames before writing new predictions for the next requested frame). I'll look into fixing this today

sounds good, let me know if I need to change anything on the ui side to fix the prediction bug you mentioned

@abdullah-ukaea

Copy link
Copy Markdown
Collaborator

ready for code review @jblake42

@jblake42 jblake42 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mainly focussed on front end due to time constraints

{" "}
<em>{schema.description}</em>{" "}
</Text>
// For some reason anything other than hard coding a size here

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wk9874 - was this fixed by setting the toolbar width. Can we remove the comment etc?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep this is fixed, will remove the TODO

updater: (annotations: Annotation[]) => Annotation[] | Annotation[],
) => void;
setDataParams: (params: DataParams) => void;
setDataParams: React.Dispatch<React.SetStateAction<DataParams>>;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this typed like this for a reason or can we be consistent with the other instances below?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good spot, there wasn’t a good reason for it to be typed differently. I’ve changed setDataParams to match the other context setters and cleaned up the VideoView call site so the typing is simpler. fixed in commit ef902a8

return prev;
}
return {
...prev,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not need to expand the existing previous frame here as you are overwriting all existing data anyway:

return {
  name: "image",
  frame,
};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good spot, fixed in commit da4a93c

): ImageAnnotation {
return stampCreator(stampLabelAndTrack(a, className, trackId), createdBy);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The functions are a little messy here imo - you have split functionality into the different types of stamps and then combined them in higher level functions.

I personally think keep them all seperate and then chaining them at the point of use would improve the clarity rather than having multiple functions performing varying levels of stamping

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, fixed in commit 8dd4d4c

};
}

/** Read backend creator metadata, falling back to manual at export time. */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the comment is misleading - this function does not do any falling back as such, it just returns null. The logic that uses this does the falling back

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think falling back to manual is valid, but in that case this function should return manual and then you don't have to repeat the line created_by: getAnnotationCreator(a) ?? "manual", you could just do created_by: getAnnotationCreator(a)

I don't mind either way but whichever you go for be clear in the comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have gone with your second suggestion as I think a fall back to manual rather than null is more correct, so now the comment is actually correct. fixed in commit 2166214

dbAnnotations={annotations ?? []}
setSampleAnnotations={setAnnotations}
propagate={videoPropagate}
setPropagate={setVideoPropagate}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There may be a good reason, but can the VideoSessionProvider not just grab the context itself rather than have the inner provider do it for it. It seems a bit redundant to me and bloats the props?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, there wasn’t a strong reason to pass those through as props since they all come from SampleContext. I’ve moved those context reads into VideoSessionProvider directly, so VideoProvidersInner now only passes the video-specific props it needs to. Fixed in commit d09152b

continue;
}

entries.push(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be more explicit here and check that the type is as we expect - this will catch if an additional type is added and the logic is not updated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in commit 8cc8af1

});

const anno =
dbAnno.type === "video_bounding_box"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here with explicitly checking types

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are other instances below - I won't comment them all

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in commit 8cc8af1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are other instances below - I won't comment them all

could you double check I got all the instances?

setByFrame((prev) => mapSetFrame(prev, f, list));
// Seeding should not mark the session dirty.
}, []);
useEffect(() => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep useEffects grouped together

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in commit 876420a

Could you double check this commit is what you wanted me to do?

},
[byFrame.size, dirty, projectId, sampleId],
);
if (invalid > 0) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do duplicates frequently happen or is there any actions that need to be taken if duplicates happen - if they are frequent or there is no action to be taken we shouldn't flood the log

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, this was just leftover debug-style logging for a handled cleanup path. I removed the warnings and kept the duplicate cleanup behavior unchanged so we do not flood the console. fixed in commit 0d18293

@abdullah-ukaea

abdullah-ukaea commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

@jblake42 I have addressed your UI code review now. I think @wk9874 has one pending comment

Dr. CI Bot and others added 4 commits June 11, 2026 11:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Image Annotation: Detect annotation changes in db and update UI Change model predict/train models to require same params as annotators

3 participants