Skip to content

Image inpainting, outpainting#4047

Open
atobiszei wants to merge 12 commits intomainfrom
atobisze_image_inpainting
Open

Image inpainting, outpainting#4047
atobiszei wants to merge 12 commits intomainfrom
atobisze_image_inpainting

Conversation

@atobiszei
Copy link
Collaborator

@atobiszei atobiszei commented Mar 9, 2026

  • Add inpainting and image-to-image pipeline support via /v3/images/edits endpoint (multipart form with image + optional mask)
  • Add mask parsing in multipart request handler
  • Propagate extraQuantizationParams to all optimum export functions (embeddings, TTS, STT, rerank, image_gen, text_gen)
  • Demo

Ticket:CVS-181770

@atobiszei atobiszei added the WIP Do not merge until resolved label Mar 9, 2026
@atobiszei atobiszei marked this pull request as ready for review March 13, 2026 14:12
Copilot AI review requested due to automatic review settings March 13, 2026 14:13
@atobiszei atobiszei removed the WIP Do not merge until resolved label Mar 13, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR extends OVMS image-generation support to cover inpainting/outpainting via the OpenAI-compatible /v3/images/edits endpoint (using an uploaded mask), and updates pipeline initialization to include OpenVINO GenAI’s InpaintingPipeline.

Changes:

  • Add InpaintingPipeline to the image-generation pipeline bundle and initialize pipelines with weight-sharing + fallbacks.
  • Route /v3/images/edits requests to inpainting when mask is provided; expand request-option validation to accept mask.
  • Extend multipart parser interface with a “files array” accessor and update demos/docs/assets accordingly.

Reviewed changes

Copilot reviewed 13 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/image_gen/http_image_gen_calculator.cc Routes edit requests to inpainting when mask is present; removes per-request pipeline cloning.
src/image_gen/pipelines.hpp Adds InpaintingPipeline member and include.
src/image_gen/pipelines.cpp Builds/compiles inpainting pipeline and derives other pipelines with fallbacks.
src/image_gen/imagegenutils.cpp Accepts mask in allowed fields for generation/edit option parsing.
src/multi_part_parser.hpp Adds getFilesArrayByFieldName() to the multipart parser API.
src/http_frontend/multi_part_parser_drogon_impl.hpp/.cpp Implements getFilesArrayByFieldName() for Drogon multipart parser.
src/test/text2image_test.cpp Updates MockedMultiPartParser to match the new interface.
src/test/test_http_utils.hpp Updates multipart parser mock to match the new interface.
src/test/pull_hf_model_test.cpp Adds test coverage for image-generation export command with extra params.
src/pull_module/optimum_export.cpp Appends extraQuantizationParams for image-generation export command.
demos/image_generation/README.md Documents inpainting/outpainting usage via cURL and OpenAI Python client.
demos/image_generation/cat_mask.png Demo asset for inpainting mask.
demos/image_generation/outpaint_mask.png Demo asset for outpainting mask.
.gitignore Reorders/adds Bazel output directories to ignore list.
.dockerignore Expands ignored local/dev and build artifacts; ignores models/ and logs.

You can also share your feedback on Copilot code review. Take the survey.

mask field should only be accepted in image edit (inpainting) requests,
not in text-to-image generation requests.
@atobiszei atobiszei requested a review from dkalinowski March 17, 2026 13:26
![cat](./cat.png) ![cat_mask](./cat_mask.png)

Linux
```bash
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add tab for sphinx? Can you generate sphinx doc so we can see how it is going to look? @atobiszei


![cat](./cat.png) ![cat_mask](./cat_mask.png)

Linux
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Follow switch formating with sphinx, as in earlier part of readme.

oss << " --weight-format " << this->exportSettings.precision;
if (this->exportSettings.extraQuantizationParams.has_value()) {
oss << " " << this->exportSettings.extraQuantizationParams.value();
} // TODO FIXME check if its not needed to propagate to other exports
Copy link
Collaborator

Choose a reason for hiding this comment

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

who is going to do this? FIXME are treated as errors during release

@atobiszei atobiszei force-pushed the atobisze_image_inpainting branch from c818d8b to eac3932 Compare March 18, 2026 10:28
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds OpenAI-compatible image edit support (image-to-image + inpainting/outpainting) to OVMS image generation, extends multipart parsing, and propagates Optimum export extra quantization parameters across tasks. This fits into the image generation REST API surface (/v3/images/*) and the HF pull/export flow.

Changes:

  • Add inpainting routing for /v3/images/edits when a mask multipart file is provided, including pipeline initialization and request serialization.
  • Extend multipart parser interface to support arrays of file parts; add unit tests for edits option validation (including mask).
  • Propagate extraQuantizationParams into additional Optimum export command builders and update related tests; refresh demo docs/assets.

Reviewed changes

Copilot reviewed 14 out of 21 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/test/text2image_test.cpp Adds unit tests around /v3/images/edits request-option validation (mask accepted, unknown/rejected fields, defaults, bounds).
src/test/test_http_utils.hpp Updates multipart parser mock with new getFilesArrayByFieldName() API.
src/test/pull_hf_model_test.cpp Updates expected Optimum export commands to include extra quantization params; adds image-gen specific coverage.
src/pull_module/optimum_export.cpp Appends extraQuantizationParams to additional Optimum export command builders (embeddings/TTS/STT/rerank/image-gen).
src/multi_part_parser.hpp Extends multipart parser interface with getFilesArrayByFieldName().
src/image_gen/pipelines.hpp Adds inpainting pipeline + queue serialization guard for inpainting requests.
src/image_gen/pipelines.cpp Builds pipeline chain with fallbacks and initializes single-slot queue for inpainting serialization.
src/image_gen/imagegenutils.cpp Treats mask as an accepted multipart field for edits.
src/image_gen/http_image_gen_calculator.cc Routes /v3/images/edits to inpainting when mask is present; adds pipeline availability checks and queue-guarded execution.
src/image_gen/BUILD Adds dependency on //src:libovms_queue for inpainting serialization.
src/http_frontend/multi_part_parser_drogon_impl.hpp Declares new getFilesArrayByFieldName() implementation.
src/http_frontend/multi_part_parser_drogon_impl.cpp Implements getFilesArrayByFieldName() using Drogon parser’s files list.
demos/image_generation/outpaint_mask.png Adds demo asset for outpainting mask example.
demos/image_generation/cat_mask.png Adds demo asset for inpainting mask example.
demos/image_generation/README.md Documents inpainting/outpainting usage and updates model-status endpoint example.
.gitignore Adjusts Bazel output ignore entries.
.dockerignore Expands ignored dev/build artifacts to reduce Docker build context size.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +38 to +45
InpaintingQueueGuard(Queue<int>& queue, std::chrono::seconds timeout) :
queue_(queue) {
auto future = queue_.getIdleStream();
if (future.wait_for(timeout) == std::future_status::ready) {
streamId_ = future.get();
acquired_ = true;
}
}
Comment on lines +68 to +72
// Serializes concurrent inpainting requests (InpaintingPipeline lacks clone()).
// Queue size = 1: only one inpainting inference runs at a time.
std::unique_ptr<Queue<int>> inpaintingQueue;
static constexpr std::chrono::seconds DEFAULT_INPAINTING_TIMEOUT{300}; // 5 minutes

Comment on lines 37 to +42
// API for MP calculators to get the multipart file content by field name.
// Returns empty string if file is not found.
virtual std::string_view getFileContentByFieldName(const std::string& name) const = 0;

// API for MP calculators to get all file contents for a given array field name (e.g. "image[]").
virtual std::vector<std::string_view> getFilesArrayByFieldName(const std::string& name) const = 0;
Comment on lines +214 to +217
ov::Tensor maskTensor;
SPDLOG_LOGGER_DEBUG(llm_calculator_logger, "ImageGenCalculator [Node: {}] Inpainting: decoding mask tensor", cc->NodeName());
status = makeTensorFromString(std::string(mask.value()), maskTensor);
if (!status.ok()) {
@atobiszei atobiszei requested a review from rasapala March 18, 2026 15:26
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.

3 participants