2015年10月24日

imagej用Macro測多層厚度

補:有新的作法,請見 imagej用Macro邊緣偵測後測量多層厚度

有網友寫信來問imagej的問題「怎麼測多層膜的厚度」

哎呦!那還不簡單,就一條一條畫線,然後用Analyze/Measure不就好了。如果有一百層,那就作一百次就好了啊。

如果真的這樣作,應該會死人吧?那怎麼作哩?

那就要靠coding了,imagej有提供Macros(巨集)的功能,線上也有詳細的說明書,另外還有幾百個範例檔。於是我研究了一下,寫一個簡單的程式就搞定了。

方法是這樣
先設定好你要的臨界灰階值是多少?意思就是用灰階值去區分你的不同層材料,比方說灰階值100以上就叫做A層,100以下叫做B層。那接下來就是用profile的功能去畫出x軸和灰階值的折線圖,然後去找出來這個折線圖和臨界灰階那條橫線的交會點。找到數個交會點之後,把x座標減一減,就可以得到各層的厚度了。

好的,我打賭應該看不懂我寫什麼,沒關係,反正那是寫給我看的。

底下有錄製一段影片,有需求的就自己看看,然後程式碼擺在本文章最底下,複製貼上自己改就行了。





macro "Measure Multilayers" {
    Dialog.create("Set Threshold");
    Dialog.addNumber("threshold:", 100);
    Dialog.show();
 
    thre = Dialog.getNumber();
    run("Clear Results");
    print("\\Clear")
    profile = getProfile();
    getPixelSize(scale, pixelSize, trash);
    xAxis=newArray(profile.length)
    x1=newArray(profile.length);
    var j=0;

    for (i=0; i<profile.length; i++)
        xAxis[i]=i*pixelSize;
        for (i=0; i<profile.length-1; i++){

            if(profile[i]<thre && profile[i+1]>thre) {
            x1[j]=i;
            j++;
            }

            if(profile[i]>thre && profile[i+1]<thre) {
            x1[j]=i;
            j++;
            }
        }

    k=0;
    while(x1[k+1]!=0){
        print(k+1,"\t",(x1[k+1]-x1[k])*pixelSize,scale);
        k++;
    }


    Plot.create("profile","Distance "+ scale, "Grey Value", xAxis,profile);
    Plot.show();
}