void ns_worm_multi_frame_interpolation::generate_heat_map(ns_image_standard & heat_map_out,const unsigned int number_of_frames_used_to_find_stationary_objects_,ns_sql & sql){
	if (time_points.size() == 0)
		throw ns_ex("ns_worm_multi_frame_interpolation::generate_heat_map::No time points available!");
	unsigned long number_of_frames_used_to_find_stationary_objects(number_of_frames_used_to_find_stationary_objects_);
	//0 indicates that the algorithm should choose the best number of points to use

	if (time_points.size() <= 2 && number_of_frames_used_to_find_stationary_objects != 1)
			throw ns_ex("Cannot calculate static mask for such a small number of frames:" ) << time_points.size();

	//if not stationary object frame count is specified, determine one automatically
	if (number_of_frames_used_to_find_stationary_objects_ == 0){
		//for very short experiments (ie heat shock) use a short time interval
		if (time_points.size() < 60)
			number_of_frames_used_to_find_stationary_objects = 3;
		else{
			if (number_of_frames_used_to_find_stationary_objects_ > time_points.size())
				number_of_frames_used_to_find_stationary_objects = time_points.size()/5;
		
			if (number_of_frames_used_to_find_stationary_objects==0)
				number_of_frames_used_to_find_stationary_objects = 2;
		}
	}

	//get image size for heatmap from first threshold
	bool size_loaded = false;
	ns_image_properties heat_map_size;
	for (unsigned int i = 0; i < time_points.size(); i++){
		try{
			//cerr << "Loading heat_map size from time_point " << i << "\n";
			time_points[i]->load_threshold(sql);
			heat_map_size = time_points[i]->threshold.properties();
			size_loaded = true;
			break;
		}
		catch(ns_ex & ex){
			cerr << "Could not open threshold frame for size info: " << ex.text() << "\n";
		}
	}
	if (!size_loaded)
		throw ns_ex("ns_worm_multi_frame_interpolation::generate_heat_map()::Sample region has no usable images!");

	heat_map_size.components = 3;
	heat_map_out.prepare_to_recieve_image(heat_map_size);
	
	for (unsigned int y = 0; y < heat_map_size.height; y++)
			for (unsigned int x = 0; x < 3*heat_map_size.width; x++)
				heat_map_out[y][x] = 0;
	unsigned int i = 0;
	for (std::vector<ns_worm_interpolation_timepoint *>::iterator p = time_points.begin();;){
		//stop at one element before the end.
		std::vector<ns_worm_interpolation_timepoint *>::iterator end_p = time_points.end();
		end_p--;
		if (p == end_p) break;
		try{

			cerr << "Processing frame " << i+1 << "/" << time_points.size() << "\n";
			if (i != 0)
				(*p)->load_threshold(sql);
		}
		catch(ns_ex & ex){
			cerr << ex.text() << "\n";
			p = time_points.erase(p);
			continue;
		}
		for (long y = 0; y < (long)(*p)->threshold.properties().height; y++){
			for (long  x = 0; x < (long)(*p)->threshold.properties().width; x++){
				long color = ns_get_division_from_frame_number(i,number_of_frames_used_to_find_stationary_objects,(unsigned int)time_points.size());
				if ((*p)->threshold[y][x] && heat_map_out[y][3*x+color] < 255)
					heat_map_out[y][3*x+color]++;
			}
		}
		(*p)->clear_threshold();
		p++;
		i++;
	}
	ns_out_frame_count(heat_map_out,number_of_frames_used_to_find_stationary_objects,(unsigned long)time_points.size());
	
}
//A heat map is generated by summing all thresholded frames of a time series.  For the first
//third of the time series, treshold values are added to the red channel of the heat map.
//for the second third of the time series, threshold values are added to the green channel
//for the final, blue.
//This means we can roughly inspect which pixels are constantly bright for the biggining, middle, or end
//of the experiment.
//This function looks for pixels that were bright for a specified fraction of each third of the experiment.
//Such bright pixels, if situated in a region where at least one pixel was bright in the two other thirds
//of the experiment, are added to the output image.
//The output image can then be used to mask out unwanted "static" pixels that represent
//features such as the plate edge or dust.
void ns_worm_multi_frame_interpolation::generate_static_mask_from_heatmap(const ns_image_standard & im, ns_image_standard & out){
	const unsigned int	spatial_smudge_distance(ns_worm_detection_constants::get(ns_worm_detection_constant::allowed_drift_distance_for_objects_during_static_mask_creation)),
						early_strong_threshold(ns_worm_detection_constants::get(ns_worm_detection_constant::proportion_of_early_time_points_present_required_during_static_mask_creation)),  //out of 10
						middle_threshold(ns_worm_detection_constants::get(ns_worm_detection_constant::proportion_of_middle_time_points_present_required_during_static_mask_creation)), //out of 10
						late_threshold(ns_worm_detection_constants::get(ns_worm_detection_constant::proportion_of_late_time_points_present_required_during_static_mask_creation));  //out of 10
	if (im.properties().width < 2 || im.properties().height == 0)
		throw ns_ex("ns_worm_multi_frame_interpolation::Empty heat map was provided");

	
	ns_32_bit number_of_frames_used_to_make_heatmap(0);
	ns_32_bit number_of_frames_used_to_find_stationary_objects(0);

	ns_32_bit time_points_l = 0;
	if (im.properties().description.size() != 0){
		//load frame information from xml spec
		bool found_total(false),
			 found_begin_count(false);
		ns_xml_simple_object_reader xml;
		xml.from_string(im.properties().description);
		for (unsigned int i = 0; i < xml.objects.size(); i++){
			if (xml.objects[i].name == "frame_count"){
				number_of_frames_used_to_make_heatmap = atol(xml.objects[i].value.c_str());
				found_total = true;
			}
			else if (xml.objects[i].name =="number_of_frames_used_to_find_stationary_objects"){
				number_of_frames_used_to_find_stationary_objects = atol(xml.objects[i].value.c_str());
				found_begin_count = true;
			}
		}
		if (!found_total)
			throw ns_ex("ns_worm_multi_frame_interpolation::generate_static_mask_from_heatmap::Could not find total frame count specification in heat map");
		if (!found_begin_count)
			throw ns_ex("ns_worm_multi_frame_interpolation::generate_static_mask_from_heatmap::Could not find number_of_frames_used_to_find_stationary_objects specification in heat map");
	}
	else{
		throw ns_ex("Old style heat maps no longer supported!");
		//old style heatmaps stored pixel information in the first five pixels of the image.
		ns_8_bit a=im[0][0],
			b=im[0][1],
			c=im[0][2],
			d=im[0][3],
			e=im[0][4],
			f=im[0][5];
		if (im[0][0] != im[0][4] || im[0][1] != im[0][5])
			throw ns_ex("ns_worm_multi_frame_interpolation::Could not find watermark specifiying source frame count");	
		ns_8_bit * fr = reinterpret_cast<ns_8_bit *>(&number_of_frames_used_to_make_heatmap);
		fr[0] = im[0][0];
		fr[1] = im[0][1];
		fr[2] = im[0][2];
		fr[3] = im[0][3];
		if (number_of_frames_used_to_make_heatmap < 30)
			 number_of_frames_used_to_find_stationary_objects = number_of_frames_used_to_make_heatmap;
		else if (number_of_frames_used_to_make_heatmap < 90)
			number_of_frames_used_to_find_stationary_objects = number_of_frames_used_to_make_heatmap/3;
		number_of_frames_used_to_find_stationary_objects = number_of_frames_used_to_make_heatmap/9;
	}



	//number_of_frames_used_to_make_heatmap = 306;
	ns_number_of_frames_in_heatmap number_of_frames(number_of_frames_used_to_find_stationary_objects,number_of_frames_used_to_make_heatmap);

	/*cerr << number_of_frames_used_to_make_heatmap << " frames used in heat map, divided into " 
		<< number_of_frames.early << ", "<< number_of_frames.middle << ", and " << number_of_frames.late << "\n";
*/
	if (im.properties().components != 3)
		throw ns_ex("ns_image_server_calculate_heatmap_overlay::Heatmaps must be in color");
	ns_image_properties p(im.properties());
	p.components = 1;
	out.prepare_to_recieve_image(p);

	for (int y = 0; y < (int)p.height; y++){
		for (int x = 0; x < (int)p.width; x++){
			const bool	found_early(10*((unsigned int)im[y][3*x  ]) >= early_strong_threshold*number_of_frames.early),
						found_middle(10*((unsigned int)im[y][3*x+1]) >= middle_threshold*number_of_frames.middle),
						found_late(10*((unsigned int)im[y][3*x+2]) >= late_threshold*number_of_frames.late);
			if(!found_early &&!found_middle &&!found_late){
				out[y][x] = 0;
				continue;
			}

			int x0(x-spatial_smudge_distance),
				x1(x+spatial_smudge_distance),
				y0(y-spatial_smudge_distance),
				y1(y+spatial_smudge_distance);
			if (x0 < 0) x0 = 0;
			if (x1 >= (int)p.width) x1 = (int)p.width-1;
			if (y0 < 0) y0 = 0;
			if (y1 >= (int)p.height) y1 = (int)p.height-1;
			bool cont(true);
			out[y][x] = 0;

			for (int _y = y0; _y < y1 && cont; _y++){
				for (int _x = x0; _x < x1 && cont; _x++){
					if(	10*((unsigned int)im[_y][3*_x  ]) >= early_strong_threshold*number_of_frames.early ||
						(found_early && 
							(10*((unsigned int)im[_y][3*_x+1]) >= middle_threshold*number_of_frames.middle ||
							10*((unsigned int)im[_y][3*_x+2]) >= late_threshold*number_of_frames.late)
						)
					){

						out[y][x] = 255;
						cont = false;
					}
				}
			}
		}
	}
}
Example #3
0
void ns_barcode_encoder::encode(const string & str, ns_image_standard & image, const unsigned int margin_size){
	#ifdef NS_USE_2D_SCANNER_BARCODES
		DmtxEncode encode;
		encode = dmtxEncodeStructInit();
		unsigned char * a(new unsigned char[str.size()+1]);
		try{
			for (unsigned int i = 0; i < str.size(); i++)
				a[i] = str[i];
			a[str.size()] = 0;
			cerr << "Encoding " << a << "\n";
			dmtxEncodeDataMatrix(&encode, (int)str.size(), a, DMTX_SYMBOL_SQUARE_AUTO);
			image.prepare_to_recieve_image(ns_image_properties(encode.image->height+2*margin_size,
															 encode.image->width+2*margin_size,
															 1,150));
			for (unsigned int y = 0; y < image.properties().height; y++)
				for (unsigned int x = 0; x < image.properties().width; x++)
					image[y][x] = 255;

			for (unsigned int y = margin_size; y < image.properties().height-margin_size; y++)
				for (unsigned int x = margin_size; x < image.properties().width-margin_size; x++)
					image[y][x] = encode.image->pxl[encode.image->width*(y-margin_size) + (x-margin_size)][0];

			ns_font & font(font_server.default_font());
			font.draw(margin_size+10,margin_size + encode.image->height + 10,ns_color_8(125,125,125),str,image);

			
			dmtxEncodeStructDeInit(&encode);
			delete[] a;
		}
		catch(...){
			
			dmtxEncodeStructDeInit(&encode);
			delete[] a;
			throw;
		}
	#else
	const unsigned w[3] = {3,6,12};
	const unsigned int spacing = w[1];

	vector <unsigned int> bar_widths;

	for (unsigned int i = 0; i < str.size(); i++){
		unsigned int v;
		if (str[i] == '_')
			v = 26;
		else v = str[i]-'a';
		bar_widths.push_back( w[(v/9)%3]);
		bar_widths.push_back( w[(v/3)%3]);
		bar_widths.push_back( w[(v  )%3]);
	}
	unsigned int total_width = 0;
	for(unsigned int i = 0; i < bar_widths.size(); i++)
		total_width += bar_widths[i] + spacing;
	ns_image_properties prop;
	prop.width = total_width + 2*margin_size;
	prop.height = height*2 + 2*margin_size;
	prop.components = 1;
	prop.resolution = 150;
	image.prepare_to_recieve_image(prop);
	for (unsigned int y = 0; y < prop.height; y++)
		for (unsigned int x = 0; x < prop.width; x++)
			image[y][x] = 255;
	unsigned int x = 0;
	for (unsigned int i = 0; i < bar_widths.size(); i++){
		for (unsigned int y = 0; y < height; y++)
			for (unsigned int dx = 0; dx < bar_widths[i]; dx++)
				image[y+margin_size][x+margin_size+dx] = 0;
		x += bar_widths[i];
		for (unsigned int y = 0; y < height; y++)
			for (unsigned int dx = 0; dx < spacing; dx++)
				image[y+margin_size][x+margin_size+dx] = 255;
		x += spacing;
	}
	font.draw(margin_size,height*3/2+margin_size,ns_color_8(0,0,0),str,image);
	#endif

}