All projects

IntelliRoom

A graduation project, graded A+. I built its AI: the ComfyUI workflows that edit room photos, a furniture search over a catalogue I generated and annotated, and a workflow that turns a product photo into a 3D model.

Context
Graduation project, graded A+, Ain Shams University, team of seven, Aug 2025 to June 2026
Role
The AI side: every ComfyUI workflow, the universal graph, furniture search, the product catalogue and its annotations, the 3D workflow, documentation
Stack
ComfyUI, Flux 2 Klein 4B, Florence-2, SAM2, RT-DETR, SigLIP2, Qwen3-VL, ChromaDB, Hunyuan3D 2.0
Outcome
Thesis submitted June 2026, graded A+. Eleven exported workflows, a search service, a 158-product catalogue and a 3D workflow
A large room with a herringbone floor and arched alcoves, furnished with two grey sofas, a round wooden coffee table, a woven rug and a palm in warm light.

An empty room, furnished by a model.

IntelliRoom is a web platform where you upload a room, change it with AI and buy what you see. Drag the slider: an empty hall on the left, the same hall furnished by my edit workflow on the right. The arches, the doorway, the cornice and the herringbone floor stay exactly where they were.

I built every AI workflow behind it. Below are all of them, from the 72-node graph that switches between jobs to the eleven exports that run on the platform.

An empty hall with a herringbone parquet floor, a plain cornice, a doorway and two arched alcoves.
The same hall furnished with two grey sofas, armchairs, a round coffee table, a woven rug and plants.
BeforeAfter
Before: an empty hall made with Flux text-to-image. After: the same hall furnished by the Flux 2 Klein edit workflow.

One graph that switches between every job.

In the first semester each job was its own ComfyUI workflow: furnish an empty room, replace an object, transfer a style, render a sketch, upscale. I merged them into one graph, which the thesis calls the universal workflow, so the platform could change job by flipping switches instead of reloading files.

Image data runs along a rail with the control signals beside it. When a switch is off, Fast Muter and Any Switch nodes bypass that whole block, so a mode only pays for the nodes it uses. Scroll to fly through it.

The whole story in 32 seconds: the universal graph block by block, then the second-semester Flux 2 Klein edits, then the 3D workflow. Every frame is a real capture or a real output.
The whole universal workflow: a control centre of coloured switches on the left, mask, style and conditioning blocks across the middle, and the sampler and output on the right, joined by hundreds of cables.

The universal workflow 72 nodes, 116 links. Five blocks, left to right.

  1. 01 Serves: Every mode

    The control centre

    Nine switches on the far left set the whole graph: generation mode (text-to-image, image-to-image or inpaint), manual or automatic masks, the IP-Adapter, each ControlNet, the Canny source, the denoise strength and M-LSD lines. Changing a job means flipping switches, not loading another file.

    The the control centre region of the universal graph.
  2. 02 Serves: Replace one object

    Masks without drawing

    Florence-2 reads a word such as “carpet” and returns a box; SAM2 turns the box into a pixel mask. When the switch says manual, or the job needs no mask, the whole block is bypassed and costs nothing.

    The masks without drawing region of the universal graph.
  3. 03 Serves: Shop the look

    Style injection

    An IP-Adapter encodes a reference product, such as a rug from the catalogue, and injects it into the generation. With no reference, the switch opens and the prompt alone drives the result.

    The style injection region of the universal graph.
  4. 04 Serves: Empty room, sketch, restyle

    The conditioning rail

    A rail of logic gates picks which ControlNets guide the image: Canny edges for structure, depth for volume, M-LSD for straight walls, and sets their strengths for the current mode. This is what keeps walls and windows from bending.

    The the conditioning rail region of the universal graph.
  5. 05 Serves: Every mode

    One sampler, one exit

    Whatever path the image took, everything meets at a single KSampler. A last switch either saves the result or sends it to Ultimate SD Upscale for a high-resolution export. The comparer on the right shows a real run.

    The one sampler, one exit region of the universal graph.
Open the whole graph at full size

Eleven workflows, every one of them.

The universal graph is one of eleven workflows I exported for the platform. Here is each graph as it looks in ComfyUI, with the size of its export. Open any of them at full size to read the nodes. The universal graph is above; the two Flux 2 Klein edit exports share one card, and the Flux text-to-image graph that made several of the empty test rooms has nine nodes.

The Empty room graph in ComfyUI.Open full size

First semester18 nodes

Empty room

Stable Diffusion 1.5 with stacked ControlNets furnishes an empty room without moving its walls.

The Replace one object graph in ComfyUI.Open full size

First semester33 nodes

Replace one object

Florence-2 finds the object by name, SAM2 masks it and an inpaint pass replaces only that region.

The Replace with a reference graph in ComfyUI.Open full size

First semester33 nodes

Replace with a reference

The same masking, plus an IP-Adapter that copies a reference product into the masked region.

The Sketch to render graph in ComfyUI.Open full size

First semester20 nodes

Sketch to render

A line drawing is turned into a photographic render under Canny, M-LSD and depth control.

The Ultimate SD Upscale graph in ComfyUI.Open full size

First semester9 nodes

Ultimate SD Upscale

A tiled upscaler that regenerates the image in tiles at a low denoise to add detail.

The Flux 2 Klein edit graph in ComfyUI.Open full size

Second semester11 nodes

Flux 2 Klein edit

The source image, a prompt and up to three reference images go straight into an image-edit model. No masks, no ControlNets.

The SeedVR2 upscale graph in ComfyUI.Open full size

Second semester7 nodes

SeedVR2 upscale

Restores the whole frame at once, replacing the tiled upscaler and its seams.

The Photo to 3D model graph in ComfyUI.Open full size

Second semester44 nodes

Photo to 3D model

Background removal, Hunyuan3D 2.0 mesh, de-lighting, six painted views and a textured .glb.

Two generations of the edit pipeline.

First semester: Stable Diffusion 1.5 and ControlNet. To furnish a room without bending its walls, I stacked ControlNets (Canny edges, M-LSD lines and depth) on Stable Diffusion 1.5. To replace one object I chained Florence-2 to find it, SAM2 to mask it and an IP-Adapter to copy a reference texture. Each task was its own workflow.

Then I merged them into the universal graph above, 72 nodes behind nine switches. It worked, and it is the graph you just flew through, but every feature added another place for the routing to break.

Second semester: Flux 2 Klein. Flux 2 Klein 4B is an image-edit model: it takes the source image and a prompt, and optionally reference images, directly. Its graph needs no mask, ControlNet or preprocessing branch, so the whole edit fits in 11 nodes. I chose the 4B model partly for its Apache 2.0 licence. The 9B model's licence limits commercial use, and the thesis notes it also needs about 22 GB of VRAM against about 12 GB for the 4B.

What the Flux 2 Klein workflow does.

One 11-node graph, many jobs. Each result below was made with the Flux 2 Klein edit workflow; the image metadata records it. Several input rooms were themselves generated with Flux text-to-image, so the starting point is known exactly. Drag every slider, and switch between examples where there are several.

An empty white room with a dark wooden floor and a glass door to a garden.
The same room furnished with a grey sofa, armchairs, a rug, a coffee table, plants and framed prints.
BeforeAfter

01

Furnish an empty room, then keep adding to it

An empty room becomes a furnished one in one pass. Then references stack: a floor material, then a wallpaper, each added on top of the last result while the window and the walls hold still.

In
An empty room photo and a short instruction
Kept
Walls, window, door, floor lines
Out
A furnished room; with references, the same room re-finished
The empty room.The same room with a turquoise terrazzo floor from the first reference.The same room with the floor and a colourful patterned wallpaper from the second reference.
The Flux 2 Klein graph with two reference images loaded and the result in its comparer.Open full size
The run that stacked both references.
A grey-walled room with a slanted ceiling, a dark door, a TV unit and a wooden floor.
The same room styled with a light sofa, armchairs, a round table, a rug, a lamp and wall art.
BeforeAfter

02

Redesign a room that is already furnished

The edit does not need an empty room. Given a lived-in room it swaps the furniture and the styling and leaves the architecture alone.

In
A furnished room photo
Kept
Ceiling beams, door, windows, floor
Out
New furniture and decoration
A beach bedroom with a wooden bed in white linen, tall glass doors and a view of palms and the sea.
The same bedroom with the brown upholstered bed from the product photo.
BeforeAfter

03

Place a catalogue product into the photo

This is the shop-the-look step. I gave the edit this bedroom and a product photo of one bed. The bed in the room becomes that bed, with its fabric and colour, and the window, the light and the sea view stay.

In
A room photo and a product photo
Kept
Everything except the bed
Out
The room with that exact product in it
The product photo: a brown upholstered double bed on white.
The product photo passed as a reference.
The Flux 2 Klein graph run with the bedroom and the bed photo as inputs, with the result in its comparer.Open full size
The run, as it looked in ComfyUI.
A living room with a pale rug, grey sofas and a coffee table.
The input room.
The Flux 2 Klein graph with the living room and a red patterned rug as inputs; the comparer shows the room with the new rug.Open full size
The run: the room and the rug photo go in on the left, the result is in the comparer on the right.

04

Swap the rug for one from the catalogue

The same reference edit on a smaller object: the rug on the floor is replaced by a patterned rug from a product photo, and nothing else in the living room moves.

In
A living room photo and a rug photo
Kept
Sofas, table, walls, light
Out
The room with the new rug
A plain room with wooden cabinets, shelves and a window.A plain room with wooden cabinets, shelves and a window.A plain room with stone-textured walls and a small window.An ordinary bedroom.
The same room drawn as an anime illustration in daylight.The same anime room at night, with a lamp lit and a dining table.The same room as a Minecraft build with blocky furniture and lanterns.The same bedroom as a bright coastal beach house.
BeforeAfter

05

Restyle a whole room

The same graph can move a room into a different world: an anime illustration by day and by night, a Minecraft build, a coastal beach house. Pick an example, then drag.

In
A room photo and a style instruction
Kept
Layout and furniture positions
Out
The room in the new style
A teenage bedroom in daylight with a single bed, shelves and a window.A teenage bedroom in daylight with a single bed, shelves and a window.A teenage bedroom in daylight with a single bed, shelves and a window.
The same bedroom recoloured in brighter daylight.The same bedroom at night with warm lamps lit.The same bedroom at night with the curtains closed.
BeforeAfter

06

Turn day into night

Light is an edit too. One teenage bedroom, three results: recoloured in daylight, at night with the lamps on, and at night with the curtains drawn.

In
A daylight room photo
Kept
Every piece of furniture
Out
The same room in new light
A street of white modern houses under a cloudy sky.A street of white modern houses under a cloudy sky.A street of white modern houses under a cloudy sky.A street of white modern houses under a cloudy sky.A street of white modern houses under a cloudy sky.
The same street in heavy rain, the road wet and reflective.The same street under an orange sunset.The same street at purple twilight with lit windows.The same street drawn as a cartoon.A second cartoon version of the same street.
BeforeAfter

07

Change the weather outside

It works on exteriors as well. One street of white houses, five results: two cartoon versions, an orange sunset, a purple twilight and rain on wet asphalt.

In
A street photo
Kept
Every building and the street layout
Out
The same street in a new light or style
A cluttered room with clothes and rubbish on the floor, a bed with a heap of clothes and old furniture.
The same room tidied: the floor is clear and the bed is made.
BeforeAfter

08

Clean up a messy room

Clothes and rubbish are removed and the floor under them is filled in, while the bed, the chest and the window stay where they were.

In
A cluttered room photo
Kept
Furniture and walls
Out
The same room, tidy
A pen line drawing of a living room with shelves, a sofa, a coffee table and a rug.A black-and-white block-out of a modern living space.
A photographic render of the same living room.A photographic render of the same living space.
BeforeAfter

09

From a drawing to a render

A pen sketch or a black-and-white block-out becomes a photographic interior. The drawn proportions and openings are what the render keeps.

In
A line drawing or a grey block-out
Kept
Proportions, openings, furniture placement
Out
A photographic render
A black and white image of a room with cracked plaster walls, a chest of drawers and a table.
The same room in colour, with warm wood and plaster tones.
BeforeAfter

10

Bring colour to a black-and-white room

A monochrome room gets its colours back: wood, plaster and fabric, with the cracks in the walls and the furniture kept as they were.

In
A black-and-white room
Kept
Every crack and object
Out
The room in colour
A soft, low-resolution image of a sunflower field at sunset.
The same sunflower field, upscaled and sharp.
BeforeAfter

11

Restore detail at the end

Diffusion output can leave noise on smooth surfaces. SeedVR2 restores the whole frame at once; here it took an 813 by 512 image to 1706 by 1080. Drag across the sunflowers to see the difference.

In
A low-resolution result
Kept
Composition and colour
Out
The same image at twice the size, with detail
The SeedVR2 graph with the input and the upscaled sunflower field.Open full size
The SeedVR2 graph, with the run in it.
A ComfyUI graph run on a photo of an ornate brown leather armchair: its cut-out mask, a grey mesh, the armchair with shadows removed, six coloured render views, six painted views, texture maps and the final textured 3D preview.
The 3D workflow after a run on a photo of an armchair: mask, grey mesh, shadows removed, six views, texture maps and the textured result.

From a product photo to a 3D model.

A separate ComfyUI workflow turns one photo of a piece of furniture into a textured 3D model. It removes the background, builds the shape with Hunyuan3D 2.0, removes baked-in shadows from the photo, paints the unseen sides from six rendered views, patches texture seams and exports a .glb file with a 2048 px texture.

To run on a cloud GPU notebook it needed extra work: patching the Hunyuan3D nodes and compiling a custom CUDA rasterizer. The graph has 44 nodes.

Finding the furniture in a render.

A generated room is not much use if you cannot buy what is in it. The search service takes a room image, finds a piece of furniture and looks for similar products in a catalog.

RT-DETR detects furniture and I keep the most confident detection. Two models read that crop in parallel. SigLIP2 turns it into an embedding for visual similarity, and Qwen3-VL describes it as JSON: colour, material, style and room fit. The service filters the catalog by colour, material and style, then ranks what is left by embedding similarity. If the filter returns nothing, it ranks without the filter, so a search always returns results.

IntelliRoom: from a room image to ranked products A room image goes to a FastAPI service on my machine, which sends it over a zrok tunnel to a Kaggle GPU notebook. There RT-DETR finds furniture and crops the most confident detection. SigLIP2 turns the crop into an embedding and Qwen3-VL describes it as JSON tags, in parallel. The tags return to a tag snapper that maps them to allowed words, then ChromaDB filters by tags and ranks by similarity; if nothing matches, it searches again without the filter. The result is a ranked list of products. A second row shows catalog ingestion, run once per product. From a room image to ranked products The GPU models run on Kaggle. The catalog and the search run on my machine. My machine Room image FastAPI service catalog and search logic Tag snapper map to allowed words ChromaDB search filter by tags, then rank by similarity colour, material, style no matches: search again without the filter Ranked products Kaggle GPU notebook RT-DETR find furniture, crop the best one Qwen3-VL tags as JSON SigLIP2 embedding in parallel send image via the zrok tunnel tags embedding Catalog ingestion, run once per product Catalog images RT-DETR crops SigLIP2 + Qwen3-VL Tag snapper ChromaDB (store)
The GPU models run in a Kaggle notebook, reached through a zrok tunnel. The catalog, the ChromaDB index and the search logic run on my machine.

Tag clean-up

The vision-language model invents words such as "cream", "charcoal black" or "mid-century". A catalog filter needs a fixed list. A small snapper maps known synonyms first ("cream" becomes "beige"), then picks the nearest allowed word by character n-gram similarity. That keeps the filters working. It cannot fix a description that is wrong.

Licences decided two choices

I picked RT-DETR over YOLO because many YOLO versions carry GPL or AGPL terms and RT-DETR is Apache 2.0. Flux 2 Klein 4B was chosen on licence too, as above.

Choosing the Qwen3-VL size

I tried three sizes on two furniture images, a wicker sofa and a gold classic sofa, and recorded the time for each.

2B, about 9 s
Fastest, but on the first image it put a stray "json" before the JSON, which broke parsing.
4B, about 18 s
Valid JSON on both images. This is the one I used.
8B, about 23.5 s
Valid JSON on both. Its suggested complementary items were slightly richer, for example a crystal chandelier where the 4B suggested a gold floor lamp. It was 31% slower than the 4B.

The catalogue I made for the team.

IntelliRoom was built by a team of seven. My teammates built the web app, the backend, the marketplace and the 2D and 3D planner. Those products needed furniture to sell and to place, so I made the data they run on.

I generated every product with a ComfyUI workflow, running it through permutations of furniture type, colour and material: sofas, armchairs, beds, tables, shelves, lamps, rugs and curtains on a clean white ground. Then a vision-language model annotated each product to a strict format and a fixed taxonomy, so the marketplace filters and the furniture search all speak the same words.

A sheet of 158 generated product photos on white: sofas in many colours, armchairs, beds, tables, shelves, chandeliers, plants, rugs and curtains.
All 158 generated products in the catalogue folder, in one sheet.

A strict format

Qwen3-VL receives each product with a system prompt that allows one answer shape only: raw JSON, no explanation, no markdown, and every value taken from the allowed lists. If it is unsure it must pick the closest allowed value, never a new one.

{
  "color":                one of 14,
  "material":             one of 13,
  "style":                one of 13,
  "room_fit":             a list from 8,
  "complementary_styles": a list from 11,
  "description":          one sentence
}

When a model still drifts, a snapper maps known synonyms first (“cream” becomes beige) and then the nearest allowed word, so nothing outside the taxonomy reaches the database.

The taxonomy

Style new classicmodernscandinavianindustrialbohemianminimalistjapandicoastalrusticart decotraditionalheritage fusiondesert modern

Material solid woodengineered woodmetalglassleatherfaux leatherfabricvelvetlinenrattanmarbletravertineplastic

Colour blackwhitegraybrownbeigebluenavygreenredorangeyellowpinkpurplegold

Room salonliving roombedroomdining roomofficeoutdoorkids roombathroom

The thesis and the presentation.

The thesis covers the whole platform, graded A+. The presentation is 72 slides on the image edits and the furniture search, with before and after examples; the 3D workflow is not in it.