Skip to main content
Back to Projects
FeaturedAIStable DiffusionFastAPISAM

AI Art Stylization Platform

AI image stylisation: SAM segments the region you pick, and Stable Diffusion restyles only that region, served from FastAPI.

Stable Diffusion + SAM
Models
FastAPI
Backend
Region masks
Control

Facts about the build and who it was for. Any figure here is shown on a public store listing or site linked on this page — how we present portfolio work.

Project Story

The Challenge

Image stylization tools lacked precise control and real-time AI performance.

What Was Built

Built an AI-powered platform using FastAPI, Stable Diffusion, and SAM for segmentation-based stylization.

The Result

Region-level stylisation: SAM masks the chosen area and Stable Diffusion restyles only that area.

Project Details

AI-powered image stylization system using Stable Diffusion and SAM with real-time segmentation and processing.

Tech Stack

FastAPI
Stable Diffusion
SAM

No public link for this project

Category

FastAPI & Stable Diffusion
Written by DevoraXReviewed by Sameem Amjad, Founder & Lead Architect EngineerLast updated Based on project records and public sources (case study)

The AI Art Stylization Platform is an image stylization system with a FastAPI backend that uses SAM to segment an image and Stable Diffusion to restyle a chosen region rather than the whole picture. The sections below explain why region control needs a segmentation model, how Stable Diffusion restyles part of an image, why interactive speed is hard for a diffusion model, and what FastAPI and accelerator memory mean for serving one.

What problem was the AI Art Stylization Platform built to solve?

The problem it addresses is that image stylization tools lack precise control and real-time performance. Precise control is the first of two deficits. A model that restyles an image restyles all of it, and that is the correct behaviour when the whole frame is the subject. It is the wrong behaviour when a person wants the jacket repainted and the face left alone, or the sky replaced and the building untouched. Without a way to say where, the only available instruction is a prompt describing the result, and the model decides on the rest by itself.

Speed is the second deficit, and it is bound up with the first. Control is exercised by iteration. Somebody selects a region, looks at the result, adjusts the selection or the instruction and looks again, and that loop is only usable if each pass returns while the previous attempt is still in mind. Once a pass outlasts that attention, the loop stops being a control surface and becomes a submission form. Precision therefore depends on speed in a way that is not obvious from reading the two words side by side, and a build that solved either one alone would not solve the problem described here.

Why does the platform need a segmentation model at all?

The approach is segmentation-based stylization, with SAM working alongside Stable Diffusion. The pairing answers a question that generative models do not answer for themselves, which is where the edit is allowed to happen. Selecting that region by hand is the obvious alternative and it is slow, because the boundaries that matter in a photograph are hair, foliage, glassware and shadow rather than rectangles. Conventional semantic segmentation is the other alternative, and it carries a different limit: those models are trained against a closed list of classes, so they can find a person or a car because somebody decided in advance that person and car were categories. The regions an art tool is asked about do not form a fixed vocabulary. They are whatever the person looking at the picture happens to point at.

SAM is promptable and class-agnostic, which is the property that matters here. It takes a point, a box or a rough mask and returns the region that prompt refers to, without needing a label for what that region contains, and it returns more than one candidate because a click is ambiguous by nature. A point on a sleeve might mean the sleeve, the jacket or the whole person, and offering all three is more honest than guessing. Its architecture reinforces the same interaction. A heavy image encoder runs once to produce an embedding for the picture, and a light decoder then answers each prompt against that cached embedding, so the expensive work is paid once per image rather than once per click. Selection stays responsive while the person explores.

How does Stable Diffusion restyle only part of an image?

Stable Diffusion is a latent diffusion model, which means the denoising does not happen on pixels. An encoder compresses the image into a much smaller latent representation, the iterative work happens there, and a decoder turns the finished latent back into an image. That compression is what makes the model run on a single accelerator instead of a cluster, because every denoising step operates on a fraction of the data a pixel-space model would have to touch. Restricting an edit to a region uses that loop directly. In the simplest form, a mask marks which part of the latent the model is permitted to change, and at each step the area outside the mask is overwritten with the original image carried forward to the same noise level. Dedicated inpainting checkpoints go further and take the mask and the masked image as extra inputs. Either way the model still sees the whole canvas, so what it paints inside the region is conditioned on the context around it, but it cannot write outside the boundary.

Two details make that harder than it sounds, and both are general properties of the approach. The first is resolution. The latent grid is coarser than the image, so a mask drawn to the pixel has to be resampled down before it can be applied, and a boundary that was exact in the picture becomes approximate in the space where the work is done. The second is the seam. Inside and outside were produced by different processes, so the join can read as a cut even when both halves look correct, which is why masks are usually softened at the edge and the result blended rather than pasted. Control also has a second axis beyond location. How far the model is allowed to travel from the original, and how many steps it takes to get there, decide whether a region is retouched or replaced.

Why is real-time performance difficult for a diffusion model?

The problem statement asks for real-time performance, and a diffusion model is an awkward thing to ask that of, because its cost is not one forward pass. Generation is a loop, and each iteration runs the full denoising network over the latent. Halving the number of steps roughly halves the time and changes the output, since the step count is a quality setting as much as a speed setting. Resolution compounds it, because a larger latent means more work in every one of those iterations. That is the structural difference between this workload and the request handling most backends do. A database query is slow because something is being waited on. A denoising loop is slow because an accelerator is fully occupied for its duration, and no amount of concurrency in the serving layer makes the arithmetic smaller.

The general levers are well known and each is a trade. Samplers that reach an acceptable result in fewer steps buy time against fidelity. Working at a lower resolution and enlarging afterwards moves cost from the loop to a cheaper stage. Distilled variants of the model trade some range for speed. Keeping weights resident in memory removes load time from every request, at the cost of holding that memory permanently. There is also a perceptual lever that is often worth more than any of them, which is returning intermediate states while the loop runs, so the person watches the image resolve instead of watching a spinner.

Why was FastAPI a reasonable choice for the serving layer?

FastAPI is the backend, and the first reason is one the model choice already made. Stable Diffusion and SAM are published as Python, with their weights, loaders and inference code in that ecosystem, so the serving process wants to be Python too. The alternative is a second runtime talking to a Python worker across a boundary, which adds a hop and a serialisation format for data that is large and awkward to serialise. FastAPI is the ordinary choice inside that constraint. Its request models are declared as types and validated before a handler runs, which matters more here than in a typical API, because the parameters are numerous and expensive to get wrong. A step count, a strength value, a seed, a mask and a prompt are cheap to reject at the edge and costly to discover as invalid after an accelerator has been committed.

The tradeoff is worth naming plainly, because it is where services of this shape usually go wrong. FastAPI is asynchronous, and asynchronous concurrency helps with work that waits. Inference does not wait. It holds a device, and a blocking call made inside an event loop stalls every other request sharing that loop, including the ones that only wanted to upload an image or fetch a mask. The general remedy is to keep inference off the loop entirely: accept the request, put it on a queue served by however many workers the hardware supports, and give the caller a channel to watch. FastAPI accommodates both halves of that, since handlers declared synchronously are run off the loop and the framework carries WebSocket and streaming responses for progress.

What limits throughput on a service like this?

The platform runs two models, and both have to be in memory to be useful. A diffusion pipeline carries a denoising network, an autoencoder and a text encoder; SAM carries an image encoder and its decoder. Loading weights from disk is slow enough that nobody wants to do it per request, so the weights stay resident, and resident weights occupy device memory whether or not anything is being generated. That inverts the usual scaling question. A conventional web service scales by adding processes because processes are cheap. Here the unit of capacity is the accelerator, a second process on the same device competes for the same memory, and the honest ceiling on concurrent work is set by hardware rather than by the framework. The reasonable shape is a bounded queue in front of a small number of workers, so load turns into waiting rather than into failure.

There is also a piece of state that a stateless design would throw away. SAM's image embedding is expensive to compute and reusable across every prompt on the same picture, so keeping it between requests is what makes a second click cheap, and keeping it is a caching decision with a memory cost and an eviction policy attached.

Where can the AI Art Stylization Platform be seen?

There is no public link and no named client: there is no live tool to try and no gallery of its output to inspect. The build itself is an image stylization system with a FastAPI backend that uses SAM to pick out a region and Stable Diffusion to restyle it, and the sections above explain how those pieces fit together.

Why this stack

  • FastAPI is the backend, and Python is effectively forced by the models beside it, since Stable Diffusion and SAM live in that ecosystem and a separate runtime would add a hop and a serialisation step for large tensors. Within that constraint FastAPI validates typed request models before a handler runs, which is worth more than usual when the parameters are a prompt, a mask, a seed, a strength and a step count. Its asynchronous core helps with uploads and waiting, not with inference, which has to be moved off the event loop.
  • Stable Diffusion is the generative model. It denoises in a compressed latent space rather than on pixels, which is what lets it run on a single accelerator, and that same loop is where region control is implemented: a mask decides which part of the latent the model may change while the rest is carried forward from the original at each step. The consequences are structural. The mask is applied at latent resolution, so a pixel-exact boundary becomes approximate, and cost scales with step count and resolution rather than with one forward pass.
  • SAM is the segmentation model, and it supplies the mask that the diffusion step needs. Its useful property is that it is promptable and class-agnostic: a point, a box or a rough mask returns the corresponding region without a label vocabulary deciding in advance what counts as a subject, which suits an art tool where the region of interest is whatever someone points at. Its structure also fits an interactive loop, because a heavy encoder runs once per image and a light decoder answers each prompt against that cached embedding.