fullseye

X 線の 2 つのエネルギーで厚みと材質を分ける(デュアルエナジー / フォトンカウンティング)

できること

1 枚の X 線透過像は、各画素で L = −ln(I/I₀) = Σ μₘ tₘ という1 つの数しか測りません。厚い肉と薄い骨片・ガラスは同じ L を作れるので、厚みと材質は分けられません。光子のエネルギーを 2 つ以上の窓で数え分ける検出器(フォトンカウンティング)か、2 つの管電圧で撮ると、μ(E) の形が材質で違う(光電効果は ≈ Z³/E³、コンプトン散乱は電子密度だけ)ので、各画素で方程式が窓の数だけ立ち、2 つの基底物質の厚みに分けられます(Alvarez & Macovski 1976、Lehmann ら 1981)。

What it does

Dual-energy and photon-counting X-ray material discrimination. The material table gains an X-ray column: mass attenuation coefficients from a bundled subset of NIST SRD 126 (Hubbell and Seltzer; 51 elements, 21 materials, 1 keV to 1 MeV) and the mixture rule for anything with a known composition, under the same names as the optical column. On top of it: a tungsten-anode tube spectrum and its half-value layer, photon-counting energy windows (absorption efficiency, energy resolution, charge-sharing tail) and dual-kVp channels, a noisy channel projection, a per-pixel polychromatic basis-material decomposition that rejects pixels it cannot solve, its Cramér-Rao bound, the R value, an effective-Z map and the closed-form separability of two materials. Seven inorganic scintillators (CsI:Tl, NaI:Tl, Bi4Ge3O12, Lu2SiO5:Ce, Lu1.8Y0.2SiO5:Ce, CdWO4, Gd2O2S:Tb) carry an emission column with a source for every value, and a scintillator-coupled sensor model follows one X-ray photon through absorption, light yield and the overlap of the emission with a photodetector’s quantum efficiency. The PoC finds bone and glass fragments that a single X-ray image buries under the thickness variation of meat.

向くところ / 向かないところ

向く: 食品の異物検査(骨片・ガラス・金属・石を、肉や包装の厚みのむらから切り離す)、電池・電子部品の検査、リサイクルの選別、検査系の設計(窓のしきい値・管電圧・光子数を変えたときの雑音の下限と、分けられなくなる厚さの見積り)。

向かない: ★肉に埋まった異物は肉を押しのけるので、2 つのエネルギーで測れるのは「異物 − 同じ厚さの肉」の向きで、見かけの Z は組成だけでなく密度でも動きます(PVC は組成の Z_eff 13.9 が 18.7 に見える)。無機物の向きは Al(13)から Cu(29)まで狭い角度に詰まるので、Z を 1 刻みでは読めず、骨・ガラス・アルミは同じ仲間になります。肉より軽い有機物(PE・ゴム)は画素ごとには雑音に埋もれます。散乱線、検出器の K 蛍光の逃げ(CdTe の 23〜31 keV)、パイルアップ、画素間の電荷共有の二重計数、ヒール効果は入っていません。

推奨パイプライン

xray_tube_spectrum → photon_counting_channels → basis_decomposition_crlb → basis_material_decompose → effective_z_map

管電圧とろ過から xray_tube_spectrum でスペクトルを作り → photon_counting_channels で窓に分け(検出器の応答も入れる) → 撮る前に basis_decomposition_crlb で狙う厚さの雑音の下限を見積もって窓のしきい値を選び → 撮った計数像を basis_material_decompose で基底(肉なら赤身と Al)の厚み図に分け、Al の像で異物を見つける → 材質の当たりは effective_z_map(素の板)か、基底の向き(埋まった異物)で読む。

代替

2 管電圧の装置なら dual_kvp_channels。分解をせずに材質の指標だけ見るなら r_value_map。「この厚さの組は分けられるか」だけなら dual_energy_separability。撮る前に絵で確かめるなら xray_channel_projection。材料の μ(E) を見るだけなら material_xray_attenuation。

限界

実寸校正

Fullseye に較正の op は無い。管電圧・ろ過・検出器の材料と厚さ・窓のしきい値・エネルギー分解能・電荷共有の割合を既知として photon_counting_channels に入れる。PoC の門のとおり、電荷共有 25 % と分解能 8 keV を知らずに分解すると、肉 1 画素あたり Al が −3.2 mm(雑音の 14 倍)も出る —— 実機では厚さの分かった 2 材料の段(例: PMMA と Al の楔)を撮ってチャネルの応答を合わせる。

最初の 1 本

import numpy as np
import fullseye as fs

spec = fs.ledger.xray_tube_spectrum(80.0, filtration=(("AL", 2.5),))   # 80 kV、Al 2.5 mm
ch = fs.ledger.photon_counting_channels(spec, (20.0, 45.0))            # 窓 20〜45 keV と 45 keV 以上
t = np.zeros((2, 32, 32))
t[0] = 4.0                                                             # 赤身 4 cm
t[1, 10:20, 10:20] = 0.2                                               # 皮質骨 2 mm
sig = fs.ledger.xray_channel_projection(t, ["MUSCLE_ICRU44", "BONE_CORTICAL_ICRU44"], ch, 5e4, seed=1)
b = np.asarray(fs.ledger.basis_material_decompose(sig, ch, ("MUSCLE_ICRU44", "AL"), 5e4))   # 基底ごとの厚み [cm] の並び → (2, 32, 32)
print("骨の位置の Al 相当 %.3f cm、外 %.3f cm" % (b[1, 12:18, 12:18].mean(), b[1, 22:, 22:].mean()))
print(fs.ledger.material_xray_constants("CU", 8.0)["mu_rho_cm2_g"])     # 52.55(NIST)

走らせて見るなら py -3.11 examples/poc_dual_energy_xray.py(図は FULLSEYE_FIGURE_DIR か既定の out/figures/<PoC 名>/)。

裏づけ