前回示したように、画像の一部でドップラーシフトの連続変化が見えるなら、頑張れば画像全体でも見えるはずです。


今回は、全画面でのドップラーシフトをアニメ化する方法を探ってみたいと思います。いい機会なので、JSol'Exの強力なスクリプト言語のImage Mathを使ってみようと思います。


1. 自動画像生成+マニュアルでアニメ化

まずは連続波長ずれ画像(静止画)を出力する一番簡単な方法です。

とりあえず、JSol'Exでserファイルを開いて、「Custum prosess」を選んで「Mode」を「Simple」にして、下の「Select all」ボタンを押し、右上の数字が並んでいるところに「-10;-9;-8;-7;-6;-5;-4;-3;-2;-1;0;1;2;3;4;5;6;7;8;9;10」などと入れてやって、-10pixelから+10pixlelまでシフトした画像を生成してくれます。
redshift_cut

autostrerchフォルダなどに出力された21枚の画像を、適当なツールを使ってアニメ化するというのが、まずは一つ目の簡単な方法になります。例えば、PixInsightのBlinkで動画化することができます。

実際に作って見ました。ブログに載せるために縮小してgif化してますが、これだけでも迫力があります。
Blink_10_blog

一旦はこれで作ったのですが、でもまだまだ不満が残ります。


Image Math

まず、どれだけ波長がシフトしているかの数字を画面内に入れたいのですが、なかなかいいツールが見つかりません。高々20枚ほどなのでPhotoshopなどでマニュアルで入れるのでも構いませんが、JSol'ExのImageMath機能を使うと、さらに細かいことが色々できるみたいです。せっかくなので、ここで使い方を一通り把握しておきたいと思います。

まず、マニュアルや解説に相当するページですが、以下の4つくらいでしょうか。

https://melix.github.io/astro4j/3.3.1/en/jsolex.html
https://melix.github.io/astro4j/3.3.1/en/imagemath.html
https://youtu.be/l6tb-UFC6Zs?si=oyHAQhvETiXK3iJe
https://youtu.be/8XKzFcmvqfI?si=GXIArv_YOCPATGgI

上の2つはバージョンごとにページがあるので、今使っているバージョンのものを見るといいでしょう。アドレス内の数値を自分のバージョンに合わせてください。いっそのこと最新バージョンの3.3.1を落とすのもいいでしょう。このJSol'Exですが、まだ開発絶頂期の範囲なのか、バージョンアップの頻度がものすごいです。私が使い始めたわずか2週間の間に、3.2.1から3.2.2、3.3.0、3.3.1と、3回もアップデートしています。

下の2つは動画ですが、1つ目は基礎からImageMathまでわかりやすく英語で解説してくれています。え?日本語でないからわかりにくい?いやいや、2つ目の動画はImageMath専用の解説ですが、フランス語です。私は大学でフランス語を選択してましたが、今では全くわかりません。作者が解説してくれているJSol’Ex関連のビデオは結構たくさんあります。

https://melix.github.io/blog/jsolex.html

でも見てみるとわかりますが、21本中英語版はわずか3本、他は全部フランス語です。なので英語にしてくれているものは大きな情報源になり、かなり助かります。でもフランス語でも画面を見ているとわかるところもあり、特にImageMathについてはソースコードを見るとわかることも多いので、多少は役に立つと思います。というか、他の方のものなども散々探しましたが、どうもこれくらいしか解説はないようです。


Image Mathを使ってみる

実際にImageMathを触るときは、まずはサンプルコードを見るといいでしょう。JSol'Exのメニューの「Tools」から「Image Math editor」を選びます。出てきた画面で「Sample scripts」を押すと、いくつかの例が出てきます。

IM_card

この中で一番わかりやすいのは「Technical card」でしょうか。Full modeで緯度とか経度が書き込まれるcardという画像が出ていますが、それと同じ画像を作るスクリプトです。中身はこんな感じです。

#
# Generates a technical card similar to the built-in one
#

[params]
gamma=1.5
cropFactor=1.2

[tmp]
contrast=sharpen(auto_contrast(img(0);gamma))
cropped=autocrop2(contrast;cropFactor)
globe=draw_globe(cropped)

[outputs]
techcard=draw_solar_params(draw_obs_details(globe))

まずはこのスクリプトを、そのままSaveボタンを押して適当な名前をつけてどこかに保存してみてください。

次にserファイルを開いて、「Custum process」に進んで、出てきた画面の右上の「Mode」を「ImageMath」にします。右横の「Open ImageMath」ボタンを押してエディタを開き、「Load」ボタンを押して先ほど保存したファイルを開きます。

もし先ほどのスクリプトを保存していない場合は、ここであらためて「Technical card」を選択してもいいですが、SaveしてLoadせずに進めると何も読み込まれない状態になってImageMathの処理がされないので注意です。それから、ここで開いたサンプルファイル一覧では、「Tools」から「Image Math editor」から開いた場合で見たサンプルファイル一覧に出てくるものより少ないものしか出てこないので、これも注意です。なので、サンプルファイルは基本的にはメニューの「Tools」から辿って開くようにした方がいいいです。

Image Math editorの「Ok」ボタンを押し元の画面に戻って、「Unselect all」を押します。これでImage Mathの処理のみが行われるので時間の節約になります。JSol'Ex上に処理された緯度経度情報が入った画面が表示されると思います。その後のスクリプトの改造ですが、この画面の右下にImageMath scriptという場所があって、そこに先ほどのソースコードの内容が表示されていると思います。ここをいじっていきます。

手始めに、このモノクロのcard画像をカラー化してみましょう。

まず[param]、[tmp]、[output]の3つのパートに分かれているのがわかります。[param]は変数 (数値) の定義、[tmp]は内部的な画像処理で、[outputs]で指定されたもののみが実際の画像として出力保存されます。

改造のための情報を得るために、関数リファレンスページでコントロールキーとFキーを押すなどして「color」などとページ内検索します。どんなコマンドを使えばいいかはこの関数リファレンスページの関数一覧を一通り読むか、他のサンプルファイルを読み込んでみるといいでしょう。検索すると「COLORIZE」という関数が出てきます。使用例には

colorize(img: img(0), profile: "H-alpha")
colorize(range(-1, 1), "Calcium (K)")

などと書かれていますが、これを参考にします。例えば今処理しているcardスクリプトでは[tmp]の最後にglobeという画像が出来上がっているので、同じ[tmp]のところに

colorized=colorize(globe;"H-alpha")

という1行を追加して、colorizedという変数に画像を入れてみましょう。上の使用例と結構違っているので注意が必要です。それぞれの引数の間は「, (カンマ)」ではなくて、「; (セミコロン)」が標準みたいです。カンマでもいいみたいなのですが、サンプルコードでは全てセミコロンになっているので、私もセミコロンで統一することにしました。あと、引数のところの「img」とか「profile」は入れても入れなくてもいいみたいですが、入れるなら全て入れて、入れないなら全て入れないようにしないとダメみたいです。他のサンプルコードを見ると、入れない方が標準みたいです。

あとは、[output]の中の1行を

techcard=draw_solar_params(draw_obs_details(colorized))

のように書き換えて、先ほど作ったcolorizedを引き継ぎます。これでもう一度JSol'Ex画面右下のImage Math Scriptの「Run」ボタンを押して走らせるとカラー化された緯度軽度情報が入った画像が出来上がる位はずです。ただし、ここで書き換えたスクリプトはあらわにセーブしないと、再度立ち上げた時には元のモノクロの状態のスクリプトしか残ってないので、気をつけてください。

ちなみに、ここで出来たカラー画像ですが、フルモードなどで自動で作ったカラー画像とは色使いが違います。自動処理の方のカラー化はもう少し凝ったことをしているようです。


2. Image Mathで全画面ドップラーシフトをアニメ化

ここまででImage Mathの使い方のきっかけくらいは掴めたのかと思います。次は目的の全景のドップラーシフトアニメーションを作ってみましょう。といっても、これもサンプルファイルがあります。同様にImage Math editorで見えるサンプルリストの中から「Continuum animation」を選びます。以下のような内容です。

#
# Creates an animation of the continuum
#

[params]
# the animation will be created with images from [-shift;+shift]
shift=5
# autocrop factor
cropFactor=1.1
# contrast adjustment
gamma=1.2
# interpolation steps
steps=5
# delay between frames
delay=20

[tmp]
continuum=transition(range(-shift,shift);steps)
cropped=autocrop2(continuum;cropFactor)
contrast_adjusted=auto_contrast(cropped;gamma)

[outputs]
continuum_anim = anim(contrast_adjusted;delay)

このコードをそのまま使ってもいいのですが、前回のアニメであったような波長などの書き込みはありません。ここでは練習として、動画の各画像にテキストで波長を書き込んでみましょう。

使うコマンドはdraw_textです。[tmp]の最後に1行

text_added=draw_text(contrast_adjusted; 200; 2900; "Shift from Hα: %SHIFT%Å", 72; "FFFFFF")

を付け加えます。200とか2900は位置なので、自分の画像の大きさに合わせて適当に数字を変えてください。%SHIFT%はリファレンスマニュアルのdraw_textのところに書いてありますが、あらかじめ予約されている変数で、単位がÅに換算されたそれぞれの画像の波長のずれを表します。72はフォントの大きさです。こちらも適当に変えてください。FFFFFFは色で、RGBを各2バイトで表していて、この場合はRもGもBも255で一番明るくしてあるので白色になります。

[outputs]内では、最後の行を以下のようにtext_added変数を引き継いだ形に変更します。

continuum_anim = anim(text_added;delay)

基本的にはこれで走るはずですが、[params]内にある数値に少し触れておきます。
  • まず、shiftですが、これは[tmp]内のrange関数の引数に使われます。単位はピクセルなので、serファイルのHαの中心線から上下5ピクセルを処理します。ここは10くらいにしておくと楽しいでしょう。
  • stepですが、transition関数引数で使われていて、1ピクセルと1ピクセルの間を何枚補完するかになります。5の場合はかなり滑らかになります。ただし、先ほど表示したテキストの波長は間が補完されず、元画像の飛び飛びの波長しか出せないみたいなので、私はここは1にしました。
  • 最後delayですが、[output]のanim関数の引数で使われていて、フレームとフレームの間の時間で、単位はmsです。これはshiftとstepの数に合わせて調整しますが、私は1波長1枚としたので、ここでは200としました。

出来たスクリプトは以下のようになります。

#
# Creates an animation of the continuum
#

[params]
# the animation will be created with images from [-shift;+shift]
shift=10
# autocrop factor
cropFactor=1.1
# contrast adjustment
gamma=1.2
# interpolation steps
steps=1
# delay between frames
delay=200

[tmp]
continuum=transition(range(-shift,shift);steps)
cropped=autocrop2(continuum;cropFactor)
contrast_adjusted=auto_contrast(cropped;gamma)
text_added=draw_text(contrast_adjusted; 200; 2900; "Shift from Hα: %SHIFT%Å", 72; "FFFFFF")

[outputs]
continuum_anim = anim(text_added;delay)

走らせた結果ですが、以下のようになります。ブログにアップロードできるように、元々出力された3040x3040のmp4ファイルを600x600のgifに落としています。無事に数値が入って、わかりやすくなりました。

step
  • 撮影日: 2025年6月18日7時13分
  • 撮影場所: 富山県富山市自宅
  • 鏡筒: Takahashi FC-76(f600mm、F7.9) 
  • 分光器: SHG700
  • 赤道儀: Celestrn CGEM II
  • カメラ: ToupTek G3M678M
  • 撮影: SharpCap Gain 200 (=6dB)、露光時間1ms、ROI: 3840x100、平均381fps
  • 画像処理: JSol'Ex

これでももう結構十分で、ここでフルサイズの画像をアップしてもいいのですが、追加でもう一つ手法を紹介します。


3. もっと簡単な全画面ドップラーシフトのアニメ化の方法

Image Mathをある程度見てみて、上の動画まで完成させた後に、もっとはるかに簡単に全景画像を作る方法があることを知りました。悔しいですが、紹介しておきます。

処理したいserファイルを、Quick modeで一度処理します。出てきた画像の上で、コントロールキーを押しながら左クリックで処理したい部分を選択します。そして右クリックして「Create animation or panel」を選択します。

anime_select

すると次のような設定画面が出るので適当に設定して「Generate」ボタンを押します。
anime_setting

時間がかかりますが、処理が終わると以下のような画像と動画ができます。
07_13_53-trimmed_0000_07_13_53-trimmed_custom-panel_cut

out

上の動画はブログ用に縮小しています。フルサイズの動画はここにおいておきました。どうもショート動画になってしまうようですが、かなりの解像度なのでぜひ全画面化や、さらに拡大して見てみてください。

この領域選択はどこでもできます。最初からこんな大きな全景範囲で処理すると大変なので、まずは小さなサイズで試してみるといいと思います。例えばプロミネンスなどです。

out

この便利な機能、マニュアルにも記述がないみたいです。


まとめ

今回は3通りの全画面の連続波長ずらしのアニメ化の方法を示しました。本当は2つ目までだったのですが、一旦2つ目までの記事をほとんど書き終えてから3つ目の画像の一部選択の方法があることを知りました。まさか全画面ではできないかと思っていたら、あまりに簡単にできてしまったので、悔しかったですが紹介することにしました。でもまあ、Image Mathの使い方がわかったからよしとしましょう。

次の記事はこのドップラーシフトの全景画像を使って、色々議論したいと思っています。