问题
贵金属纳米颗粒如纳米金和纳米银
在暗场显微镜下
具有特定颜色的散射光斑
其颜色类型与纳米颗粒的大小,形貌以及聚集状态相关
现在获得了大量暗场细胞图像
细胞存在较高的背景
如何从这样的图像中对粒子进行统计分析
代码实现
因为时间关系,直接上代码,以后再细讲
/*
* count particles automatically
*/
//global parameters------
hue_blue = 300;
hue_green = 160;
hue_yellow = 65;
dot_k = 10;
p_noise = 20;
//functions------
function mark(){
type = newArray("monomer","dimer","polymer");
Dialog.create("mark it!");
for(i=0;i<lengthOf(type);i++){
Dialog.addNumber(type[i], 0);
}
Dialog.setLocation(900,200);
Dialog.show();
res = newArray(lengthOf(type));
for(i=0;i<lengthOf(type);i++){
res[i] = Dialog.getNumber();
}
return res;
}
function drawmap(map,title,width,height){
n = sqrt(lengthOf(map));
newImage(title,"RGB black",width,height,1);
n_width = width/n;
n_height = height/n;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
x = i*n_width;
y = j*n_height;
c = map[i*n+j];
setColor(30*c,0,0);
fillRect(x,y,n_width,n_height);
setColor(180,180,180);
drawRect(x,y,n_width,n_height);
}
}
}
function adjust(img){
selectWindow(img);
run("Duplicate...","title=adjust");
run("Enhance Contrast","saturated=0.35");
}
//Particle finder------
function finder(Noise){
run("Find Maxima...", "noise="+Noise+" output=List");
selectWindow("Results");
Num = nResults;
Location = newArray(2*Num);
for (j=0;j<Num;j++){
Location[2*j] = getResult("X",j);
Location[2*j+1] = getResult("Y",j);
}
run("Close");
return Location;
}
//Partile filter------
function getRGB(x,y){
RGB = newArray(3);
v = getPixel(x,y);
RGB[0] = (v>>16)&0xff;
RGB[1] = (v>>8)&0xff;
RGB[2] = v&0xff;
return RGB;
}
function RGB2HSI(RGB){
RGB[0] = RGB[0]/255;
RGB[1] = RGB[1]/255;
RGB[2] = RGB[2]/255;
Array.getStatistics(RGB,min,max);
R = RGB[0];
G = RGB[1];
B = RGB[2];
I = (R+G+B)/3;
n = (R-G)+(R-B)+(1e-6);
m = (R-G)*(R-G)+(R-B)*(G-B);
m = 2*sqrt(m)+(1e-6);
sigma = acos(n/m);
if (G>=B) H = sigma;
else H = 2*PI-H;
S = 1 - 3*min/(R+G+B);
HSI = newArray(3);
HSI[0] = H*180/PI;
HSI[1] = S;
HSI[2] = I*255;
return HSI;
}
function getHSI(x,y){
RGB = getRGB(x,y);
HSI = RGB2HSI(RGB);
return HSI;
}
function pcheck(x,y){
s = 17;
n = (s-1)/2;
bri = newArray(n);
for(i=0;i<n;i++){
makeRectangle(x-n+i,y-n+i,s-2*i,s-2*i);
getStatistics(area, mean, min, max, std, histogram);
bri[i] = mean;
}
k = newArray(4);
for(i=0;i<4;i++){
k[i] = bri[i+4]-bri[i+3];
}
Array.getStatistics(k,min,max,mean,sd);
if (mean>dot_k && sd<3) return true;
else return false;
}
function collectpixels(x,y){
s = 5;
makeRectangle(x,y,s,s);
getStatistics(area, mean, min, max, std, histogram);
setMinAndMax(min,max);
pixels = newArray(s*s);
for(i=0;i<s;i++){
for(j=0;j<s;j++){
pixels[s*i+j]=getPixel(x+i,y+j);
}
}
return pixels;
}
function pHSI(pixels){
n = lengthOf(pixels);
HueSum = 0;
Hue_n = 0;
SatSum = 0;
Sat_n = 0;
BriSum = 0;
Bri_n = 0;
for(i=0;i<n;i++){
RGB = newArray(3);
v = pixels[i];
RGB[0] = (v>>16)&0xff;
RGB[1] = (v>>8)&0xff;
RGB[2] = v&0xff;
HSI = RGB2HSI(RGB);
if (HSI[2]>50){
if (HSI[1]>0.2){
HueSum = HueSum + HSI[0];
Hue_n = Hue_n + 1;
SatSum = SatSum + HSI[1];
Sat_n = Sat_n + 1;
BriSum = BriSum + HSI[2];
Bri_n = Bri_n + 1;
}
}
}
hsi = newArray(HueSum/Hue_n,SatSum/Sat_n,BriSum/Bri_n);
return hsi;
}
function pfilter(x,y){
pixels = collectpixels(x,y);
hsi = pHSI(pixels);
if (hsi[0]>hue_blue && hsi[2]>0.2){
type = 1;
}
else if (hsi[0]<hue_green && hsi[0]>hue_yellow){
type = 2;
}
else if (hsi[0]<=hue_yellow){
type = 3;
}
else {
type = 0;
}
return type;
}
function automark(img){
selectWindow(img);
res = newArray(3); //(monomer,dimer,polymer);
Loc = finder(20);
num = lengthOf(Loc)/2;
num_monomer = 0;
num_dimer = 0;
num_polymer = 0;
for(i=0;i<num;i++){
x = Loc[2*i];
y = Loc[2*i+1];
if (pcheck(x,y)){ //调用pcheck
type = pfilter(x,y);
if (type==1){
num_monomer = num_monomer + 1;
}
if (type==2){
num_dimer = num_dimer + 1;
}
if (type==3){
num_polymer = num_polymer + 1;
}
}
}
res[0] = num_monomer;
res[1] = num_dimer;
res[2] = num_polymer;
return res;
}
function getparticlemap(img){
selectWindow(img);
Loc = finder(p_noise);
num = lengthOf(Loc)/2;
num_monomer = 0;
num_dimer = 0;
num_polymer = 0;
map = newArray(3*num);
for(i=0;i<num;i++){
x = Loc[2*i];
y = Loc[2*i+1];
if (pcheck(x,y)){
type = pfilter(x,y);
}
else type = -1;
map[3*i] = x;
map[3*i+1] = y;
map[3*i+2] = type;
}
return map;
}
function drawparticlemap(map,title,width,height){
num = lengthOf(map)/3;
newImage(title,"RGB black",width,height,1);
p_size = 5;
for(i=0;i<num;i++){
x = map[3*i];
y = map[3*i+1];
type = map[3*i+2];
if (type==0){
setColor(150,0,150);
fillOval(x-p_size,y-p_size,p_size*2+1,p_size*2+1);
}
if (type==1){
setColor(0,0,150);
fillOval(x-p_size,y-p_size,p_size*2+1,p_size*2+1);
}
if (type==2){
setColor(0,150,0);
fillOval(x-p_size,y-p_size,p_size*2+1,p_size*2+1);
}
if (type==3){
setColor(150,150,0);
fillOval(x-p_size,y-p_size,p_size*2+1,p_size*2+1);
}
}
}
//execuation------
ID = getTitle();
run("Duplicate...","title=back");
width = getWidth();
height = getHeight();
map = getparticlemap(ID);
drawparticlemap(map,"remap",width,height);
//image calculator
selectWindow("back");
run("8-bit");
setMinAndMax(0,512);
run("RGB Color");
imageCalculator("Add create", "back","remap");
实现效果
自动识别出的粒子按照其颜色差异被区分,而且在原位做上标记。