自动化我的 35 毫米胶片扫描流程
Automating my 35mm film scanning pipeline

原始链接: https://shannadige.com/blog/darkroom/

Shan Dige 构建了一个个性化数字暗房,以简化胶片摄影的后期流程,同时保留胶片拍摄的乐趣。过去,每卷 36 张的胶片在扫描和编辑上大约需要四个小时。他最初尝试让 Claude 通过 SANE 控制扫描仪,但由于扫描仪托架控制出错,硬件险些损坏,因此他改变了方案:现在使用 VueScan 扫描,并通过自定义工具自动完成负片转换、整卷色彩校正、灰尘检测、基于上下文的图像修复、编辑控制以及 AI 生成元数据。 本地运行的 Qwen3-VL 模型会为每张处理完成的照片添加标签,使不断增长的照片库能够被搜索。部分精选照片会发布到 Cloudflare R2,并通过一个模仿胶卷盒、毛毡桌面和实体胶片的交互式画廊展示。整个项目在 11 天内完成,共有 64 次代码提交;画廊目前已收录 22 卷胶片、共 314 张照片,时间跨度可追溯至 2020 年。 这个项目最终减少了重复性的后期处理工作,同时保留了模拟摄影从容、动手参与的魅力,让人们有更多时间探索、拍摄和分享。

一个 Hacker News 讨论帖探讨了如何自动化 35 毫米胶片扫描流程。一位评论者询问了基于 NumPy 的处理流程的细节,包括如何使用空白胶片作为参考,以及如何通过整卷胶片层面的测量来校正橙色蒙罩、白平衡和色调曲线。他们还询问是否使用了校准设置或针对特定胶片型号的配置文件,询问图中 OpticFilm 7400 的价格及适用性,并了解相机扫描,以及如何在保持色彩转换一致性的同时,实现胶片传输和拍摄过程的自动化。 另一位评论者称,这段详细的问题可能是由人工智能生成或编辑的,并引用了 HN 的相关规则,同时承认有时无法确定这一点。原发帖者澄清,这些问题是通过语音输入的,并由转录应用进行了格式化。提交时,该帖子获得了 6 个分数,并有 3 条评论。
相关文章

原文

View the experience

I love photography. There is a special feeling to seeing an image through a lens, organizing it to compose a story, and working with the resulting photo. I had cycled through DSLR and mirroless cameras before falling in deep love with the Canon AE-1P, an analog SLR that my dad traveled with around the world before settling down in the States.

Film photography is simple, but particular: you expose reflected light against a strip of plastic and burn-in a chemical image. Depending on the light conditions, film stock used, and lens, you’ll get magically unique compositions.

For years my process looked like this: load film and take photos, send the film to a lab and wait for development, pick up said film, cut the negatives into strips, load them into a holder, capture the negative of each frame in with a specialized scanner, open every file in darktable, invert it by hand, make topical edits, then decide where to store and/or share the exported image. At first this was an exciting process for me. Then as the number of rolls increased, so did my effort to do this for 36 frames per roll.

A desk lit by a lamp, with a strip of negatives hanging from it, VueScan open on a monitor showing an orange negative, and film holders, a blower and a brush next to a blue Plustek scanner.

On average it would take me about 4 hours to fully scan in a roll of 36 photos and complete edits. It requires delicacy in handling film especially to avoid dust or scratches on the final image. Safe to say, the process grew weary on me quite fast. I was spending more time processing my images than actually taking them. So I began looking for ways I could cut some time, or as the CEOs like to say, “streamline operations” across my personal digital lab.

Giving Claude destructive hardware capabilities

My first hypothesis was if I could take myself out of the loop entirely. I’d have Claude drive the scanner over SANE (open-source scanner driver stack) and handle scanning, colour conversion and edits end to end.

On the first scan, Claude used SANE with inversed X/Y scanbed directions and nearly broke the gear mechanism inside the scanner. So I unfortunately killed time by needing to perform an emergency surgical operation on the scanner to save $200 from being spent on a new one.

Chat: Blank white scans

Sep 20, 2026

  1. Shan 4:54 pm

    there is definitely film in there, maybe its the scanning settings you opted for

  2. Claude 4:56 pm

    I've been tracing why the scans come out white, and your guess about settings can be ruled out. … Instead, every one of the 856 rows is identical: smooth vertical bands from the lamp's uneven illumination, with zero variation from top to bottom and no image detail. … So the sensor saw the same unobstructed line of light for the whole scan.

  3. Shan 5:01 pm

    i tried with vuescan, but the sensor or the carriage is not moving, you must have done something wrong

  4. Shan 5:04 pm

    its definitely in a bad state. can you check on the scanner, until i let you know its moving. i did hear some clicking earlier, so it might have been going an opposite direction

  5. Claude 5:05 pm

    I found what the clicking was, and it came from my scans. … At the end of every scan, the genesys backend sends the carriage back with a blind reverse move: 7010 steps at 900 dpi, and more at 3600. It assumes the carriage travelled forward during the scan. … So each scan ended with the motor driving a carriage that was already parked backwards into its end stop. That is the clicking you heard, and your read on the direction was right. I ran seven scans, so it happened seven times.

The Plustek scanner with its case removed, showing the carriage, a threaded rod, a spring and the motor gear.
Surgery. Pushing a rod and gear that did not want to be pushed back into place.

I ended up working with what was already working well. VueScan was the software I’d licensed way back when - given that it had the best compatibility with my scanner, and given that I didn’t have a robot arm automating the physical operation of loading and scanning, I’d just use this myself and find a solution that can handoff from right after this.

Studio

Learning from failure fortunately turned my thought process around. I work in VueScan the way I always have, so I needed some way to automate the processing of those scans. After a handful of individual tests against image data I had tested against, I had a full suite of tools working in combination to help me.

Negative Conversion

Converting negatives into positives is mostly plain code. The inversion is a short numpy routine, that works in film density and measures color across the whole roll before adjusting each frame within limits of its negative. So thirty-six frames look consistent to one full roll and a sunset doesn’t get radically color-corrected. This was something I tended to struggle with even doing manually. My agent determined that using the blank leading slot of a roll would be a good reference for how color correction should be weighted against the rest of the frames. Before building anything else, we ran it on an old roll as a go or no-go test.

Chat: Conversion test

Sep 21, 2026

  1. Shan 10:35 am

    start the conversion test on film/valentines2026

  2. Claude 10:40 am

    The conversion test passed on 28 of 29 frames. Custom conversion works well enough to build on, and it needs no darktable to get there. … Mine are brighter and more neutral, while your exports lean teal and dark (the Hotel del Coronado sky, the beach portrait, the garden). That is taste as much as correctness, so you should judge.

  3. Shan 10:40 am

    i like your direction, run the dust detection test

Sample negatives vs. converted positive (those scratch marks are characteristic of the film stock)

Dust Removal & Editing

The models come in where plain code runs out. Dust is found by image analysis on the negative and marked for removal. This is harder than it sounds: on a beach frame the first detector flagged about 2,000 sun glints on the water as dust. The fix was to affix context and act only where surroundings are smooth. The spots it finds are filled by LaMa (inpainting model), with detail copied back in from nearby film spots so the patch doesn’t look smudged. Kind of like the repair tool on Photoshop.

Not every single area needs to be filled. I have a custom threshold set where I can hold grainy spots for review, and approve/deny them individually or in batch.

This also created a need to adjust light and color properties of each image individually to account for graininess, so I had exposure, contrast, temperature, and other controls embedded in reach.

The frame review screen in studio: a frozen lake under a pale sky, covered in circles marking dust and scratches, with sliders and dust counts in a panel on the left.
Frame review. Green circles were dust-repaired automatically, amber ones held for review.

Metadata

Indexing data for analog film can be time-consuming, especially if I’m working across separate tools on my own. This was a “hmm, why not?” problem to address since now that I’m using technology I can extend it to identify a photo for easy searching later on.

So Qwen3-VL runs locally in Ollama when scans come in, looks at each finished frame and drafts tags for it in about five seconds. That combined with camera, lens, date, and film stock data gives me a comprehensive library to easily search from.

The Gallery tab of the review panel beside a portrait of a woman in front of a Green House Motel sign, with drafted tags: woman, sign, motel, plants, flowers, greenhouse.
Tags drafted by Qwen3-VL in 3 seconds, fixed once I pick the frame.

My part is now the part I can thoroughly enjoy, which is looking at the results I’ve snapped and finding inspiration to snap more.

The studio app with valentines2026 selected in the sidebar's list of roll folders: a roll header with Revolog Rasp 200, the Canon AE-1P and notes about the Chicago Botanic Garden's orchid show, and a contact sheet of all 28 converted frames marked live or check.

Once I had gotten a few rolls through the pipeline, the next question was where they’d live.

Typically they’re stored on my 4TB HDD that I’ve set to eternally spin while plugged into my machine. But while off the rush of building enterprise-software-for-one, I wanted to explore a way to share via the world wide web.

Publish Workflow

I have a Cloudflare account that gets the occassional activity from visitors on some CDN content I have for my personal site, and what better way to max out the free plan than uploading all my images to my own R2 bucket? So I extended the studio to enable publishing.

The publish dialog for the valentines2026 roll over the studio: label Valentines 2026, stock Revolog Rasp 200, date 2026-02, a private-link checkbox, and all 23 picked photos numbered in the order the gallery shows them.
Publishing a roll. The picked frames go to R2 in the order shown, with their tags and nothing else.

Showcasing Photos by Roll

A grid of thumbnails felt too cheap for a publish experience. I continued to scan more rolls throughout the days and recounted my earlier times dropping off my rolls for development. Seeing the lab technicians unroll the film itself to spool to their C41 processor gave me a simple idea to emulate the roll itself.

I do acknowledge that this is not the most accurate form of realism, but it was a very fun idea to play with and evolve. I ended up with a felt table covered in film canisters modeled for 3js, each with real label art and random scuff marks. Pick one up and you can yank the film out to expose the frames. Then it just falls back onto the felt table.

I was able to source the effective

Demo walkthrough; credits to Opus-5.5 for recording

My corner of the Internet

In total this project took 11 days and 64 commits. The gallery has 22 rolls and 314 photos dating all the way back to 2020.

I will continue to add to this as I purge more money on rolls and development. It’s my corner of the Internet, for you to unplug and enjoy if you choose to revisit.

There’s been something just as alluring about creating a site like this, versus just engaging the scanner and process itself. The manual process is something that someone might enjoy and wouldn’t want to delegate. At least for me, it keeps me off the computer and focused on enjoying the time I have exploring the world. Capturing it in a different perspective. ■

Shan in a wide-brimmed green hat and a white shirt, looking down at a black Canon film camera held in both hands, on a tree-lined road with a van and a stall of king coconuts behind him.
联系我们 contact @ memedata.com