Esempio n. 1
0
    def locate(self, geo_image, image, marked_image):
        '''Find QR codes in image and decode them.  Return list of FieldItems representing valid QR codes.''' 
        
        # Threshold grayscaled image to make white QR codes stands out.
        #gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        #_, mask = cv2.threshold(gray_image, 100, 255, 0)
        
        hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
        lower_white = np.array([0, 0, 160], np.uint8)
        upper_white = np.array([179, 65, 255], np.uint8)
        mask = cv2.inRange(hsv_image, lower_white, upper_white)
        
        # Find outer contours (edges) and 'approximate' them to reduce the number of points along nearly straight segments.
        contours, hierarchy = cv2.findContours(mask.copy(), cv2.cv.CV_RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        #contours = [cv2.approxPolyDP(contour, .1, True) for contour in contours]
        
        # Create bounding box for each contour.
        bounding_rectangles = [cv2.minAreaRect(contour) for contour in contours]

        # Remove any rectangles that couldn't be a QR item based off specified side length.
        filtered_rectangles = filter_by_size(bounding_rectangles, geo_image.resolution, self.qr_min_size, self.qr_max_size)
        
        if ImageWriter.level <= ImageWriter.DEBUG:
            # Debug save intermediate images
            thresh_filename = postfix_filename(geo_image.file_name, 'thresh')
            ImageWriter.save_debug(thresh_filename, mask)
        
        # Scan each rectangle with QR reader to remove false positives and also extract data from code.
        qr_items = []
        for rectangle in filtered_rectangles:
            qr_data = self.scan_image_different_trims_and_threshs(image, rectangle, trims=[0, 3, 8, 12])
            scan_successful = len(qr_data) != 0 and len(qr_data[0]) != 0 

            if scan_successful:

                qr_code = create_qr_code(qr_data[0]) 
                
                if qr_code is None:
                    print 'WARNING: Invalid QR data found ' + qr_data[0]
                else:
                    qr_code.bounding_rect = rectangle
                    qr_items.append(qr_code)
                    
            elif self.missed_code_finder is not None:
                # Scan wasn't successful so tag this rectangle for later analysis.
                self.missed_code_finder.add_possibly_missed_code(rectangle, geo_image)
                
            if marked_image is not None:
                # Show success/failure using colored bounding box
                success_color = (0, 255, 0) # green
                if scan_successful and qr_code is not None and qr_code.type == 'RowCode': 
                    success_color = (0, 255, 255) # yellow for row codes
                failure_color = (0, 0, 255) # red
                item_color = success_color if scan_successful else failure_color
                draw_rect(marked_image, rectangle, item_color, thickness=2)
        
        return qr_items
Esempio n. 2
0
    def locate(self, geo_image, image, marked_image):
        '''Find possible plant leaves in image and return list of rotated rectangle instances.''' 

        # Convert Blue-Green-Red color space to HSV
        hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
            
        # Threshold the HSV image to get only green colors that correspond to healthy plants.
        lower_green = np.array([35, 80, 20], np.uint8)
        upper_green = np.array([90, 255, 255], np.uint8)
        plant_mask = cv2.inRange(hsv_image, lower_green, upper_green)
        
        # Now do the same thing for greenish dead plants.
        #lower_dead_green = np.array([10, 35, 60], np.uint8)
        #upper_dead_green = np.array([90, 255, 255], np.uint8)
        #dead_green_plant_mask = cv2.inRange(hsv_image, lower_dead_green, upper_dead_green)
    
        # Now do the same thing for yellowish dead plants.
        #lower_yellow = np.array([10, 50, 125], np.uint8)
        #upper_yellow = np.array([40, 255, 255], np.uint8)
        #dead_yellow_plant_mask = cv2.inRange(hsv_image, lower_yellow, upper_yellow)
        
        filtered_rectangles = []
        for i, mask in enumerate([plant_mask]):
            # Open mask (to remove noise) and then dilate it to connect contours.
            kernel = np.ones((3,3), np.uint8)
            mask_open = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
            mask = cv2.dilate(mask_open, kernel, iterations = 1)
            
            # Find outer contours (edges) and 'approximate' them to reduce the number of points along nearly straight segments.
            contours, hierarchy = cv2.findContours(mask.copy(), cv2.cv.CV_RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

            # Create bounding box for each contour.
            bounding_rectangles = [cv2.minAreaRect(contour) for contour in contours]
            
            if marked_image is not None and ImageWriter.level <= ImageWriter.DEBUG:
                for rectangle in bounding_rectangles:
                    # Show rectangles using bounding box.
                    draw_rect(marked_image, rectangle, (0,0,0), thickness=2)
            
            # Remove any rectangles that couldn't be a plant based off specified size.
            filtered_rectangles.extend(filter_by_size(bounding_rectangles, geo_image.resolution, self.min_leaf_size, self.max_leaf_size, enforce_min_on_w_and_h=False))
            
            if ImageWriter.level <= ImageWriter.DEBUG:
                # Debug save intermediate images
                mask_filename = postfix_filename(geo_image.file_name, 'mask_{}'.format(i))
                ImageWriter.save_debug(mask_filename, mask)
        
        if marked_image is not None:
            for rectangle in filtered_rectangles:
                # Show rectangles using colored bounding box.
                purple = (255, 0, 255)
                draw_rect(marked_image, rectangle, purple, thickness=2)
        
        return filtered_rectangles
Esempio n. 3
0
    def locate(self, geo_image, image, marked_image):
        '''Find possible blue sticks in image and return list of rotated bounding box instances.''' 

        # Convert Blue-Green-Red color space to HSV
        hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
        
        # Create binary mask image where potential sticks are white.
        lower_blue = np.array([90, 31, 16], np.uint8)
        upper_blue = np.array([130, 255, 255], np.uint8)
        mask = cv2.inRange(hsv_image, lower_blue, upper_blue)
        
        # Open mask (to remove noise) and then dilate it to connect contours.
        kernel = np.ones((3,3), np.uint8)
        mask_open = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
        mask = cv2.dilate(mask_open, kernel, iterations = 1)
        
        # Find outer contours (edges)
        contours, hierarchy = cv2.findContours(mask.copy(), cv2.cv.CV_RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

        # Create bounding box for each contour.
        bounding_rectangles = [cv2.minAreaRect(contour) for contour in contours]
        
        if marked_image is not None and ImageWriter.level <= ImageWriter.DEBUG:
            for rectangle in bounding_rectangles:
                # Show rectangles using bounding box.
                draw_rect(marked_image, rectangle, (255,255,255), thickness=1)
        
        # Remove any rectangles that couldn't be a stick part based off specified size.
        filtered_rectangles = filter_by_size(bounding_rectangles, geo_image.resolution, self.min_stick_part_size, self.max_stick_part_size, enforce_min_on_w_and_h=True)
        
        if ImageWriter.level <= ImageWriter.DEBUG:
            # Debug save intermediate images
            mask_filename = postfix_filename(geo_image.file_name, 'blue_thresh')
            ImageWriter.save_debug(mask_filename, mask)
        
        if marked_image is not None:
            for rectangle in filtered_rectangles:
                # Show rectangles using colored bounding box.
                purple = (50, 255, 255)
                draw_rect(marked_image, rectangle, purple, thickness=2)
                
        return filtered_rectangles
Esempio n. 4
0
def debug_draw_plants_in_images_subset(debug_geo_images, possible_plants, actual_plants, image_out_directory):
    
    debug_images = []
    DebugImage = namedtuple('DebugImage', 'image existed')
    for geo_image in debug_geo_images:
        if hasattr(geo_image, 'debug_filepath'):
            path = geo_image.debug_filepath
            already_existed = True
        else:
            path = geo_image.file_path
            already_existed = False
        img = cv2.imread(path, cv2.CV_LOAD_IMAGE_COLOR)
        if img is None:
            print "Could not open image {}".format(path)
            continue
        debug_images.append(DebugImage(img, already_existed))
    for item in possible_plants:
        from random import randint
        item_color = (randint(50, 255), randint(50, 100), randint(50, 255))
        for k, geo_image in enumerate(debug_geo_images):
            for ext_item in [item] + item.get('items',[]):
                image_rect = rect_to_image(ext_item['rect'], geo_image)
                center, size, theta = image_rect
                x, y = center
                if x >= 0 and x < geo_image.width and y >= 0 and y < geo_image.height:
                    draw_rect(debug_images[k].image, image_rect, item_color, thickness=2)
            
    for plant in actual_plants:
        for ref in plant.all_refs:
            if not ref.parent_image_filename:
                continue
            geo_image_filenames = [geo_image.file_name for geo_image in debug_geo_images]
            try:
                debug_img_index = geo_image_filenames.index(ref.parent_image_filename)
            except ValueError:
                continue
            debug_img = debug_images[debug_img_index].image
            if ref.type == 'CreatedPlant':
                draw_rect(debug_img, ref.bounding_rect, (255, 255, 255), thickness=6)
            else:
                draw_rect(debug_img, ref.bounding_rect, (0, 255, 0), thickness=5)
            
    debug_filepaths = [os.path.join(image_out_directory, postfix_filename(geo_image.file_name, 'marked')) for geo_image in debug_geo_images]
    for k, (debug_image, filepath) in enumerate(zip(debug_images, debug_filepaths)):
        if not debug_image.existed:
            output_debug_image = debug_image.image
            # KLM - don't make image smaller or bounding rect coordinates won't be right next time try to draw on image.
            #output_debug_image = cv2.resize(debug_image.image, (0,0), fx=0.25, fy=0.25)
        else:
            output_debug_image = debug_image.image
        cv2.imwrite(filepath, output_debug_image)
        debug_geo_images[k].debug_filepath = filepath