为 HDR 显示设备导出照片

本文建议使用 Chrome 浏览器观看。本文建议使用 PC / 苹果设备观看。

本文用 HDR 显示设备观看效果更佳。

想了好久标题怎么取,因为 HDR 这几个字在摄影领域早就有了自己固有的含义。本文并非介绍不同曝光设置下的照片堆叠的处理技术,而是介绍如何让自己拍摄的照片在新一代 HDR 显示设备上充分利用显示设备的高动态范围获得更好的显示效果

为 HDR 显示设备导出的 AVIF 图。目前由于 HDR 照片生态仍然不完善,并非全部设备可以正常查看这张照片。
通常 Chrome 可以准确显示(包括 HDR 和 SDR 显示器)。用 Firefox 查看会明显偏暗,一些 Android 手机看颜色可能是错误的。
这张是常规的 SDR JPEG 图片

背景

最近 Nikon Z8 发布,B站上有个评测视频【我路过这个世界并截下一帧 |尼康Z8评测 |4K HDR】。评测里面大量展现了雪山、银河等高光比场景,虽然我只有个 500nit 的 iPad mini 但苹果还是有一定的 HDR 展示能力,看起来效果确实不错。视频出来那两天这个评测让我周围不少同学都说想从索尼换门到尼康。

但是,转念一想……

我尼康也用了快十年了,我 10 年前买的 D750 就已经有了一块 14 bit 的传感器,那么我拍摄的照片理论上完全可以支撑起 HDR 10 bit 多出来的色深的。想了想我也拍过雪山(虽然菜),如果真的有个 HDR 显示器,我照片肯定能够展示的更好看。那怎么才能把 RAW 导出成 HDR 显示器能看的格式呢…… emmmmm 到了知识盲区了(有空再想)

带着这样的反思,又过了一周,正好看到新闻(其实是四月底)说,Adobe 最近更新了 Camera RAW 支持 HDR 编辑了,但 Lightroom 还没支持。这看起来正是我需要的东西,所以我就 Follow 了一下文章流程,导出了 HDR 照片。

我办公用的设备和 PC 都没有 HDR 显示器,我只有个索尼 4K 电视支持 HDR 输出。另外有 iPhone SE (2nd gen) 和 iPad mini 6 自带的屏幕最亮只有 500 尼特,算是个残血版本 HDR 屏幕,可以用来验证。

生成照片的处理流程

下面的流程在一台 SDR 显示器的 Windows 10 操作系统下完成

如上图,在 Camera RAW 的设置中启用 HDR 支持,然后重启 PhotoShop 重新打开后,可以看到编辑器多了一个 HDR 按钮,点击之后直方图右侧会多出一段 HDR 亮度的内容

我只有 SDR 显示器,所以这时候编辑 HDR 范围的内容会看到这部分内容是被 Clip 掉,但可以通过勾选下面的“可视化 HDR 范围”来查看这部分的亮度信息

Camera RAW 的常规功能这里就不介绍了,处理之后我只需要保存 HDR 格式的图片,不需要通过“打开”导入到 Photoshop,这时点击右上角的按钮保存即可。

导出图片的界面,先关注红色框的内容,需要勾选上 “启用 HDR 显示器” 才能选择 HDR 色域,可以选择的包含 P3 和 Rec.2020,这里我选择了最广的 Rec.2020。

然后是蓝色框里面的格式选项。按照 Adobe 的介绍看起来 AVIF 是目前对浏览器兼容性最好的 HDR 照片格式。我的目标就是把照片导出到 Blog 里面给大家看,所以选择 AVIF 是最合适的(找不到 AVIF 图片查看器?拖到 Chrome 浏览器里就行啦)。JPEG XL 浏览器支持不算太好。其他的 TIFF / PNG 虽然一直就支持 16 / 32 bit 深度,但缺乏色域描述,主要还是用来编辑的中间格式而不是适合直接观看的格式。

导出之后就可以看到开头展示的图片效果了。

效果统计

让身边有 HDR 显示器的同学帮忙试了下效果

  • AVIF 文件很多地方都没法看,目前还是推荐用 Chrome 浏览器查看。
  • Firefox 完全没法看;
  • Chrome 兼容性还不错,但并不完美
    • Windows 上面不管是 HDR 或者 SDR 显示器,显示效果都没有问题,Chrome 会自动在 SDR 显示设备上把 HDR 内容 Fallback 到 SDR 色域上
    • iPad / iPhone 上面的 Chrome 浏览器都可以准确显示,不过我的 iPad / iPhone 最大亮度只有 500nit,图片中第三档以上的高亮(上面可视化时紫色区域)会有 Clip 的效果,其实不是很完美。
    • 如果苹果设备配备了 XDR Display(比如新的 12.9 iPad Pro 或者 2023 款 Macbook Pro),那么可以非常完美地看到 HDR 效果。

再进一步——视频?

其实我还有个 HDR 显示设备——五年前买的索尼电视 X9000F,但它上面只有 Apple TV 能输出 HDR 内容,我要怎么把照片扔过去?

然而昨天跟李老师聊天提到 ffmpeg 可以直接把照片转换成视频。想了下这样我就可以用 Plex 直接播放 HDR 视频来看这个效果了。

ffmpeg -i DSC_4587_edit.avif -vf scale=4096:2160 -framerate 0.05 output.mp4

试了下效果确实不错,果然手上最合适的 HDR 设备就是索尼电视了。

直接播放就可以了,Plex 标记出来了 4k HDR 属性,视频信息可以看到 Rec.2020 色域。拍出来的效果也很接近观感。

吐槽

很讽刺,我为了在电视上看 HDR 拍摄的照片,竟然还需要先把图片转换成视频,这真的很讽刺。

跟同事聊,感慨现在的 HDR 生态基本都是影视行业的厂商主导,照片行业其实并没有吃到显示设备更新的红利。这篇文章展示的照片是用 2014 年的 D750 相机拍摄,2018 年就已经有消费级 4k HDR 电视了(当时主要是打 PS4),所以其实硬件早就准备好 HDR 照片的展示了,但相关事情晚了至少五年才发生,感慨有点可惜。

内容的角度,我其实希望我能手动控制 Fallback 行为,一张精细制作的 HDR 内容 Fallback 到 SDR 上不一定有最好的展示效果,那么我不如手动制作两个版本的内容 HDR / SDR。这可能也是 HDR 不容易普及的一个原因。

希望至少各种 SNS 和图库(Flickr 之类)的应用网站等能够尽快支持 HDR 照片,让大家能够更好利用起手上的 HDR 显示设备吧。

当然最后总结,我也可以反驳最开始提到 Z8 评测视频里的观点,HDR 照片不再是特定设备的专利,任何一张现代数码相机拍摄的 RAW 图都可以处理成 HDR 内容,这个过程也不需要我一定有个 HDR 显示器用来监视输出效果。同时在展示层 Chrome 基本解决了大多数平台的显示效果问题。虽然整个生态还有很长的路要走,我想可以说,Adobe 的这个功能更新是让 HDR 照片处理下放到普通消费者环境的第一步。

【续】【水】为图像搜索引擎添加搜索图片中文字的能力

上一篇 CLIP 的文章,我自己在搭建个人图像搜索引擎的过程中还有搜索图片中文字的需求,其实技术部分比较水,自己想要的多语言 Feature 完全没时间去尝试,就算是填坑把之前的内容补齐,也算是一个简单的笔记。

本文内容包括:

  • 搜索文字的需求从何而来?
  • 个人使用 PaddlePaddle 的 Best Practice 与限制
  • ES 作为的文本检索后端的选择
  • 效果展示,与 CLIP 搜索的对比分析
  • Limitations & TODO

背景

沿着上一个自己架在 NAS 上的服务,我这边还有其他搜图的需求,包括但不限于:

  • 想搜一些表情包,但只知道上面的文字,或者图片主题很难用 CLIP 关键字描述
  • 找一些聊天记录截图里面群友发的黑历史,这时候只能搜群友 ID / 用户名
  • 想找一些包含特定编号 / 编码的内容(比如我的用户名、邮箱、电话、航班编号等等,这些在 CLIP 里面是没有语义的)

怎么做呢?前面已经写过图像存储和搜索前端了,想了下找个开源的 OCR 模型应该就能做到这一点。另外文本检索不是我熟悉的东西,所以还得找一个支持文本检索的后端服务,这里我选择了 ElasticSearch。

PaddleOCR 模型的使用

按照周围同学同事的说法,PaddleOCR 基本是开源 OCR 模型里面易用性和性能 Trade-off 做得最好的,最初部署基本上参考他们的 github 页面即可。

这里需要注意的事情是他们的库参数还是有点多,有一些内容还是有点缺乏文档需要自己去试。

多语言部分,我尝试了一些他们提供的多语言模型,感觉就只有默认的汉语 + 英语模型性能是最好的,宣称的多语言感觉不管怎么搭配都会损害原始汉语 / 英语的性能。按照其他同学测试感觉还是 Google Android Demo 里面的多语言 OCR,或者使用 PaddlePaddle 另一个项目的 PULC 多语种分类模型可能才能达到还不错的效果。

总之我对 Paddle 自带的多语言不是太满意,毕竟我想一个配置直接无脑解决汉语+英语+日语多语言场景,这里就只能退一步先无脑用他们的汉英模型。模型下载部分可能需要注意下本地模型的加载:自己在开发机器时会发现模型名称按照文档写就可以,反正回自动下载;但如果要在非联网机器的话需要到他们的 model list 页面手动下载到本地解压,加载时也要注意目录结构。

在上面目录结构下,加载模型的代码如下

from paddleocr import PaddleOCR

ocr_model = PaddleOCR(
    ocr_version="PP-OCRv3",
    # det_model_dir="/home/andy/.paddleocr/whl/det/ml/Multilingual_PP-OCRv3_det_infer/",  # multi-language
    det_model_dir="/home/andy/.paddleocr/whl/det/ch/ch_PP-OCRv3_det_infer",  # Chinese
    # rec_model_dir="/home/andy/.paddleocr/whl/rec/ch/ch_ppocr_server_v2.0_rec_infer/",  # chinese model on server
    # rec_model_dir="/home/andy/.paddleocr/whl/rec/japan/japan_PP-OCRv3_rec_infer",
    rec_model_dir="/home/andy/.paddleocr/whl/rec/ch/ch_PP-OCRv3_rec_infer",  # Chinese model
    # use_angle_cls=True,
    # lang="ch",
) # need to run only once to download and load model into memory

使用模型的代码如下

try:
    ocr_result = ocr_model.ocr(img=image_path, cls=False)
except:
    print("Error: ", image_path)
    continue

ocr_str = ""
ocr_full_result = []
for idx in range(len(ocr_result)):
    for line in ocr_result[idx]:
        ocr_str += (" " + line[1][0])
        ocr_full_result.append(line)
ocr_str = ocr_str.strip()

ElasticSearch 文本搜索的使用

之前基本没用过 ES,也是一边踩坑一遍试,感慨现代数据库系统坑是真的多(我还丢了一次数据)。多语言感觉自己没找到好办法,还是先当只有汉语的场景来处理吧。

其实用 ES 之前试了下 MongoDB 自带的中文检索,唉,一团糟……因此想着直接 ES 一步到位吧。

首先是建立中文索引,安装最新版本(我是 8.7.0)之后需要手动安装中文 smartcn 分词插件,来到 ES 安装目录下:

sudo bin/elasticsearch-plugin install analysis-smartcn

之后重启 ES 并建立中文索引,我用的 python 接口

from elasticsearch import Elasticsearch

es_client = Elasticsearch("http://10.0.0.11:9200")
ret = es_client.indices.create(index="ocr_text_result", body={
    'mappings': {
        'properties': {
            'ocr_text': {
                'type': 'text',
                'analyzer': 'smartcn',
            },
            "filename": {
                "type": "keyword",
            }
        },
    },

    'settings': {
        'analysis': {
            'analyzer': {
                'smartcn': { # 使用 smartcn 分词器
                    'type': 'custom',
                    'tokenizer': 'smartcn_tokenizer'
                },
            },
            'tokenizer': {
                'smartcn_tokenizer': { # 定义 smartcn 分词器
                    'type': 'smartcn_tokenizer'
                }
            }
        }
    }
})

之后导入文档即可

ret = es_client.index(
    index=ES_INDEX,
    body={
        "filename": filename,
        "ocr_text": ocr_text,
    }
)

ES 的检索效率可比上一篇 CLIP 搜索高多了,基本可以控制在 1s 以内。不过因为 ES + Mongo + CLIP Model 我直接给我 NAS 加到了 32G 内存……

效果对比 / 展示

先是要搜图,最近大家都在吐槽五一调休,正好用关键词找了个表情包。

另外,还有些不太适合展示但是确实很方便的场景,包括:

  • 找群友发言黑历史(甚至包括自己)
  • 找自己的地址订单门票截图
  • 找之前坐过航班的机票 / 截图(比如我发现我竟然三年坐过三次 NH961 这个航班,还有两次日期都是相同的只有年份不同)

虽说 OCR 解决了不少 CLIP 时候的问题,我觉得这只是搜索工具的一部分,CLIP 和 OCR 感觉互相各有些无法替代的功能吧。

最后我发现 Google Photos 也有 OCR,就是……好像没那么强,不是很显眼(

Limitations & TODO

// 写到这里我明白我只是在挖坑不填

多语言是我想花点时间去解决的事情,不过目前看可能要尝试的东西有点多。语种分类模型 + 文字识别的思路其实最开始来自 Android 上的一个应用叫 fooviewer,从里面集成了 Paddle 的模型但不是 OCR 才发现这个思路。

Epix 帮忙尝试的 Android Demo 效果如下图,其实还可以。有点类似另外一个人用 iphone 做 OCR 后端的思路,所以没有用的主要原因是我还得连个手机(但我真的有个不用的 iphone SE)

另外即便多语言 OCR 做好之后,还有后面分词、文本检索的问题。目前看任何一个搜索引擎后端系统上多语言的处理都不是很显然,有精力的时候再去想这件事请吧(

OCR 效率,检索效率目前看问题不大,速度什么的完全可以接受,可以先苟着。