2019年2月6日

使用imagej Macro客製化imagej的LUT(lookup table)

這兩天在我的imagej教學影片《05 imagej的LUT》上,有人留言詢問了問題:

你好,我想请问一下如何只是显示比如说25到150之间的lut,而小于25和大于150点不显示,而且在添加calibration bar的时候也是显示25-150呢?谢谢啦!
我现在的问题是我把8bit的图片的lut设置成了jet,也就是最低的灰度值为蓝色,最高的255为红色。但是呢我的图片最高的灰度值为150,最低的为25,我想在这个范围内设置为jet的lut可以吗?也就是25的灰度值为蓝色,150的灰度值为红色。且中间的颜色变化是像jet中连续的。我的问题有点儿长,不知道是不是说明白了。谢谢您!


lut是用來視覺化圖片的工具,作用就是把8bit灰階圖片著色,lut提供的就是著色的規則表。例如。例如下圖左下角的LUT規定了「72這個灰階值,要用R0 G159 B255的顏色來著色」


不同的顏色規則就會形成不同的規則表,在imagej裡頭預設就有數十種LUT可以使用。利用Image/Color/Display LUTs 可以顯示這些LUT


其實我並不太在youtube回答留言者的問題,因為光是我Gmail裡的問題我就回答不完了,再者是youtube的留言提問,並沒有辦法附圖去說明。不過因為留言者的問題剛好跟我過去想解決的問題有關,他寫出的問題有我需要的關鍵字,所以我就投入去找資料了。

留言回應者提到的LUT名稱叫做「jet」,我翻了好久倒是沒看到。後來去查才知道是Matlab這個程式裡頭的LUT,它的顏色配置就是本文第一張圖左上角的樣子,就像是彩虹的顏色。


要解決留言回應者的問題前,得先找到方法去做出這個規則。一開始是在一個論壇上看到有imagej Macro的解法,幾行就可以生成jet lut

r=newArray(256);g=newArray(256);b=newArray(256); 
for (i=0;i<256;i++) { 
    i4=4*i/256; 
    r[i]=255*minOf(maxOf(minOf(i4-1.5,-i4+4.5),0),1); 
    g[i]=255*minOf(maxOf(minOf(i4-0.5,-i4+3.5),0),1); 
    b[i]=255*minOf(maxOf(minOf(i4+0.5,-i4+2.5),0),1); 

setLut(r,g,b); 


雖然可以生出jet Colormap,但是中間的i4-1.5或是-i4+4.5,弄不懂怎麼修改,所以暫時放下,繼續找其他文章。後來在stackoverflow的討論串裡找到解法。


這樣的解法就容易修改了,我只要縮窄原有的範圍(從256縮到151),再做位移(從0往後位移到25)就可以了。根據這位提問者的需求,做出來的就會是這樣。



在imagej點選File/New/Text Window,把下面這段貼到視窗裡,然後把Text Window的Language設定為IJ1 Macro,再按下Run/Run就可以修改Lut了。

在前幾行的xrange、xoffset和NanFill的數值都可以依照需求修改。
==============================================

run("8-bit");

xrange = 126; //灰階值範圍,不需特製的話,使用256
xoffset = 25; //最低灰階值,不需特製的話使用0
NaNFill = 255; //沒有灰階的部份填充的顏色,白色為255,黑色為0

r=newArray(256);
g=newArray(256);
b=newArray(256);

for (i=0;i<xrange;i++) {
x= -1 + i/(xrange/2);
r0 = 1.5 - abs(2*x -1);
    g0 = 1.5 - abs(2*x);
    b0 = 1.5 - abs(2*x +1);
   
    //clamp
    r[i+xoffset]=255*minOf(maxOf(r0,0),1);
    g[i+xoffset]=255*minOf(maxOf(g0,0),1);
    b[i+xoffset]=255*minOf(maxOf(b0,0),1);
}

//填充灰階值下界
for (i=0;i<xoffset;i++) {
r[i]=NaNFill;
    g[i]=NaNFill;
    b[i]=NaNFill;
}
//填充灰階值上界
for (i=xrange+xoffset;i<256;i++) {
r[i]=NaNFill;
    g[i]=NaNFill;
    b[i]=NaNFill;
}

setLut(r,g,b);  //設定LUT
run("Show LUT");  //顯示LUT的list