2016年8月11日

用Imagej測最大粒徑和最小粒徑--Rotating calipers

Imagej要測量一個顆粒的最大徑最小徑,用其內建功能就行
請看此篇
用Imagej測最大粒徑和最小粒徑

不過測量最大徑最小徑,還有一種叫做Rotating calipers。上面的連結中,本來有個外掛就是用那個演算法在測最大徑最小徑的,不過後來外掛死掉了。

Rotating Caliper又叫做旋轉卡殼,想像有個兩條平行的尺夾住你要測量的多邊形,一邊夾一邊旋轉。(可以看看這篇連結文章,寫得很清楚)
计算几何之凸包(三) {旋转卡壳初步


前幾天為了作最小徑,又不想用Feret的方法,所以就嘗試用了Rotating Caliper的演算法來測量顆粒的長徑和短徑,是用Imagej的Macro寫成的。把底下的程式複製之後貼到Imagej的Plugin/New/Macro,然後去Run就行了。

執行前要先把選取區都加入ROI裡頭,這個Macro就是去處理每個ROI裡的多邊形選取區,去計算利用Rotating Caliper夾出來的最大徑和最小徑。這個會和Feret的徑會不一樣長,因為是不同的夾法。

在Result視窗或是Log視窗出現的MinCaliper和MaxCaliper就是測量的結果。


=========================
vResult=getValue("results.count");
IJ.deleteRows(0,vResult);

//count how many selection in ROI Manager
n = roiManager("count");
for (i=0; i<n; i++) {
    roiManager("select", i);
    run("Convex Hull");
    roiManager("Update");

    getStatistics(area, mean);
    setResult("Area",  i, area);
    setResult("Mean", i, mean);

//measure each selection area
    getSelectionCoordinates(x, y);
//how many points in the polygon >>m
    m =x.length;


    lengthArray=newArray(m);
    for (j=0; j<m; j++){
//        print(i);
        area = 0;
//how many triangle in the polygon>>m-2
        areaArray=newArray(m-1);

        for (k=1; k<m;k++){
                p0=j%m;
                p1=(j+1)%m;
                p2=(j+1+k)%m;
                lengthBottom=sqrt(pow((x[p0]-x[p1]),2)+pow((y[p0]-y[p1]),2));
//                print(p0+" "+p1+" "+p2);
                area += x[p0]*y[p1] - x[p1]*y[p0];
                area += x[p1]*y[p2] - x[p2]*y[p1];
                area += x[p2]*y[p0] - x[p0]*y[p2];
                area /= 2;
                if (area<0) area = -area;
                //print(i+" "+p0+" "+p1+" "+p2+" "+area);
                //print(area);
                areaArray[k-1]=area;
                if(k>1){
                        if(areaArray[k-1]<areaArray[k-2]) {
                                //print(areaArray[k-2]);  //Maximan Area
                                height=areaArray[k-2]*2/lengthBottom;
                                //print(height);
                                break;
                        }
                }
        }

                lengthArray[j]=height;
    }
    MinCaliper=Array.findMinima(lengthArray,1);
    MaxCaliper=Array.findMaxima(lengthArray,1);
    print("MinCaliper:"+lengthArray[MinCaliper[0]]);
    print("MaxCaliper:"+lengthArray[MaxCaliper[0]]);
    setResult("MinCaliper",  i, lengthArray[MinCaliper[0]]);
    setResult("MaxCaliper", i, lengthArray[MaxCaliper[0]]);
}