细胞内粒子识别与统计作图

问题

贵金属纳米颗粒如纳米金和纳米银

在暗场显微镜下

具有特定颜色的散射光斑

其颜色类型与纳米颗粒的大小,形貌以及聚集状态相关

现在获得了大量暗场细胞图像

细胞存在较高的背景

如何从这样的图像中对粒子进行统计分析


代码实现

因为时间关系,直接上代码,以后再细讲

/*
 * 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");


实现效果

自动识别出的粒子按照其颜色差异被区分,而且在原位做上标记。

猜你喜欢

转载自blog.csdn.net/sheldonxxd/article/details/80932493
今日推荐