省型旧形国電の残影を求めて

戦前型旧形国電および鉄道と変褪色フィルム写真を中心とした写真補正編集の話題を扱います。他のサイトでは得られない、筆者独自開発の写真補正ツールや補正技法についても情報提供しています。写真補正技法への質問はコメント欄へどうぞ

ImageJ / Python プログラミング Tips: 32-bit 画像で所定の閾値を超えたピクセル値をクリップする

 ImageJ の 32-bit 浮動小数点画像 (FloatProcessor) は 8-bit (ByteProcessor), 16-bit 整数画像 (ShortProcessor) とは異なり、所定の値を超えてもデータがクリップすることはありませんし、負の値もとることがあります。8-bit, 16-bit 整数画像は、正負符号のない (unsigned) 0-255, もしくは 0-65535 までの値を取り、この範囲を超えた場合は 0 もしくは最大値 (255 or 65535) にクリップされます。

 この32-bit データのクリップしないという特徴は都合が良い場合もありますが、不都合な場合もあります。一般的な 32-bit 浮動小数点画像データは、0.0-1.0 を取ることが多いですが、計算上その範囲を下回ったり上回ってもデータがクリップされません。これをマイナスの値を取る場合は 0.0 に、また 1.0 を上回る場合は 1.0 にクリップさせるにはどうしたら良いでしょうか。

 当初は threshold と ROI を組み合わせていろいろやろうとしましたが、よく考えたら、より簡単な方法がありました。

 以下、マイナスの値を取ったら、0.0 に直すユーザ作成関数の例です。なお、FloatProcessor を含む ImagePlus を読み込むことを前提としています。

-----------------------

def clipUnder0(imp):
    ip0 = imp.getProcessor()
    ip1 = FloatProcessor(ip0.width, ip0.height)
    ip1.setValue(0.0)
    ip1.fill()
    imp1 = ImagePlus("imp1", ip1)
    ic = plugin.ImageCalculator()
    imp2 = ic.run("Max created", imp, imp1)
    imp2.setLut(None)
    imp1.close()
    imp.close()
    return imp2

-----------------------

 オリジナルの画像は imp として読み込みます。元の画像と同じサイズで、0.0 で塗りつぶした imp1 という ImagePlus を作成し、Image Calculator でオリジナルの画像 (imp) と比較明の画像 imp2 を作っています。すると、マイナスの値を取るピクセルは 0.0 で塗りつぶされた画像が出来上がります。

 同様に、1.0 を超えたピクセルはすべて、1.0 に塗潰す関数は...

 

-----------------------

def clipOver1(imp):
    ip0 = imp.getProcessor()
    ip1 = FloatProcessor(ip0.width, ip0.height)
    ip1.setValue(1.0)
    ip1.fill()
    imp1 = ImagePlus("imp1", ip1)
    ic = plugin.ImageCalculator()
    imp2 = ic.run("Min created", imp, imp1)
    imp2.setLut(None)
    imp1.close()
    imp.close()
    return imp2

-----------------------

 こちらは、1.0 で塗りつぶした imp1 という ImagePlus を作成し、Image Calculator を使って、オリジナル画像との比較暗の画像を作成します。すると 1.0 を超えた部分はすべて 1.0 に揃った画像を戻り値として出力します。

 なお、 Image Calculator を使っていますので、以下のインポート文が必要です。

from ij import plugin