Wearsper

Publications / Technical Case Study

Building an AI Wardrobe Intelligence System

From clothing images to personalised outfit recommendation: how Wearsper turns a photograph of a garment into structured data a recommendation system can reason over.

Teslim Bello
Teslim Bello · Founder & AI/Product Developer, Wearsper
September 11, 2026 · 16 min read

Teslim Bello is the founder and AI/Product Developer behind Wearsper. He holds an MSc in Data Science (Distinction, University of East London) and a BSc in Mathematics and Statistics, and has led the product's AI, backend, and application development.

↓ Download publication (PDF)

1. Overview

A photograph of a shirt is, to a computer, an unstructured grid of pixel values. A person looking at the same photograph immediately understands it as a garment with a category, a colour, a level of formality, and a set of other garments it would or wouldn't pair well with. Wearsper's core technical problem is closing that gap: turning a wardrobe of ordinary photographs into a structured representation that a recommendation system can actually reason over, and using that representation to suggest outfits from clothes the person already owns.

This is a case study of the pipeline as it's actually built today, not a proposal or a roadmap presented as finished work. Sections are written to distinguish clearly between what is implemented and what is a planned future direction, and development-time observations are presented as exactly that, not as formal benchmarks.

2. The problem

The simplest version of a digital wardrobe app is a photo album: a folder of pictures the user manually sorted into categories. This is a reasonable starting point, but it caps out quickly, because a folder of images has no way to answer the questions an outfit recommendation actually depends on:

  • What category is this item: a shirt, a jacket, a pair of trousers?
  • What colour is it, and does that colour combination work with another item?
  • Is it formal, casual, or something in between?
  • Does the person already own something that would clash or compete with it?
  • Is it appropriate for the current weather or occasion?

None of these questions can be answered from a raw image file. They require the image to first be converted into attributes, discrete, structured facts about the garment, before any reasoning about outfits can happen at all. This is the reason Wearsper's architecture treats image understanding as a distinct, upstream stage from recommendation, rather than asking a single model to go directly from "here are some photos" to "here's an outfit."

3. From images to structured wardrobe intelligence

When a user photographs a clothing item, the image moves through a sequence of distinct stages before it becomes a usable wardrobe entry:

ClothingphotoObjectdetection(YOLOS)Backgroundremoval(U2Net)Attributeclassification(CLIP)Structuredwardrobe itemEach stage narrows an unstructured image down to a small set of concrete, storable facts.
Figure 2, Image-to-wardrobe pipeline. A photographed garment passes through detection, segmentation, and attribute classification before it's stored as a structured wardrobe entry.

I designed the pipeline to use a locally-run object detection model to first localise the actual garment within the photo, separating it from background clutter, other objects in frame, or the person wearing it. A separate background-removal step produces a clean cutout of the item, which is what the user sees represented in their digital wardrobe. A third stage, built on a CLIP-based vision-language model, classifies visual attributes such as colour and style category.

I chose three separate, specialised models rather than one general-purpose model asked to do everything, because each stage solves a genuinely different problem: finding where the garment is, isolating what it looks like visually, and describing what kind of thing it is. Chaining specialised stages together produced more reliable, more debuggable results during development than a single larger model attempting the same task end-to-end.

On confidence and uncertainty. Not every photo is classified with equal confidence. Wearsper supports two classification modes: an automatic mode that applies the model's best guess directly, and a manual review mode that surfaces lower-confidence items for the user to confirm or correct before they're treated as final. This exists because a wrong automatic guess in a wardrobe app has a real cost: it directly corrupts the exact data a later recommendation depends on.

4. Representing the wardrobe as structured data

Once a garment has been through the pipeline above, it isn't stored as "an image with a caption." It's stored as a record with distinct fields, category, colour, style attributes, alongside the processed image itself. This is a deliberate design choice: the wardrobe is a structured dataset the app can query and reason over, not an unstructured photo library with metadata bolted on afterward.

A simplified version of one wardrobe item's structure looks like this:

{
  "id": "a1b2c3d4-...",
  "category": "tops",
  "garment_type": "shirt",
  "colour": "navy",
  "style": "smart-casual",
  "classification_status": "done",
  "image_url": "...",
  "processed_image_url": "..."
}

This is a simplified illustration of the shape of the data, not a literal database export. The important property it demonstrates is that a garment's category, colour, and style are each independently addressable fields, not text buried inside a single description. That's what makes it possible for the recommendation layer, described next, to filter and reason over the wardrobe systematically, rather than needing to re-interpret every image from scratch on every request.

5. The recommendation layer

Once a wardrobe is represented as structured data, generating an outfit recommendation becomes a reasoning problem over that structured data, rather than a raw image-understanding problem. Wearsper's recommendation layer takes the user's structured wardrobe, along with context such as an occasion the user describes or the current weather, and uses an AI reasoning step (currently Google's Gemini) to propose a coherent outfit from the items that already exist in the wardrobe.

Structured wardrobeUser contextOccasion / weather /usage limitsAI reasoning(Gemini)Candidate outfitStructural validation(items exist in wardrobe)
Figure 3, Recommendation pipeline. Structured wardrobe data and user context are passed into the reasoning step; its output is then checked against the wardrobe before being shown to the user.

One architectural decision matters here more than any specific model choice: I deliberately did not treat the language model as the source of truth for what's in the wardrobe. The computer vision stage described in Section 3 already produced the factual record of what the user owns. I built the reasoning layer to operate on top of that existing structured record, it doesn't re-derive it, and its output is checked against it. A recommendation is only useful if the items it names actually exist in the user's real wardrobe; a model that occasionally proposes a garment that doesn't exist is a much more contained, checkable failure than a model whose classification of the physical wardrobe itself can't be verified at all.

6. Why this architecture

I separated "what does the user own" from "what should the user wear" into two distinct stages, rather than one end-to-end model. This was a deliberate trade-off, not a default. The advantages I observed during development:

  • Contained failure modes. If the reasoning stage makes a mistake, it's a recommendation problem, not a data-integrity problem, the underlying wardrobe record stays correct regardless.
  • Debuggability. When an outfit recommendation looks wrong, it's possible to check whether the wardrobe data was correct and the reasoning was faulty, or the wardrobe data itself was wrong at the classification stage. A single fused model would not offer this distinction.
  • Cost and latency control. Classification happens once, at upload time, and is cached as structured data. Recommendation requests don't need to re-analyse every image on every request, they operate over data that's already been extracted.

The trade-offs are real too. Running a multi-stage pipeline means more moving parts, more places for a failure to occur, and a genuine dependency on the classification stage being accurate, if an item is misclassified upstream, that error propagates into every future recommendation involving it, silently, until someone corrects it. This is discussed further under limitations.

7. Engineering Problems and Technical Decisions

A selection of concrete problems I encountered during development, and the reasoning behind how I resolved each one, rather than a generic list of "AI is hard" problems.

Inconsistent classification confidence

Problem. Real user-submitted photos vary enormously in lighting, framing, and background clutter compared to clean product photography. Detection and attribute confidence scores vary accordingly.

Investigation. I tracked classification confidence scores across a range of real uploaded photos and found that low-confidence predictions were common enough that silently accepting every automatic guess as fact would regularly corrupt wardrobe data.

Decision. I decided wardrobe data integrity had to take priority over full automation, so I designed a dual classification mode rather than trusting the model unconditionally.

Implementation. I built an automatic mode that applies the model's best guess directly, alongside a manual review mode that surfaces lower-confidence items for the user to confirm or correct before they're treated as final.

Result. Wrong automatic guesses no longer silently corrupt the data a later recommendation depends on, at the cost of occasionally asking the user to confirm an uncertain item.

Concurrency in the image-processing pipeline

Problem. Running multiple garment uploads through the same backend process concurrently caused the entire worker process to crash.

Investigation. I traced the crash to the background-removal library's underlying numerical routines, which were not safe to run from multiple threads at the same time within a single worker process.

Decision. Rather than serialising the entire pipeline and losing concurrency everywhere, I decided to isolate the fix to just the specific operation that was actually unsafe.

Implementation. I added an explicit lock around that one background-removal call, leaving every other stage of the pipeline free to run concurrently.

Result. The crash was eliminated while concurrent throughput was preserved for every stage that didn't share the underlying constraint.

Resource contention under load

Problem. Running multiple machine-learning worker processes on a single host produced a severe, measured slowdown in per-item classification time.

Investigation. I found that each worker process was independently trying to use every available CPU core for its own inference, so the processes were competing for the same cores simultaneously instead of sharing them.

Decision. I decided each process needed an explicit, bounded share of CPU resources rather than being left to compete freely.

Implementation. I set explicit thread-count limits per process.

Result. Per-item classification time returned to expected performance under concurrent load.

Third-party integration correctness

Problem. A real production bug caused usage-limit resets to fail after a subscription tier upgrade.

Investigation. I traced the failure to the backend reading field names that didn't actually match the billing provider's documented webhook response schema.

Decision. I decided the fix needed to be verified directly against the provider's actual documented payloads, rather than patched based on assumption.

Implementation. I corrected the field names to match the provider's real, documented response schema.

Result. Usage-limit resets now correctly reflect a user's current subscription tier after an upgrade, and the incident became a standing reminder to verify third-party API behaviour against real documentation and sample payloads, not memory.

8. Performance and observations

Formal benchmarking, with a controlled methodology and representative dataset, remains future work. What follows are observed request timings from development, included to give a genuine sense of where time is currently spent in the pipeline, not as a performance claim.

Stage (recommendation request)Observed duration
Wardrobe fetch~605 ms
Request processing before model call~1.1 s
Gemini reasoning request~14.1 s
Total observed~15.1 s

The large majority of end-to-end latency currently sits in the language model reasoning call itself, not in Wearsper's own data-fetching or processing logic. This is a useful, honest data point for prioritising future latency work: optimising the wardrobe-fetch or pre-processing stages further would have limited effect on the overall experience compared to work on the reasoning call itself.

Separately, the classification pipeline (Section 3) logs its own per-stage timings for every processed item, download, detection, segmentation, attribute classification, and upload, which is what surfaced both the concurrency and CPU-contention issues described in Section 7. These are development-time engineering logs used for debugging, not a benchmark suite.

9. Product architecture

UserMobile app (React Native / Expo)Backend API (FastAPI / Railway)Image understanding / ML layerYOLOS · U2Net · CLIPStructured wardrobe storeSupabase / PostgreSQLRecommendation / reasoning layerGemini
Figure 1, System architecture. The mobile app talks only to Wearsper's own backend; the backend coordinates between the ML layer, the structured data store, and the reasoning layer.

I designed the system so the mobile client never talks to the machine-learning pipeline or the reasoning layer directly, every request goes through the backend API, which is responsible for orchestrating classification, persisting structured wardrobe data, and calling the reasoning layer with that data as context. This keeps the client simple and means the underlying models or providers can change without requiring a client update.

10. What makes wardrobe intelligence different

It's worth being precise about what this system is not. It is not a generative fashion tool that produces new clothing designs or dresses a person in garments they don't own. The entire premise is the opposite: the system is constrained to reason over a specific, real, individually-owned inventory. The value isn't in generating novel outfits in the abstract, it's in making better use of clothes that already exist, which is a meaningfully different, more constrained, and arguably harder problem than open-ended fashion generation, because every recommendation has to remain grounded in a real, verifiable set of physical items.

11. Current limitations

A serious technical account of this system needs to be honest about where it currently falls short:

  • Classification is not perfect. Detection and attribute classification can be wrong, particularly on ambiguous garments, unusual lighting, or overlapping items in a single photo. The manual review mode mitigates but doesn't eliminate this.
  • Colour and style are inherently somewhat subjective. A model's judgement of "navy" versus "dark blue," or what counts as "smart-casual," won't always match every individual user's own categorisation.
  • Outfit compatibility reasoning is still relatively coarse. The system does not yet incorporate a learned, personalised model of an individual user's own taste beyond what's inferable from their stated preferences and wardrobe contents.
  • No large-scale evaluation exists yet. Observations described in this article come from development and early real-world usage, not a structured, large-sample user study.
  • Latency is dominated by the external reasoning call (Section 8), which is a dependency outside Wearsper's own direct control.

12. Future research and development

Distinguishing clearly between what exists today and what's a planned direction:

Implemented

Weather-aware recommendations, using current conditions as context for the reasoning layer.

Planned

Wardrobe gap analysis: identifying categories or combinations missing from a user's existing wardrobe, rather than only recommending from what already exists.

Planned

Learned personal preference modelling: moving beyond stated preferences toward a model that improves from a user's actual accept/reject feedback on recommendations over time.

Planned

Embedding-based wardrobe representation: supplementing discrete categorical attributes with learned visual embeddings, to better capture compatibility that's hard to express as a fixed set of fields.

Planned

Formal recommendation evaluation: a structured methodology and dataset for measuring recommendation quality, replacing the development-time observations described in Section 8.

Planned

Latency optimisation of the reasoning call, given it's currently the dominant cost in end-to-end recommendation time.

13. Conclusion

The underlying problem this system addresses, turning unstructured personal visual data into a structured representation that a reasoning system can act on reliably, is broader than clothing. The specific decision that has mattered most in building it is keeping the factual record (what a person actually owns, as determined by computer vision) architecturally separate from the reasoning applied on top of it (what they should wear, as determined by an AI model). That separation is what keeps the system's failures contained and debuggable, and it's the design principle most worth carrying forward as the reasoning layer itself continues to improve.