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; } } } } } }
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 }