Reshoot any object from a controlled camera position: feed a photo, ask for a different azimuth/elevation, get the same subject from that angle. First camera-control LoRA for Qwen-Image-2.1 — the newest Qwen image base (unified generate + edit, native RGBA), where this format did not exist yet.
<mva> — every caption/prompt starts with itclose-up variant of each → 72 addressable framingsv2 is trained on v1's documented weak spots (characters, OOD identity detail) and is the
recommended download. v1 files remain untouched in checkpoints/; the <mva> grammar and pose
dictionary below are unchanged.
Recommended v2 file:
checkpoints_v2/angles_v2_full_qwen21_multiple_angles_v2_qwen21_multiple_angles_v2_000001500.safetensors
(step 1,500 · 319 MB · rank 64)
v2 orbit demo — the golden retriever reshot through all 12 azimuths at eye level (step 1,500, single seed per frame):

Full labeled strip: examples/orbit_strip_v2.jpg. Also new:
the orange-cat orbit, protocol-matched to v1's orbit_cat.gif — examples/orbit_cat_v2.gif.
| v1 | v2 | |
|---|---|---|
| Training pairs | 5,028 | 13,328 — Dome-Objaverse character-prioritized (9,376) + 1,986 license-filtered rigged characters (3,952) |
| Rank / alpha | 32 | 64 |
| Base precision | convrot8 int8 | bf16 full precision |
| Timestep sampling | shift | weighted |
| Recommended checkpoint | step 1,000 | step 1,500 |
| Checkpoint files | checkpoints/ | checkpoints_v2/ |
Checkpoint evidence (stated plainly): two independent reads agree on step 1,500.
(a) The run's per-250-step sample grids
(samples/qwen21_multiple_angles_v2/samples/) —
angle-following solid from step 1,000, peak ~1,000–2,000, slight orientation drift at 2,500.
(b) An out-of-distribution real-photo curve
(benchmarks/v2_curve/ — cat, dog, and a third held-out subject,
v1@1000 vs v2@500→2,500 at the same prompt and seeds): v2 holds identity and background detail at
least as well as v1@1000 on all three subjects, with no drift visible at step 2,500 (the drift
seen in the training-sample grid does not reproduce on real photos). Step 1,500 stays the
recommendation as the balanced point; 2,000–2,500 are usable for stronger angle-baking.
Character test (benchmarks/v2_verify/character_sheet.jpg):
three rigged characters from the Linzhan training data — a subject class v1 never saw — rendered
at back view and top-down with v1@1000 vs v2@1500. v1 attempts the poses (rendered characters
resemble dome objects) but softens and drifts on character-specific structure; v2 holds identity
and sculpted detail (hair spikes, creature forms) more faithfully at the hard poses. Honest scope
note: these are in-distribution subjects for v2, so this verifies the character data took;
generalization to arbitrary real-world characters rides on the OOD curve above.
Download this one: multiple_angles_step1000.safetensors (repo root, 159 MB).
It is the step-1,000 checkpoint — selected from the training run's ten saved checkpoints by visual
evaluation (see the examples below): it is where angle-following, identity preservation, and render
detail all peak together. Every example image on this card was produced with it.
All checkpoints were saved every 250 steps of a 2,500-step run; they are not interchangeable in character:
| File | Verdict |
|---|---|
multiple_angles_step1000.safetensors (root) | Use this. Best angle-following + identity + detail. |
checkpoints/…_000001500.safetensors | Alternate — comparable angles, slightly softer detail. Try it if step 1,000 feels too weak for your subject. |
checkpoints/…_000002500.safetensors | Final step — stronger-baked. Angles still follow, but drift begins: outputs start copying the reference view instead of moving the camera. |
checkpoints/…_000000250–750.safetensors | Undertrained — angle-following incomplete. Keep only for studying the training curve. |
checkpoints/…smoke….safetensors | Pipeline smoke test artifact — ignore. |
Rule of thumb: start at strength 1.0; if the reshot drifts toward copying your reference photo, lower the strength toward 0.8 rather than switching checkpoints.
Does it work on everyday photos it never saw? Dog, cat and apple from Wikimedia Commons, step-1,000 checkpoint, same prompt grammar:
Golden retriever · <mva> front-right quarter view, eye-level shot

Golden retriever · <mva> back view, eye-level shot

Cat · <mva> front-right quarter view, eye-level shot

Cat · <mva> back view, eye-level shot

Apple · <mva> front-right quarter view, eye-level shot

Apple · <mva> back view, eye-level shot

Generalizes to real photos: the subject rotates to the requested view and the scene mostly survives, though identity fidelity on out-of-distribution subjects is good-not-perfect (fine fur detail softens). Photo credits (CC): Golden Retriever Carlos, Cat03, Red Apple.
Front view in, captioned angle out — rendered at the recommended step-1,000 checkpoint:
<mva> right side view, high-angle shot

<mva> back view, eye-level shot — the front features are gone; genuinely the back of the object

<mva> front-left quarter view, eye-level shot close-up

<mva> left side view, eye-level shot

These are step-0 renders from training — the adapter is zero-initialized, so they show the
base Qwen-Image-2.1 attempting the identical caption + control image: the camera mostly stays on
the original front/three-quarter vantage in both natural-language and <mva> phrasings.
base · <mva> right side view, high-angle shot

base · <mva> back view, eye-level shot

base · <mva> front-left quarter view, eye-level shot close-up

All 40 sample grids across training (4 poses × every 250 steps, fixed prompts) are in
samples/ — including the step-2,500 grid if you prefer the stronger-baked look.
Animated comparisons (a 12-azimuth orbit of the golden retriever, and input/base/LoRA loops) are
also in examples/ as GIFs if you want the moving versions.
Protocol: 24 objects excluded from training, 6 poses each (144 test cases); both arms rendered
with matched prompts; each generation scored against the ground-truth dome render of the
requested pose (CLIP ViT-B/32 image–image cosine). Full per-render numbers:
benchmarks/bench_results.json · side-by-side montage:
benchmarks/bench_montage.jpg.
| Pose | LoRA (step 1,000) | Base |
|---|---|---|
| right side · eye-level | 0.850 ± 0.092 | 0.860 ± 0.090 |
| back · eye-level | 0.854 ± 0.069 | 0.910 ± 0.052 |
| left side · elevated | 0.813 ± 0.086 | 0.839 ± 0.084 |
| front-right quarter · high-angle close-up | 0.817 ± 0.074 | 0.830 ± 0.056 |
| back-left · top-down | 0.827 ± 0.060 | 0.841 ± 0.058 |
| front · high-angle | 0.829 ± 0.056 | 0.863 ± 0.057 |
| mean | 0.832 ± 0.074 | 0.857 ± 0.072 |
Read this honestly — the metric, not the LoRA, is the story. CLIP image–image cosine against a same-object ground truth is nearly viewpoint-invariant: any two views of the same object on a similar background score 0.8–0.95 whether or not the camera actually moved. So this table measures global image similarity (background, composition, polish) — on which the un-LoRA'd base produces more globally-similar images. It cannot distinguish "moved the camera correctly" from "stayed put", which is the capability this LoRA adds (see the visual A/B above: base's "back view" still shows front-facing features the requested view cannot contain).
The right quantitative protocol — and the reason these ground-truth renders are published — is pose-retrieval accuracy: score each generation against all six ground-truth poses of its object and check that the requested pose wins. That v2 scoring needs one more render pass; the dataset, the prompt grammar, and the held-out protocol here make it fully reproducible by anyone.
For the capability itself, the controlled visual evidence above is the primary demonstration: matched prompts, same control images, base vs LoRA.
<mva> {azimuth}, {elevation}[ close-up]
| Label | Azimuth |
|---|---|
front view | 0° |
front-right view | 30° |
front-right quarter view | 60° |
right side view | 90° |
back-right quarter view | 120° |
back-right view | 150° |
back view | 180° |
back-left view | 210° |
back-left quarter view | 240° |
left side view | 270° |
front-left quarter view | 300° |
front-left view | 330° |
| Label | Elevation |
|---|---|
eye-level shot | 0° |
elevated shot | 30° |
high-angle shot | 60° |
top-down shot | 90° |
Append close-up for the 62%-crop framing. Example:
<mva> right side view, high-angle shot close-up
Gradio Workflow Space — akhaliq/qwen21-multiple-angles-workflow: canvas UI, photo in → camera knobs out.
ComfyUI — load the LoRA with any Qwen-Image-2.1 workflow (LoRA strength 0.8–1.0), pass your photo as the edit/reference image, prompt with the format above.
diffusers (QwenImage21Pipeline, edit mode = pass the image):
image = pipe(
prompt="<mva> back view, eye-level shot",
image=input_image, # front view of your subject
num_inference_steps=40,
true_cfg_scale=1.0,
).images[0]
arch: qwen_image_2, control-image conditioning (block-causal reference
attention). v1: rank 32, convrot8 int8 base, shift timesteps. v2: rank 64, bf16 full-precision
base, weighted timesteps. Both: adamw8bit, lr 1e-4, caption dropout 0.05, 512², 2,500 steps.checkpoints/, v2 in checkpoints_v2/ — every 250 steps + samples, so the
training curve is inspectable end to end.benchmarks/v2_curve/ (see v2 section for the verdict).Credit to fal's Multiple-Angles LoRA for Edit-2511 for the caption grammar this format standardized on.