示例#1
0
 def filter(self, plants):
     
     for k, plant in enumerate(plants):
         
         if k == 0 or k == len(plants) - 1:
             continue
         
         last_plant = plants[k-1]
         next_plant = plants[k+1]
         
         last_dist = position_difference(last_plant.position, plant.position)
         next_dist = position_difference(next_plant.position, plant.position)
         
         min_dist = min(last_dist, next_dist)
         max_dist = max(last_dist, next_dist)
         
         if min_dist == 0:
             continue # protect against division by zero
         
         ratio = max_dist / min_dist
         
         if ratio <= self.spacing_thresh:
             continue # good spacing so don't need to do anything
         
         # Bad spacing so move plant to be in center
         avg_position = np.mean([last_plant.position, next_plant.position], axis=0)
         
         plants[k] = CreatedPlant(name='plant', position=avg_position, zone=last_plant.zone)
         
         self.num_plants_moved += 1
             
示例#2
0
 def find_actual_plant(self, possible_plants, segment):
     
     for possible_plant in possible_plants:
         distance_to_code = position_difference(possible_plant['position'], segment.start_code.position)
         
         closeness_penalty = self.calculate_closeness_penalty(distance_to_code)
         num_items_penalty = self.calculate_num_items_penalty(possible_plant)
         
         possible_plant['penalty'] = closeness_penalty + 0.2*num_items_penalty
         
     valid_plants = [p for p in possible_plants if not math.isnan(p['penalty'])]
         
     if len(valid_plants) == 0:
         best_plant = None # none of the possible plants worked out
     else:
         best_plant = sorted(valid_plants, key=lambda p: p['penalty'])[0]
         
     if best_plant is None:
         position = segment.start_code.position
         bounding_rect = None
     else:
         position = best_plant['position']
         bounding_rect = best_plant['rect']
         self.num_successfully_found_plants += 1
         
     plant = Plant(name=segment.start_code.name, position=position, zone=segment.start_code.zone, bounding_rect=bounding_rect)
     
     return plant
示例#3
0
def remove_plant_parts_close_to_code(plant_parts, code, closest_dist):
    '''Return updated plant part list such that none are within 'closest_dist' of code.'''
    filtered_plant_parts = []
    for part in plant_parts:
        x, y = corner_rect_center(part['rect'])
        dist_to_item = position_difference((x, y), code.position)
        if dist_to_item > closest_dist:
            filtered_plant_parts.append(part)

    return filtered_plant_parts
def check_code_precision(merged_codes):
    # Sanity check that multiple references of the same code are all close to each other.
    largest_separation = 0
    sum_separation = 0
    sum_separation_count = 0
    for code in merged_codes:
        for code_ref in code.all_refs:
            diff = position_difference(code.position, code_ref.position)
            sum_separation += diff
            sum_separation_count += 1
            if diff > largest_separation:
                largest_separation = diff
                
    average_separation = 0
    if sum_separation_count > 0:
        average_separation = sum_separation / sum_separation_count
                
    print "From average position largest separation is {} and average is {}".format(largest_separation, average_separation)
def warn_about_missing_single_code_lengths(single_segments, spacing_between_plants):

    num_good_lengths = 0 # how many groups have a close to expected length
    num_too_long = 0 # how many groups have a longer than expected length
    for k, segment in enumerate(single_segments[:-1]):

        next_segment = single_segments[k+1]

        expected_length = spacing_between_plants

        if len(segment.items) > 0 and len(next_segment.items) > 0:
            # Plants have been found.
            plant1 = segment.items[0]
            plant2 = next_segment.items[0]
            actual_length = position_difference(plant1.position, plant2.position)
        else:
            # Plants not found yet so just compare codes.
            actual_length = segment.length
        
        length_difference = actual_length - expected_length
        
        # how long segment can be without being flagged
        max_length = spacing_between_plants * 1.75
        
        if segment.end_code.type == 'RowCode':
            continue # length won't be valid
        
        if actual_length > max_length:
            print "\nSingle segment {} to {} is {} feet too long.".format(segment.start_code.name, segment.end_code.name, length_difference * 100 / 30)
            print "{} to {}.".format(segment.start_code.parent_image_filename, segment.end_code.parent_image_filename)
            num_too_long += 1
            
        if actual_length < 0.06:
            print "WARNING - segment {} to {} is way too short".format(segment.start_code.name, segment.end_code.name)
    
    print "\n------Single Segment Length Report------"
    print "Found {} single codes with close expected lengths".format(num_good_lengths)
    print "and {} that were too long".format(num_too_long)
    print "\n"
示例#6
0
 def write_out_missed_codes(self, found_codes, missed_code_filename, out_directory):
     
     missing_codes = []
     for possibly_missed_code in self.possibly_missed_codes:
         was_actually_found = False
         for found_code in found_codes:
             pos_diff = position_difference(possibly_missed_code.position, found_code.position)
             if pos_diff < 0.12:
                 was_actually_found = True
                 break
         if not was_actually_found:
             missing_codes.append(possibly_missed_code)
     
     missed_code_filepath = os.path.join(out_directory, missed_code_filename)
     missed_code_file = open(missed_code_filepath, 'wb')
     missed_code_csv_writer = csv.writer(missed_code_file)
     
     # Create subdirectory to store extracted images in.
     extracted_img_out_directory = os.path.join(out_directory, 'extracted_images/')
     if not os.path.exists(extracted_img_out_directory):
         os.makedirs(extracted_img_out_directory)
     
     for k, missed_code in enumerate(missing_codes):
         
         parent_img = cv2.imread(missed_code.parent_filepath, cv2.CV_LOAD_IMAGE_COLOR)
 
         if parent_img is None:
             print 'Cannot open image: {}'.format(missed_code.parent_filepath)
             continue
         
         extracted_img = extract_square_image(parent_img, missed_code.rect, 60, rotated=True)
         
         extracted_img_filename = '{}_{}'.format(k, postfix_filename(missed_code.parent_filename, '_missed'))
         extracted_img_filepath = os.path.join(extracted_img_out_directory, extracted_img_filename)
         
         cv2.imwrite(extracted_img_filepath, extracted_img)
         
         x, y = rectangle_center(missed_code.rect)
         missed_code_csv_writer.writerow(['add_imaged_code', k, missed_code.parent_filename, int(x), int(y)])
示例#7
0
 items = sorted(items, key=lambda item: item.number_within_field)
 
 plant_spacings = []
 if plant_spacing > 0:
     # Run spacing verification on single plants to double check no codes were missed.
     all_segments = all_segments_from_rows(rows)
     single_segments = [segment for segment in all_segments if segment.start_code.type == 'SingleCode']
     warn_about_missing_single_code_lengths(single_segments, plant_spacing)
 
     # Run spacing verification on regular plants.
     last_plant = None
     for item in items:
         if item.type not in ['Plant', 'CreatedPlant']:
             continue
         if last_plant and last_plant.row == item.row:
             spacing = position_difference(last_plant.position, item.position)
             if spacing > plant_spacing * 1.5:
                 print "{} between {} and {}".format(spacing, last_plant.number_within_field, item.number_within_field)
             plant_spacings.append(spacing)
         last_plant = item
 
 # generate a sub-directory in specified output directory to house all output files.
 out_directory = os.path.join(out_directory, time.strftime('results-%Y%m%d-%H%M%S/'))
 
 if not os.path.exists(out_directory):
     os.makedirs(out_directory)
     
 if survey_filepath != 'none':
     if not os.path.exists(survey_filepath):
         print "Survey file doesn't exist {}".format(survey_filepath)
         sys.exit(ExitReason.bad_arguments)
    if len(geo_images) == 0 or len(all_codes) == 0:
        print "Couldn't load any geo images or codes from input directory {}".format(input_directory)
        sys.exit(ExitReason.no_geo_images)

    # Merge items so they're unique.  One code references other instances of that same code.
    merged_codes = merge_items(all_codes, max_distance=500)

    print '{} unique codes.'.format(len(merged_codes))

    # Sanity check that multiple references of the same code are all close to each other.
    largest_separation = 0
    sum_separation = 0
    sum_separation_count = 0
    for code in merged_codes:
        for code_ref in code.all_refs:
            diff = position_difference(code.position, code_ref.position)
            sum_separation += diff
            sum_separation_count += 1
            if diff > largest_separation:
                largest_separation = diff
                
    average_separation = 0
    if sum_separation_count > 0:
        average_separation = sum_separation / sum_separation_count
                
    print "From average position largest separation is {} and average is {} meters".format(largest_separation, average_separation)

    if not os.path.exists(out_directory):
        os.makedirs(out_directory)

    # Write everything out to CSV file.