void ns_movement_visualization_generator::create_time_path_analysis_visualization(const ns_image_server_captured_image_region & region_image, const ns_death_time_annotation_compiler_region & compiler_region,const ns_image_standard & grayscale, ns_image_standard & out,ns_sql & sql){ unsigned long thickness = 4; const ns_color_8 excluded_color = ns_color_8(50,50,255); ns_image_properties prop(grayscale.properties()); prop.components = 3; out.init(prop); for (unsigned int y = 0; y < prop.height; ++y){ for (unsigned long x = 0; x < prop.width; ++x){ out[y][3*x+0] = 255-grayscale[y][x]; out[y][3*x+1] = 255-grayscale[y][x]; out[y][3*x+2] = 255-grayscale[y][x]; } } /* ns_death_time_annotation_set movement_annotations; // movement_annotations.events.reserve(death_time_annotations.size()); // for (unsigned long i = 0; i < death_time_annotations.size(); i++){ switch(death_time_annotations[i].type){ case ns_fast_moving_worm_observed: case ns_slow_moving_worm_observed: case ns_posture_changing_worm_observed: case ns_stationary_worm_observed: movement_annotations.push_back(death_time_annotations[i]); } } */ ns_image_worm_detection_results results; results.id = region_image.region_detection_results_id; results.load_from_db(false,false,sql); ns_image_server_captured_image_region region_t(region_image); results.load_images_from_db(region_t,sql); const std::vector<const ns_detected_worm_info *> detected_worms(results.actual_worm_list()); ns_font & font(font_server.default_font()); const unsigned long font_height(25); font.set_height(font_height); std::vector<const ns_death_time_annotation *> representative_state_event_for_location(compiler_region.locations.size(),0); for (unsigned int i = 0; i < compiler_region.locations.size(); i++){ for (unsigned int j = 0; j < compiler_region.locations[i].annotations.size(); j++){ if (ns_movement_event_is_a_state_observation(compiler_region.locations[i].annotations[j].type) && compiler_region.locations[i].annotations[j].time.period_end == region_image.capture_time){ if (representative_state_event_for_location[i] != 0){ cerr << "Found multiple state events for a time!\n"; } else representative_state_event_for_location[i] = &compiler_region.locations[i].annotations[j]; } } } std::vector<const ns_death_time_annotation *> fast_moving_animal_matches(detected_worms.size(),0); for (unsigned int i = 0; i < compiler_region.fast_moving_animals.size(); i++){ for (unsigned long w = 0; w < detected_worms.size(); w++){ if (detected_worms[w]->region_size == compiler_region.fast_moving_animals[i].size && detected_worms[w]->region_position_in_source_image == compiler_region.fast_moving_animals[i].position){ fast_moving_animal_matches[w] = &compiler_region.fast_moving_animals[i]; } } } //for debugging std::vector<char> locations_matched(representative_state_event_for_location.size(),0); unsigned long locations_with_matches(0); //for real use std::vector<ns_death_time_annotation_compiler_region::ns_location_list::const_iterator> location_matches(detected_worms.size(),compiler_region.locations.end()); unsigned long unmatched_detected_worms(0); for (unsigned long w = 0; w < detected_worms.size(); w++){ for (unsigned int i = 0; i < representative_state_event_for_location.size(); i++){ if (representative_state_event_for_location[i] == 0) continue; if (detected_worms[w]->region_size == representative_state_event_for_location[i]->size && detected_worms[w]->region_position_in_source_image == representative_state_event_for_location[i]->position){ if(location_matches[w] != compiler_region.locations.end()){ cerr << "Found multiple locations that match detected worm!\n"; } else{ //for debugging locations_matched[i] = 1; locations_with_matches++; //for real use location_matches[w] = compiler_region.locations.begin()+i; } } } if (fast_moving_animal_matches[w] == 0 && location_matches[w]== compiler_region.locations.end()) unmatched_detected_worms++; } if (unmatched_detected_worms > 0) cerr << "Could not match up " << unmatched_detected_worms << " of " << detected_worms.size() << " animals.\n"; for (unsigned long w = 0; w < detected_worms.size(); w++){ const ns_death_time_annotation_compiler_region::ns_location_list::const_iterator location(location_matches[w]); const ns_death_time_annotation * fast_animal_match(fast_moving_animal_matches[w]); const ns_vector_2i & pos = detected_worms[w]->region_position_in_source_image; //if we can't find info on the object, paint it white. if (fast_animal_match == 0 && location== compiler_region.locations.end()){ const ns_color_8 color(255,255,255); ns_vector_2i size = detected_worms[w]->region_size; out.draw_line_color_thick(pos,pos+ns_vector_2i(size.x,0),color,3); out.draw_line_color_thick(pos,pos+ns_vector_2i(0,size.y),color,3); out.draw_line_color_thick(pos+ns_vector_2i(0,size.y),pos+size,color,3); out.draw_line_color_thick(pos+ns_vector_2i(size.x,0),pos+size,color,3); continue; } ns_color_8 color; if (location != compiler_region.locations.end()){ color = (ns_movement_colors::color(ns_movement_event_state(representative_state_event_for_location[location-compiler_region.locations.begin()]->type))); if (location->properties.is_excluded()) color = excluded_color; } else color = ns_movement_colors::color(ns_movement_fast); for (unsigned int y = 0; y < detected_worms[w]->bitmap().properties().height; y++){ for (unsigned int x = 0; x < detected_worms[w]->bitmap().properties().width; x++){ if (detected_worms[w]->bitmap()[y][x]){ out[pos.y + y][3*(pos.x + x)+0] = (ns_8_bit)(.75*color.x + .25*out[pos.y + y][3*(pos.x + x)+0]); out[pos.y + y][3*(pos.x + x)+1] = (ns_8_bit)(.75*color.y + .25*out[pos.y + y][3*(pos.x + x)+1]); out[pos.y + y][3*(pos.x + x)+2] = (ns_8_bit)(.75*color.z + .25*out[pos.y + y][3*(pos.x + x)+2]); } } } ns_color_8 edge_color(color); if (location != compiler_region.locations.end() && location->properties.number_of_worms_at_location_marked_by_hand > 1){ // font.draw_color(pos.x + (detected_worms[w]->region_size.x*3)/4,pos.y+font_height,ns_color_8(255,255,255),std::string("") + // ns_to_string(location->properties.number_of_worms_at_location_marked_by_hand),out); edge_color = ns_color_8(255,180,120); const int edge_width(3); // use signed ints for x and y so that "x + dx" type expressions are also properly signed. for (int y = 0; y < detected_worms[w]->edge_bitmap().properties().height; y++){ for (int x = 0; x < detected_worms[w]->edge_bitmap().properties().width; x++){ if (detected_worms[w]->edge_bitmap()[y][x]){ for (int dx = -edge_width; dx <= edge_width; dx++) for (int dy = -edge_width; dy <= edge_width; dy++){ if ( dx + dy > edge_width) continue; //round edges if (x + dx < 0 || x + dx >= detected_worms[w]->edge_bitmap().properties().width) continue; if (y + dy < 0 || y + dy >= detected_worms[w]->edge_bitmap().properties().height) continue; out[pos.y + y+dy][3*(pos.x + x+dx)+0] = (ns_8_bit)(.2*(ns_8_bit)(edge_color.x) + .8*out[pos.y + y+dy][3*(pos.x + x+dx)+0]); out[pos.y + y+dy][3*(pos.x + x+dx)+1] = (ns_8_bit)(.2*(ns_8_bit)(edge_color.y) + .8*out[pos.y + y+dy][3*(pos.x + x+dx)+1]); out[pos.y + y+dy][3*(pos.x + x+dx)+2] = (ns_8_bit)(.2*(ns_8_bit)(edge_color.z) + .8*out[pos.y + y+dy][3*(pos.x + x+dx)+2]); } } } } } } for (unsigned int i = 0; i < compiler_region.locations.size(); i++){ if (representative_state_event_for_location[i] == 0 || locations_matched[i]) continue; const ns_death_time_annotation & a(*representative_state_event_for_location[i]); if (compiler_region.locations[i].properties.inferred_animal_location){ ns_color_8 color = ns_movement_colors::color(ns_movement_event_state(a.type)); if (compiler_region.locations[i].properties.is_excluded()) color = excluded_color; unsigned long thickness = 4; out.draw_line_color_thick(a.position,a.position + ns_vector_2i(a.size.x,0),color,thickness,.8); out.draw_line_color_thick(a.position,a.position + ns_vector_2i(0,a.size.y),color,thickness,.8); out.draw_line_color_thick(a.position+ns_vector_2i(a.size.x,0),a.position + ns_vector_2i(a.size.x,a.size.y),color,thickness,.6); out.draw_line_color_thick(a.position+ns_vector_2i(0,a.size.y),a.position + ns_vector_2i(a.size.x,a.size.y),color,thickness,.6); } } }