NTPサーバの時刻ソースに対するズレの調整

最近Chronyを使ったNTPサーバ動かしてみたが、Chronyは設定と統計情報の出力がntpdとはちょっと違う。しかも内容がよくわからない。
一応、統計情報をNode Exporterに読ませてPrometheusに送るところまではできるのだけど、その送った情報が何の値を示しているのかが判らないのでそれをグラフにしてもまぁ判らないのね。つまり、Chronyは動かすまでは簡単だけど動かしてからがだいぶ困る。

/etc/chrony.conf (の統計情報出力部分)
1
2
logdir /var/log/chrony
log measurements statistics tracking refclocks
統計ログとして4種類出力する指定。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/bin/sh

refclocklog="/var/log/chrony/refclocks.log"
measurelog="/var/log/chrony/measurements.log"
name="node_ntp_peerstats"
outdir="/tmp/node-exporter/"

offset1="# HELP node_ntpstats_offset_seconds Time offset in between local system and reference clock."
offset2="# TYPE node_ntpstats_offset_seconds gauge"
delay1="# HELP node_ntpstats_delay_seconds Time delay in between local system and reference clock."
delay2="# TYPE node_ntpstats_delay_seconds gauge"
disps1="# HELP node_ntpstats_dispersion_seconds Time dispersion in between local system and reference clock."
disps2="# TYPE node_ntpstats_dispersion_seconds gauge"
skew1="# HELP node_ntpstats_skew_seconds Time skew in between local system and reference clock."
skew2="# TYPE node_ntpstats_skew_seconds gauge"

pps='PPS'  #リファレンスドライバのrefidで指定した識別名
ppsdata=`/bin/cat ${refclocklog} | /bin/grep ${pps} | /usr/bin/tail -1`
ppsoffset=`echo ${ppsdata} | sed -e 's/ \+/ /g' | cut -d " " -f 7` 
ppsdelay=`echo ${ppsdata} | sed -e 's/ \+/ /g' | cut -d " " -f 8`
ppsdisps=`echo ${ppsdata} | sed -e 's/ \+/ /g' | cut -d " " -f 9`
#ppsskew=`echo ${ppsdata} | sed -e 's/ \+/ /g' | cut -d " " -f 8`
ppsl1="node_ntpstats_offset_seconds{device=\"pps\"} ${ppsoffset}"
ppsl2="node_ntpstats_delay_seconds{device=\"pps\"} ${ppsdelay}"
ppsl3="node_ntpstats_dispersion_seconds{device=\"pps\"} ${ppsdisps}"
#ppsl4="node_ntpstats_skew_seconds{device=\"pps\"} ${ppsskew}"

nmea='NMEA'  #リファレンスドライバのrefidで指定した識別名
nmeadata=`/bin/cat ${refclocklog} | /bin/grep ${nmea} | /usr/bin/tail -1`
nmeaoffset=`echo ${nmeadata} | sed -e 's/ \+/ /g' | cut -d " " -f 7`
nmeadelay=`echo ${nmeadata} | sed -e 's/ \+/ /g' | cut -d " " -f 8`
nmeadisps=`echo ${nmeadata} | sed -e 's/ \+/ /g' | cut -d " " -f 9`
#nmeaskew=`echo ${nmeadata} | sed -e 's/ \+/ /g' | cut -d " " -f 8`
nmeal1="node_ntpstats_offset_seconds{device=\"nmea\"} ${nmeaoffset}"
nmeal2="node_ntpstats_delay_seconds{device=\"nmea\"} ${nmeadelay}"
nmeal3="node_ntpstats_dispersion_seconds{device=\"nmea\"} ${nmeadisps}"
#nmeal4="node_ntpstats_skew_seconds{device=\"nmea\"} ${nmeaskew}"	

echo "${offset1}\n${offset2}\n${ppsl1}\n${nmeal1}\n${srv1l1}\n${srv2l1}\n${srv3l1}\n${delay1}\n${delay2}\n${ppsl2}\n${nmeal2}\n${srv1l2}\n${srv2l2}\n${srv3l2}\n${disps1}\n${disps2}\n${ppsl3}\n${nmeal3}\n${srv1l3}\n${srv2l3}\n${srv3l3}\n${skew1}\n${skew2}" > ${outdir}${name}.prom.$$

/bin/mv ${outdir}${name}.prom.$$ ${outdir}${name}.prom
/bin/chmod 666 ${outdir}${name}.prom

原始的だがこんな感じで統計情報をNode Exporterで読める情報にする。ただし、このスクリプトではoffsetだのdelayだのskewだのを○○ログの○番目の要素として抜き出す具体例が書かれているが、実際には○○ログの○番目の要素が何を示しているのか「がとらぼ」の人がよく判ってなくて作ったのでこれをそのまま真似るのはダメ。

一応頑張ってみたが、結局のところアタマが悪いのでドキュメントを見てもChronyのそれぞれのログの値が実際に何を示しているのか判らな過ぎてChronyを諦めてntpdに戻した。

「え? えぇっっっっ?!」

スンマセン

ntpdで統計情報をNode Exporterに渡すのは以前にPrometheus2とGrafana6によるシステム監視 NTP統計情報の表示で書いた。統計情報をグラフ化できないと調整は難しいと思うので、PrometheusとかElastic Searchとかの統計情報を収集する仕組みが無いという場合は、ntpdが出力する統計情報ファイルをNTP plotterに読ませてグラフ化するというようなのでも良い。Windowsならこれが簡単。何にしても、ntpdで時刻の調整をするには相当な時間〜日数で誤差を録り続けないとどれだけズレてるのかがそもそも判らない。

「がとらぼ」の人の調整の考え方

基本的にはPPSが秒替わりの間隔は一番正確。ただし、PPSはそのタイミングしか判らなくて、しかも微妙に遅延してるかも。
NMEAは秒の変わるタイミイグはだいぶデタラメだけど何時何分何秒が判る。
PPSとNMEAは衛星からのデータをGPSモジュールで受信してPCに伝えるまでの遅延がそれぞれどの程度あるのかが判らない。
インターネット上の公開NTPサーバの中には正確な時間を持っているものがあってそれをNTPサーバで参照すると個々の瞬間ではバラツキはあるけど長い時間では遅延を考慮した正しい時間を取得できる。
そこで、ネットから取得した時間とPPS/NMEAの差分を求めてPPS/NMEA側を調整する。つまり時刻自体はインターネット上のNTPサーバから取得した時刻に合わせて、秒のタイミングはインターネット上のNTPサーバに寄せてPPSの遅延(ズレ)を調整し、おまけでPPSに寄せてNMEAを調整するという感じ。PPSとネットの時刻ソースがあればNMEAは無くても良いが、ネットが切れた場合に備えてオマケで組み入れておく。

ntpdでは1つのリファレンスクロックドライバでNMEAとPPSをを組み合わせて日時+秒変わりタイミングを得る方法もあってそれが正確で良いとも聞くが、「がとらぼ」では172.172.20.xでNMEA、172.172.22.xでPPSの2つのリファレンスクロックドライバを使う方法を採用している。(GPSモジュールは1つ)

ntpdの設定で統計ファイルを出力する設定にしていないのであれば、ntpq -p の出力を監視という方法もある下のコマンドはLinux用)
#目視で監視するなら(まぁ無駄)
$ watch -n0.5 "ntpq -p | grep .NMEA."
#ファイルに出力するなら
$ watch -n0.5 "ntpq -pn | grep .NMEA. | tee --append nmea.log"

-n0.5は0.5秒毎に更新の指定。ntpq -pの出力を見るなら1秒よりは小さい方が数値がどう変化するのかよく判る。.NMEA.の部分は/etc/ntp.confのrefidで指定した文字列(上の例ではNMEA)の前後にピリオドを付けたもの。refidで指定した文字列がユニークなものなら前後のピリオドはなくても間違って抽出されることはないと思う。

GPSモジュール交換前
怪しい中華GPSモジュール(ATGM332D)を購入したという記事を書いたときに挙げた何かおかしいGPSモジュール(NEO 6M)のNMEAのグラフ。これがどう見ても異常なので新しいGPSモジュールを購入した。
それでOSも最新版で気分一新してこの記事に挑んでいる。そこで以前の「NanoPi NEOとGPSモジュールでNTPサーバ PPS解決編」では「効果が無い」と書いたsetserialにも再挑戦。

$ sudo apt install setserial    #setserialインストール

$ sudo setserial -g -a /dev/ttyS1    #setserial未適用で/dev/ttyS1の状態を確認
/dev/ttyS1, Line 1, UART: undefined, Port: 0x0000, IRQ: 38
        Baud_base: 1500000, close_delay: 50, divisor: 0
        closing_wait: 3000
        Flags: spd_normal

$ dmesg | grep serial   #システムがシリアルポートをどう認識しているか確認
[    2.472691] 1c28000.serial: ttyS0 at MMIO 0x1c28000 (irq = 37, base_baud = 1500000) is a U6_16550A
[    2.494480] 1c28400.serial: ttyS1 at MMIO 0x1c28400 (irq = 38, base_baud = 1500000) is a U6_16550A

/var/lib/setserial/autoserial.conf (編集 or 新規)
中身無しまたはコメントの行だけにする。

低遅延と速度115200bpsを指定(手動の場合)
$ sudo setserial /dev/ttyS1 low_latency spd_vhi
/dev/ttyS1が対象のシリアルポート、low_latencyが低遅延、spd_vhiが115200bpsの指定。
/lib/systemd/system/ntp.service (編集)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
[Unit]
Description=Network Time Service
Documentation=man:ntpd(8)
After=network.target
#After=rc-local.service
Conflicts=systemd-timesyncd.service

[Service]
Type=forking
# Debian uses a shell wrapper to process /etc/default/ntp
# and select DHCP-provided NTP servers if available
ExecStart=/usr/lib/ntp/ntp-systemd-wrapper
ExecStartPre=/usr/bin/bash -c '/usr/bin/mkdir -p /tmp/ntpstats 2> /dev/null'
ExecStartPre=/usr/bin/chmod 777 /tmp/ntpstats
ExecStartPre=/usr/bin/bash -c '/usr/bin/echo "B5 62 06 00 14 00 01 00 00 00 D0 08 00 00 00 C2 01 00 07 00 03 00 00 00 00 00 C0 7E" | xxd -r -p > /dev/ttyS1'
ExecStartPre=/usr/bin/setserial /dev/ttyS1 low_latency spd_vhi
ExecStartPre=/usr/sbin/ntpdate ntp1.v6.mfeed.ad.jp
ExecStartPre=/usr/sbin/hwclock -w
#PrivateTmp=true

[Install]
WantedBy=multi-user.target

15行目でubloxのGPSモジュールに115200bpsに合わせるようコマンドを送ってから16行目setserialでttyS1ポートを115200bpsのlow_latencyにセット。それからntpdateでネット上のNTPサーバを使って時刻合わせをしてRTCに時刻を書き込み。ここまでExecStartPreで実行してからntpdがサービスをスタートする。
以前の記事でsetserialでlow_latencyを使っても結果が変わらないと書いたが、長い期間で見るとNMEAの振れ幅が少し改善しているように見えたので今回はサービス起動時にsetserialを適用することにした。setserialは使わないということであれば、上の /lib/systemd/system/ntp.service の16行目は要らないと思う。
シングルボードコンピュータ用のLinux(Armbian含む)で /lib/systemd/system/ntp.service 内に PrivateTmp=true の行があったらその行を削除するかコメント化して無効にする。でないと統計情報等の出力先が設定ファイルに書いた出力先を無視?して /var/log.hdd 下になるのでワケワカランことに。理解した上で/var/log.hdd下に置くつもりならそれは構わないが、microSDカードの寿命を縮めることになるので頻繁に書き込むファイルをこの場所に置くのはオススメしない。あと、2020年7月のArmbianではlogrotateの設定の初期値が/var/log.hdd下のファイルしか面倒みないようになっていたので/var/log下のファイルがローテートされずに放置される。長期稼働を予定しているホストであれば/var/log下もローテートする設定を追加する。でないと/var/log(メモリディスク)がパンクする。ただし、logrotateサービス自体がPrivateTmp=trueになっていると/var/log.hdd以外を操作できないので /lib/systemd/system/logrotate.service の PrivateTmp=true も無効化する。/etc/logrotate.d以下も触らないといけないし、他のサービス設定も触らないといけないかも。ヘタに触ると収拾がつかなくなるので悩みどころ。

$ sudo systemctl daemon-reload
/lib/systemd/system/にある *.service を変更したらデーモンリロードしておく。もしくは変更したサービスを無効化して再度有効化する。システム再起動だけでは変更後の設定が適用されない。
/etc/ntp.conf (重要な変更部分)
1
2
3
#前略
server 127.127.20.0 mode 81 minpoll 4 prefer
#後略

忘れやすいが、GPSモジュール側のシリアル速度を変更したらntp.conf側でもmodeで速度を合わせること。(参照クロックドライバ127.127.20.xのmode 81 = 80:115200bps + 1:RMC)

/etc/ntp.conf (ズレ調整のない設定)
1
2
3
4
5
6
7
#前略
server 127.127.20.0 mode 81 minpoll 4 prefer   #NMEA mode 81: 115200bps + RMC
fudge  127.127.20.0 refid NMEA

server 127.127.22.0 minpoll 4 maxpoll 4 true   #PPS
fudge  127.127.22.0 refid PPS
#後略
$ sudo systemctl restart ntp.service
NTPサービスを再起動して24時間以上様子を見る。
「がとらぼ」ではNode ExporterでNTPの統計情報を取得してPrometheusで蓄積、Grafanaでグラフ化していつでも監視できるようにしている。

NTPのズレ調整 1
NMEAのoffsetのグラフ。これは上で書いたsetserialの未適用の状態。これだと表示中の48時間で平均が-154msになっている。ただし、グラフがところどころ数百msも下方向に伸びてしかも数分〜1時間もその状態が続いている。この平均ズレ時間をそのまま信じるのはちょっと考えもの。しかし、おおよそ150〜180msと考える。まぁ、NMEAはオマケで合わせる方針なので調整は後回しでも構わない。

NTPのズレ調整 2
ネット上の時刻ソースとの同期のグラフ。3つのNTPサーバの48時間のoffsetが描かれている。画像では上下に大きく波打っているが振れ幅としては実は2ms程度でしかないので、上のNMEAより150倍も精度が高い。でも本当はそれはちょっとおかしい。というかNMEAの振れ幅が大きすぎる。 平均は3つで1.6〜1.7msほど。これから調整するNTPサーバではこの時刻を正しい時間として合わせる。つまり、現在は設定するNTPサーバが1.6msズレているということにする。

NTPのズレ調整 3
PPSのoffset。これから調整するこのNTPサーバは現在はこのPPSの時刻が正しいと思っているのでズレは0を中心に上下にそれぞれ振れ幅10μmでグラフが描かれている。未調整でこれが上か下にズレていたらNTPサーバが何に時刻を合わせているのかを確認する必要がある。

/etc/ntp.conf (PPSの設定部分 未変更含む)
1
2
server 127.127.22.0 minpoll 4 maxpoll 4 true
fudge   127.127.22.0 time1 0.0017 refid PPS

PPS側。参照クロックドライバが127.127.22.xでは時刻のズレの調整はtime1で行う。単位は「秒」なので1.7msであれば0.0017となる。 他所の設定例のようにflag3 1なんかを設定するとPPSのoffsetが設定分ズレてワケが解らなくなるので「がとらぼ」ではflag3は設定しない。
変更したらNTPサーバを再起動する。このときdriftファイルを指定しているならnet.serviceを停止してdriftファイルの中身を消してnet.serviceを起動する。(driftファイルの中身を消してntp.serviceを再起動してすぐにdriftファイルを確認して空ならそれでもOK.)
36時間以上稼働させて、起動後少なくとも12時間は見ないでその後の24時間のoffsetの平均を見て、まだズレがあるなら更に設定を詰める。なかなか「これかな?」という値が見つからないかもしれないが、それでもおおよそで合わせるしかない。今回設定しているNanoPi NEOの例では6桁程度の精度で設定した。実際には0.00172という設定になった。これはGPSアンテナの設置環境や使用機材など幾つかの要因で値が変わると思うので「がとらぼ」の人が0.00172って書いてたから真似たら全然違ったということになるかと思う。

NMEA側。これはPPSのズレ調整が終わってからの情報で調整した方が良いと思う。この記事のNMEAのグラフではグラフの振れ幅が100ms近くあるけど、なんでこんなに酷いのかわからないが、GPSアンテナがすぐ隣にある別のNTPサーバ(FreeBSDのPCサーバとUSB接続のGPSモジュールを使ったやつ)だと振れ幅が10ms程度なので約1/10。普通はこの10ms以下(もっと小さい?)だと思うのよね。

NTPのズレ調整 4
直前に書いたFreeBSDのPCサーバとUSB接続のGPSモジュールのNTPサーバのNMEAの48時間グラフ。上に5ms、下に5ms程度の振れ幅で平均は表示している48時間でいえば-56μs。(このNTPサーバは調整済みだが、常にわずかにブレるのでこの程度の誤差はあっても異常ではない)

/etc/ntp.conf (NMEAの設定部分 未変更含む)
1
2
server 127.127.20.0 mode 81 minpoll 4 prefer
fudge 127.127.20.0 time2 0.155 refid NMEA
ネットのドキュメントを見ると混乱させられる部分だけど、参照クロックドライバの127.127.20.xでNMEAのオフセットの調整はtime2なので注意。127.127.20.xでPPSも見る場合はtime1も絡んでくるみたい。(未確認)
setserialを有効にしたらそれだけでも10ms以上(僅かだか誤差が少ない方に)ズレた。
調整する設定の単位はこれも「秒」。今回設定しているNanoPi NEOの例では結果的に0.155 (155ms)で設定した。

NTPのズレ調整 5
setserialで低遅延を適用してズレ調整済み状態のNMEAのoffsetのグラフ。
表示している48時間の平均誤差は-378μsとなっているので、振れ幅100msが当たり前の中で約400μmなら優秀ではあるけど、グラフを見たらお判りのように、7/29の早朝に長い時間メチャクチャになってるのが含まれてこれなので「調整完了」とは言い難いと突っ込まれる?でも他の時間帯でもだいたいこれで中央値が0なのよね。
先日記事のようにGPSモジュールを交換して、それでNMEAの結果が改善することを期待したのだが、謎のコノギリ波形から普通のグラフになったのは大改善とはいえ、期待していたより遥かに低い精度なので、もしかしてこのNTPサーバが使っているアンテナ個体が悪いのかな。10cm隣に設置した別のGPSアンテナを使っているFreeBSDのNTPサーバは期待程度には精度があるのでアンテナ設置場所が悪いということではない筈。

NTPのズレ調整 6
インターネット上の公開NTPサーバ3台のoffsetグラフ。7/29の午後にちょっと酷いズレが発生しているが、それで3台の平均では約100μsなのでppsの調整は一応出来ている。

NTPのズレ調整 7
当然だが、ppsのoffsetグラフの振れ幅は変わらず。

まとめ

PPS用のクロックドライバ127.127.22.xでtime1を調整するとネットの時刻ソースのグラフに変化が出るので振れ幅の中央値(≒平均)が0nsに合うようにする。PPSのグラフには変化は出ない。
NMEA用のクロックドライバ127.127.20.xでtime2を調整するとNMEAのグラフに変化が出るので振れ幅の中央値(≒平均)が0nsに合うようにする。

システム監視用のPromethusのデータ保持期間を半月にしていたのにNTPのズレ調整後に暫く放置してしまったので調整前のグラフを取得できなくなってしまった。そこで、8月に入ってからズレ未調整に戻して1週間待って画像を取得した。それでこの記事では7月の画像が調整後で8月の画像が調整前という逆転状態になっている。

関連記事:

Xiaomi Redmi Note 9Sのカメラで撮った写真は綺麗?汚い?

Xiaomi Redmi Note 9Sのカメラ写真は綺麗?汚い?

7月にXiaomiのミドルロー帯のハイコストパフォーマンス機のRedmi Note 9Sを購入した。本当はこの姉妹モデルでもう少し安いRedmi Note 9か、以前から出ると噂になっていたOPPO Reno4の5G非対応版が欲しいと思っていたのだが、Xiaomiの方は日本向けに出してきたのがRedmi Note 9Sで、OPPOの方は目当てのモデルがリリースされるのが思ったより遥かに遅かった(7月末になってしかも今のところはタイだけ)ということなので、まぁRedmi Note 9Sを選ぶことになったのは仕方がないかなと。それに、XiaomiがRedmi Note 9Sを日本でもぼったくらずに安く出してくれたのと、バンド対応しっかりしていたので、これが決め手。Xiaomiはコストパフォーマンスが良くても日本以外の地域向けモデルは日本で使うにはバンド対応が良くないのよね。正式な日本向けモデルなら技適警察さん達に怒られなくて済むし。

Redmi Note 9Sは正式に日本で販売されるモデルの中ではこれまでになくコストパフォーマンスが高いという評価は確かではあるけど、もちろん魔法じゃないから超凄い機種がウソみたいに安く販売されているというわけではない。欠点はスペックからは読み取れない部分に隠されてるので、無駄に期待し過ぎていた人は買ってから「アレ?」と思うか、その辺りを覚悟してた人なら「やっぱりか・・」と思う部分がそれぞれある筈。Redmi Note 9Sの場合は大きく3つ、MIUI含むOS周りの挙動、音質、カメラ、このあたりが目立つところかと。MIUIはもともと好きじゃなかった(カスタムロムでしか触れたことがないけど)ので半分諦めてたし。音質はまぁ仕方が無いところ。ただし、イヤホンをしても良くないというのは予想してなかったけど。カメラもまぁこの価格だとスペック上はそれなりでも画質は期待できないよね。もともとスマホのカメラは解像度高いとロクなことないし、Redmi Note 9SのカメラセンサーがSamsungとOmnivisionなので期待してなかった。それと中国人・中国メーカーはハデな色の写真が好きなのでカメラのセンサーが得た画像を塗りつぶして油絵とかゲームのCG背景みたいにしちゃう傾向があるしね。

今回はRedmi Note 9Sの写真について。標準カメラアプリによるJpeg出しとRaw出しで画質を見てみたい。

標準カメラアプリのJPEG出し 900万画素モード

Xiaomi Redmi Note 9Sのカメラ画像 標準カメラ+JPEG出し 赤い花
デジタルカメラが大の苦手とする赤い花。Redmi Note 9Sの標準カメラは無駄に明るく現像してJpegにした印象。それで赤が潰れるのを防ごうとしている?その代わり緑の葉っぱが単一色みたいなノッペリしたヘンなの。赤い花の色そのものは眼で見た感じに近くなるように雰囲気だけは頑張ってはいる。

Xiaomi Redmi Note 9Sのカメラ画像 標準カメラ+JPEG出し オレンジの花
オレンジの花。これがヘタクソで立体感のない「塗りました」みたいな色になっている。緑の葉っぱはやっぱり全部同じ色に見える。

Xiaomi Redmi Note 9Sのカメラ画像 標準カメラ+JPEG出し ピンクの花
ピンク色の花。これは白い花にピンクのスプレーを吹きかけたかという感じで全く花が台無しに。葉っぱはハデ過ぎるほど鮮やかに描かれているが葉の表面のテカりは眼で見た雰囲気を壊してはいない。

標準カメラアプリの標準設定(何も変更をしない状態)で、出力も標準のJpegのまま。おそらくメインカメラのSumsungのS5KGM2センサーが暗くて色乗りが悪くノイジーなのでこの本来の1/2 x 1/2の解像度で上下を捨てた16:9が標準モードになってる。(S5KGM2がテトラセルなので仕方ない・・・)
画像は出力された画像を加工はせずに、そのまま1920 x 1080pxに切り抜いただけ。つまり等倍。ただし、カメラが出力したJpegを切り抜いてもう一度Jpegにして、閲覧環境によってはさらにWebPに変換することになるのでブラウザで閲覧したときにはディテールが壊れているかも。

標準カメラアプリのRAW出しそのまま 1190万画素モード

Xiaomi Redmi Note 9Sのカメラ画像  標準カメラ+RAW出し 赤い花
赤い花は、真っ赤な服を漂白剤と蛍光増白剤を入れて洗濯して色落ちしたみたいななんともいえない変な色。でも完全に潰れてはいないのでソフトウエア次第ではある程度修正が効く。ただし彩度の高い赤い色はとても難しい。背景の緑の葉っぱはボケが効いているのもあるが、元々1色の緑しか無いみたいな状態で撮れていたというのが判った。これではソフトウエアで修正してもフクザツな色は出そうにない。

Xiaomi Redmi Note 9Sのカメラ画像  標準カメラ+RAW出し オレンジの花
左側のオレンジの花にピントを合わせた筈だが、実際にはこの画像の中央付近で花につながる茎にピントが合っているみたい。花はピンボケで脱色したみたいなオレンジ色だけどそれでもオレンジのグラデーションは残っている。背景の葉っぱは全体的に白っぽいけど潰れてはいないので悪くはないかも。現像しだいというところかな。

Xiaomi Redmi Note 9Sのカメラ画像  標準カメラ+RAW出し ピンクの花
このピンクの花は立体感が消えやすくて難しそうだけど意外と綺麗に写っている。全体的に脱色した感があるが、葉の表面のテカりや葉の表面の凸凹感は失われていない。これはコントラストを少し上げる程度で良さそう。

Redmi Note 9S の標準カメラアプリはモード設定をシャッターボタン近くのモード切り替えスライダーで「プロ」を選択すると右上のハンバーガーアイコンからRaw出力を選択できるようになる。Redmi Note 9SのRaw出力はDigital Negative(DNG)形式なので専用ドライバや専用アプリケーションは不要で有名処の画像加工アプリや現像アプリは対応している筈。スマートフォンのカメラアプリはセンサーが撮った画像をJpeg出力する際に派手めに加工するが、Raw出力なら(完全ではないにしても)加工なしのカメラセンサーが撮ったままの画像を得ることができる。Redmi Note 9SのリアカメラのメインセンサーはSumsungのS5KGM2という名目4800万画素でセンサーサイズが8mm、ドットあたり0.8umといういかにも暗そうなスペックで、実際昼間に屋外で撮影して上の3枚の写真のように暗くて色が無くなる酷い代物。まぁこの機種・S5KGM2だけじゃなくちっちゃいセンサー+ちっちゃいレンズのくせに妙に高解像度なスマホカメラ全般の傾向ではあるけど。これをアプリケーションで色を強調してド派手にしているんだけど。正しい色にならないのも微妙な色の変化が撮れないのも無理はない。

標準カメラアプリのRAW出し現像調整 1190万画素モード

Xiaomi Redmi Note 9Sのカメラ画像  GCam+JPEG出し 赤い花
先の3枚をDarktableで現像した。
花びらが赤で潰れないようにしながら背景の葉っぱの色が変にならないよう、のっぺりしないように気をつけたが、元のRaw画像で失われていた本来の鮮やかで明るい赤い花の色を再現することは無理だった。「赤」にはなったけどちょっと違う赤なのよね。服を洗濯して色落ちしたら元には戻せないのと同じ。

Xiaomi Redmi Note 9Sのカメラ画像  GCam+JPEG出し オレンジの花
背景の葉っぱは肉眼で見たときの色にできた。オレンジの花は意外と綺麗に色が乗らなかった。特に右側の花はオレンジというより黄色っぽく見えてしまっている。左側の花はオレンジの濃淡がキツめ。

Xiaomi Redmi Note 9Sのカメラ画像  GCam+JPEG出し ピンクの花
全体に白っぽい気がしないではないけど、この写真はちょこっと触っただけで比較的簡単にマシな結果となった。

コンデジのRawだとせいぜいノイズを取るとか少し暗めにするとかホワイトバランスを変える程度だけど、暗くて色が失われたスマホのRawを現像するのは凄い手間。不自然さの無い色味にするのが難しい。写真撮りまくるのは良いけど後で現像しなきゃって考えるとゲンナリしそう。

3つの花とも撮影時には風があって花びらがプルプルパタパタしてたのが殆どブレずに影響無しな画像になったのはちょっと褒めるべきかも。でも、それなら少しでも色が載るように「オート」の選択肢にシャッター少し速度遅めるというのがあっても良いんじゃないかと思う。今回は4800万画素のメインカメラセンサーを使いながらも4000x3000px以下程度の画素になるモード(初期値)で撮影した。選択すれば4800万画素モードも使えるようだけど、近くの物はボッケボケで色がなくて恐ろしくノイズだらけという酷い画像しか撮れないみたい。4800万画素を活かすには数メートル以上離れた屋外の明るい被写体だけなのかな?これは難しいかも。
Redmi Note 9sのメインカメラはSamsung S5KGM2というテトラセルのセンサー。このテトラセルはクセモノで、カタログスペック的には高解像度だけど実は4画素で1画素として使うモードでしかまともに撮れない。つまりテトラセルで4800万画素センサーということなら綺麗に撮るには1200万画素でということになる。はっきり書けば、カタログスペックは4800万画素だけど実は1200万画素、そういうこと。4800万画素モードで糞みたいなキッタナイ写真しか撮れないのはそういうことなのね。

なお、Redmi Note 9Sの標準カメラアプリでRaw出力は「プロ」モードだけで、そのモードは絞りやシャッター速度ISOなど撮影者が都度適切に合わせるのが本来の撮影方法だと思う。今回は「プロ」モードは使ったけど全てAUTOで撮影したので、それで暗いだの色が乗らないだの文句を言うのは筋違いかもしれない。関係者の方で気を悪くしたらスミマセン。

Redmi Note 9Sで簡単に綺麗に写真を撮るならおそらく今のところはGCam。もし次回があればGCamで撮った写真を見てみたい。

Up