Commit 40aadecf authored by David Svoboda's avatar David Svoboda
Browse files

Texture improvement:

- distribution of fluorescent points along filopodia
- modification innner structure of nuclei
- modification of camera noise to resemble the real images
parent b5c25c82
Loading
Loading
Loading
Loading
+54 −21
Original line number Diff line number Diff line
@@ -1410,6 +1410,10 @@ void ActiveMesh::ScaleMesh(const Vector3F& scale)
			filoMesh.fPoints[i].y*=scale.y;
			filoMesh.fPoints[i].z*=scale.z;
		}
		for (unsigned int i=0; i< filoMesh.segFromRadius.size(); i++)
		{
			 filoMesh.segFromRadius[i] *= 80.f;
		}
	}
}

@@ -1456,13 +1460,14 @@ void ActiveMesh::InitDots_body(const i3d::Image3d<i3d::GRAY16>& mask)

	i3d::Image3d<float> perlinInner,perlinOutside;
	perlinInner.CopyMetaData(mask);
	DoPerlin3D(perlinInner,5.0,0.8*1.5,0.7*1.5,6);
//	DoPerlin3D(perlinInner,5.0,0.8*1.5,0.7*1.5,6);
	DoPerlin3D(perlinInner,1.0,0.8*1.3,0.7*1.5,6);
#ifdef SAVE_INTERMEDIATE_IMAGES
	//perlinInner.SaveImage("2_PerlinAlone_Inner.ics");
#endif

	perlinOutside.CopyMetaData(mask);
	DoPerlin3D(perlinOutside,1.8,0.8*1.5,0.7*1.5,6);
	DoPerlin3D(perlinOutside,1.4,0.8*1.1,0.7*1.5,6);
#ifdef SAVE_INTERMEDIATE_IMAGES
	//perlinOutside.SaveImage("2_PerlinAlone_Outside.ics");
#endif
@@ -1482,9 +1487,17 @@ void ActiveMesh::InitDots_body(const i3d::Image3d<i3d::GRAY16>& mask)
		if (*p > 0.f)
		{
			//close to the surface?
			if (*p < 0.3f || *er == 0) *p=2000.f + 5000.f*(*pO); //corona
			else                       *p=600.f  + 600.f*(*pI);  //inside
			if (*er == 0) *p=2000.f; //std::max(*p,2000.f);                //corona
			if (*p < 0.2f || *er == 0) 
				 *p=1000.f + 5000.f*(*pO); //corona
			else if (*p < 0.4f)
			{
				 float factor = (*p - 0.2f)/(0.2f);
				 *p=(300.f  + 600.f*(*pI))*factor +  (1000.f + 5000.f*(*pO))*(1.0f-factor);
			}
			else
				 *p=300.f  + 600.f*(*pI);  //inside

			if (*er == 0) *p=1500.f; //corona

			if (*p < 0.f) *p=0.f;
		}
@@ -1551,8 +1564,8 @@ void ActiveMesh::InitDots_filo(const i3d::Image3d<i3d::GRAY16>& mask,const unsig
		const float length=(tP-fP).Len(); //full segment has length = 0.005

		//stepping along the axis
		const int S=(int)ceil(5.f*length/0.005); //"fraction factor"
		//std::cout << "S=" << S << ", length=" << length << "\n";
		const int S=(int)ceil(5.f*length/0.005); //"fraction factor"\

		for (int s=0; s < S; ++s)
		{
			//ratios "from" and "to"
@@ -1570,19 +1583,39 @@ void ActiveMesh::InitDots_filo(const i3d::Image3d<i3d::GRAY16>& mask,const unsig
			         p+=tS*tP;

			//insert fl. dots
			r*=4000.f;
			float dotsCount=400000.f*r;

			// prevent data overflow (5 - multiplicity of addition)
			int upper_limit = std::numeric_limits<i3d::GRAY16>::max() / (5 * TEXTURE_QUANTIZATION);
			int qM=(dotsCount > upper_limit)? upper_limit : (int)dotsCount;

			// establish 4 vectors  - all orthogonal to the direction of filopodium
			Vector3F mainDirection = tP-fP;
			Vector3F vector1(-mainDirection.y, mainDirection.x, 0.0f);
			Vector3F vector2(-vector1.x, -vector1.y, -vector1.z);

			Vector3F vector3;
			Mul(mainDirection, vector1, vector3);

			//std::cout << s << ": r=" << r << ", r*r=" << r*r << "\n";
			Vector3F vector4;
			Mul(mainDirection, vector2, vector4);

			// make them as small as the size of the radius in the given position
			vector1 *= r / vector1.Len();
			vector2 *= r / vector2.Len();
			vector3 *= r / vector3.Len();
			vector4 *= r / vector4.Len();

			//float dotsCount=10.f*r*r;
			float dotsCount=100.f*r;
			int qM=(dotsCount > 1300.f)? 1300 : (int)dotsCount;

			for (int q=0; q < qM; ++q)
			{
				dots_filo.push_back(p);
				dots_filo.push_back(p+Vector3F(0.0f,0.0f,+0.1f));
				dots_filo.push_back(p+Vector3F(0.0f,0.0f,-0.1f));
				//dots_filo.push_back(p+Vector3F(0.0f,0.0f,+100*r));
				//dots_filo.push_back(p+Vector3F(0.0f,0.0f,-100*r));
				dots_filo.push_back(p+vector1);
				dots_filo.push_back(p+vector2);
				dots_filo.push_back(p+vector3);
				dots_filo.push_back(p+vector4);
			}
		}
	}
@@ -1897,10 +1930,6 @@ void ActiveMesh::PhaseII(const i3d::Image3d<i3d::GRAY16>& texture,
	// convolution with real confocal PSF
	i3d::Convolution<double>(fimg, psf, blurred_texture);

	// DEPRECATED - remove:
	// i3d::GaussIIR(intermediate,3.f,3.f,2.5f);
	// i3d::GaussIIR(intermediate,2.f,2.f,2.f);

#ifdef SAVE_INTERMEDIATE_IMAGES
	blurred_texture.SaveImage("4_texture_blurred.ics");
#endif
@@ -1930,6 +1959,10 @@ void ActiveMesh::PhaseIII(i3d::Image3d<float>& blurred,
	float* p=blurred.GetFirstVoxelAddr();
	for (size_t i=0; i<blurred.GetImageSize(); i++, p++)
	{
		// shift the signal (simulates non-ideal black background)
		// ?reflection of medium?
		*p+=10.0f;

		// PHOTON NOISE 
		// uncertainty in the number of incoming photons
		// from statistics: shot noise = sqrt(signal) 
@@ -1938,16 +1971,16 @@ void ActiveMesh::PhaseIII(i3d::Image3d<float>& blurred,
		// for Poisson distribution E(X) = D(X)
		const float noiseVar = noiseMean; 

		*p+=30.f*((float)GetRandomPoisson(noiseMean) - noiseVar);
		*p+=40.f*((float)GetRandomPoisson(noiseMean) - noiseVar);

		// DARK CURRENT NOISE
		// DARK CURRENT
		// constants are parameters of Andor iXon camera provided from vendor:
		*p+=(float)GetRandomPoisson(0.06f);

		// READOUT NOISE
		// variance up to 25.f (old camera on ILBIT)
		// variance about 1.f (for the new camera on ILBIT)
		*p+=GetRandomGauss(560.f,15.f);
		*p+=GetRandomGauss(450.f,10.f);
	}
#ifdef SAVE_INTERMEDIATE_IMAGES
	blurred.SaveImage("6_texture_finalized.ics");