Skip to content

Conversation

@dwesolow
Copy link

@dwesolow dwesolow commented Oct 1, 2025

📝 Description

This PR introduces a few features:

  • allow user to upload images (temporary feature, to be removed when we support stream capture);
  • list uploaded images;
  • allow user to train a model when there is enough number of normal images;
  • display proper message while training.

This is just starting point, we will improve that once we know that training is stable.

image

✨ Changes

Select what type of change your PR is:

  • 🚀 New feature (non-breaking change which adds functionality)
  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • 🔄 Refactor (non-breaking change which refactors the code base)
  • ⚡ Performance improvements
  • 🎨 Style changes (code style/formatting)
  • 🧪 Tests (adding/modifying tests)
  • 📚 Documentation update
  • 📦 Build system changes
  • 🚧 CI/CD configuration
  • 🔧 Chore (general maintenance)
  • 🔒 Security update
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)

✅ Checklist

Before you submit your pull request, please make sure you have completed the following steps:

  • 📚 I have made the necessary updates to the documentation (if applicable).
  • 🧪 I have written tests that support my changes and prove that my fix is effective or my feature works (if applicable).
  • 🏷️ My PR title follows conventional commit format.

For more information about code review checklists, see the Code Review Checklist.

@dwesolow dwesolow requested a review from MarkRedeman October 1, 2025 09:03
@dwesolow dwesolow self-assigned this Oct 1, 2025
@dwesolow dwesolow requested a review from samet-akcay as a code owner October 1, 2025 09:03
@codecov-commenter
Copy link

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Contributor

@MarkRedeman MarkRedeman left a comment

Choose a reason for hiding this comment

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

Looks good, thanks @dwesolow !
I have some minor comments but feel free to handle them in follow up PRs

Comment on lines +12 to +17
const mediaItemsToRender =
mediaItems.length >= REQUIRED_NUMBER_OF_NORMAL_IMAGES_TO_TRIGGER_TRAINING
? mediaItems
: Array.from({ length: REQUIRED_NUMBER_OF_NORMAL_IMAGES_TO_TRIGGER_TRAINING }).map((_, index) =>
index <= mediaItems.length - 1 ? mediaItems[index] : undefined
);
Copy link
Contributor

Choose a reason for hiding this comment

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

np: I think this is a bit more readable, (it makes it easier to see that we render the media items by default, and potentially add some undefined placeholders)

Suggested change
const mediaItemsToRender =
mediaItems.length >= REQUIRED_NUMBER_OF_NORMAL_IMAGES_TO_TRIGGER_TRAINING
? mediaItems
: Array.from({ length: REQUIRED_NUMBER_OF_NORMAL_IMAGES_TO_TRIGGER_TRAINING }).map((_, index) =>
index <= mediaItems.length - 1 ? mediaItems[index] : undefined
);
const mediaItemsToRender = [
...mediaItems,
...Array.from({ length: Math.max(0, REQUIRED_NUMBER_OF_NORMAL_IMAGES_TO_TRIGGER_TRAINING - mediaItems.length) })
]

Copy link
Author

Choose a reason for hiding this comment

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

Nice, will add it, thanks!

{
id: 'padim',
name: 'PADIM',
},
Copy link
Contributor

Choose a reason for hiding this comment

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

@ashwinvaidya17 can you comment on what other models should be available? The id that is used here will be used in the model training service.

Comment on lines +148 to +151

return (
<InlineAlert variant='negative'>
<Heading>Training canceled</Heading>
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd maybe also add a if (jobProgres.status === 'cancelled') here instead of relying that type inference guarantees that the status must be cancelled.
Having the explicit if statement here makes it a bit easier to read when reviewing outside of an IDE (I don't have to make sure that in the if statements above we handled all except the cancelled status)

Comment on lines +172 to +173
// TODO: Investigate how to handle that case (local storage, poll for job status) after refreshing a page.
if (startTrainingMutation.data !== undefined) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we use the '/api/jobs' endpoint for this? Perhaps we can make it so that if the jobs endpoint returns 1 or more jobs for this project, then we render all of those jobs' progresses.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah I was wondering implementing this but I wasn't sure but if u also agree then I'll implement that ;).

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's go with this on the short term.
Long term we have to see how long training takes and how frequently we expect new models to be trained (and if they are trained in bulk), if they are then I think a job management panel like we have in Geti would be a good approach.

const captureImages = (files: FileList | null) => {
if (files === null) return;

Array.from(files).forEach((file) => captureImage(file));
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be better to change this function to an async function and await each mutation. Otherwise if the user selects 1000 images then we would immediately try to upload all of them.

Though given that we will likely remove this feature once the source pipeline is integrated I guess it won't be worth it to optimize this?

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, I wanted to keep it really simple since it's a temporary feature.

@dwesolow dwesolow merged commit 48794c4 into feature/geti-inspect Oct 1, 2025
14 of 17 checks passed
@dwesolow dwesolow deleted the dwesolow/upload-images branch October 1, 2025 11:36
MarkRedeman pushed a commit that referenced this pull request Oct 8, 2025
… training progress (#2984)

* feat: Allow user to upload images

* feat: List uploaded images

* chore: Extract components to separate files and add ready to train and training progress

* chore: comment thumbnail url generation
camiloHimura pushed a commit to camiloHimura/anomalib that referenced this pull request Nov 11, 2025
… training progress (open-edge-platform#2984)

* feat: Allow user to upload images

* feat: List uploaded images

* chore: Extract components to separate files and add ready to train and training progress

* chore: comment thumbnail url generation
maxxgx pushed a commit that referenced this pull request Nov 26, 2025
… training progress (#2984)

* feat: Allow user to upload images

* feat: List uploaded images

* chore: Extract components to separate files and add ready to train and training progress

* chore: comment thumbnail url generation
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.

4 participants