|
| 1 | +import cv2 |
| 2 | +import numpy |
| 3 | +import math |
| 4 | +from enum import Enum |
| 5 | + |
| 6 | +class GripPipeline: |
| 7 | + """ |
| 8 | + An OpenCV pipeline generated by GRIP. |
| 9 | + """ |
| 10 | + |
| 11 | + def __init__(self): |
| 12 | + """initializes all values to presets or None if need to be set |
| 13 | + """ |
| 14 | + |
| 15 | + self.__resize_image_width = 320.0 |
| 16 | + self.__resize_image_height = 240.0 |
| 17 | + self.__resize_image_interpolation = cv2.INTER_CUBIC |
| 18 | + |
| 19 | + self.resize_image_output = None |
| 20 | + |
| 21 | + self.__rgb_threshold_input = self.resize_image_output |
| 22 | + self.__rgb_threshold_red = [91.72661870503596, 255.0] |
| 23 | + self.__rgb_threshold_green = [0.0, 53.684210526315795] |
| 24 | + self.__rgb_threshold_blue = [0.0, 73.16638370118847] |
| 25 | + |
| 26 | + self.rgb_threshold_output = None |
| 27 | + |
| 28 | + self.__find_contours_input = self.rgb_threshold_output |
| 29 | + self.__find_contours_external_only = True |
| 30 | + |
| 31 | + self.find_contours_output = None |
| 32 | + |
| 33 | + self.__filter_contours_contours = self.find_contours_output |
| 34 | + self.__filter_contours_min_area = 20.0 |
| 35 | + self.__filter_contours_min_perimeter = 0 |
| 36 | + self.__filter_contours_min_width = 0 |
| 37 | + self.__filter_contours_max_width = 1000 |
| 38 | + self.__filter_contours_min_height = 0 |
| 39 | + self.__filter_contours_max_height = 1000 |
| 40 | + self.__filter_contours_solidity = [0, 100] |
| 41 | + self.__filter_contours_max_vertices = 1000000 |
| 42 | + self.__filter_contours_min_vertices = 0 |
| 43 | + self.__filter_contours_min_ratio = 0 |
| 44 | + self.__filter_contours_max_ratio = 1000 |
| 45 | + |
| 46 | + self.filter_contours_output = None |
| 47 | + |
| 48 | + |
| 49 | + def process(self, source0): |
| 50 | + """ |
| 51 | + Runs the pipeline and sets all outputs to new values. |
| 52 | + """ |
| 53 | + # Step Resize_Image0: |
| 54 | + self.__resize_image_input = source0 |
| 55 | + (self.resize_image_output) = self.__resize_image(self.__resize_image_input, self.__resize_image_width, self.__resize_image_height, self.__resize_image_interpolation) |
| 56 | + |
| 57 | + # Step RGB_Threshold0: |
| 58 | + self.__rgb_threshold_input = self.resize_image_output |
| 59 | + (self.rgb_threshold_output) = self.__rgb_threshold(self.__rgb_threshold_input, self.__rgb_threshold_red, self.__rgb_threshold_green, self.__rgb_threshold_blue) |
| 60 | + |
| 61 | + # Step Find_Contours0: |
| 62 | + self.__find_contours_input = self.rgb_threshold_output |
| 63 | + (self.find_contours_output) = self.__find_contours(self.__find_contours_input, self.__find_contours_external_only) |
| 64 | + |
| 65 | + # Step Filter_Contours0: |
| 66 | + self.__filter_contours_contours = self.find_contours_output |
| 67 | + (self.filter_contours_output) = self.__filter_contours(self.__filter_contours_contours, self.__filter_contours_min_area, self.__filter_contours_min_perimeter, self.__filter_contours_min_width, self.__filter_contours_max_width, self.__filter_contours_min_height, self.__filter_contours_max_height, self.__filter_contours_solidity, self.__filter_contours_max_vertices, self.__filter_contours_min_vertices, self.__filter_contours_min_ratio, self.__filter_contours_max_ratio) |
| 68 | + |
| 69 | + |
| 70 | + @staticmethod |
| 71 | + def __resize_image(input, width, height, interpolation): |
| 72 | + """Scales and image to an exact size. |
| 73 | + Args: |
| 74 | + input: A numpy.ndarray. |
| 75 | + Width: The desired width in pixels. |
| 76 | + Height: The desired height in pixels. |
| 77 | + interpolation: Opencv enum for the type fo interpolation. |
| 78 | + Returns: |
| 79 | + A numpy.ndarray of the new size. |
| 80 | + """ |
| 81 | + return cv2.resize(input, ((int)(width), (int)(height)), 0, 0, interpolation) |
| 82 | + |
| 83 | + @staticmethod |
| 84 | + def __rgb_threshold(input, red, green, blue): |
| 85 | + """Segment an image based on color ranges. |
| 86 | + Args: |
| 87 | + input: A BGR numpy.ndarray. |
| 88 | + red: A list of two numbers the are the min and max red. |
| 89 | + green: A list of two numbers the are the min and max green. |
| 90 | + blue: A list of two numbers the are the min and max blue. |
| 91 | + Returns: |
| 92 | + A black and white numpy.ndarray. |
| 93 | + """ |
| 94 | + out = cv2.cvtColor(input, cv2.COLOR_BGR2RGB) |
| 95 | + return cv2.inRange(out, (red[0], green[0], blue[0]), (red[1], green[1], blue[1])) |
| 96 | + |
| 97 | + @staticmethod |
| 98 | + def __find_contours(input, external_only): |
| 99 | + """Sets the values of pixels in a binary image to their distance to the nearest black pixel. |
| 100 | + Args: |
| 101 | + input: A numpy.ndarray. |
| 102 | + external_only: A boolean. If true only external contours are found. |
| 103 | + Return: |
| 104 | + A list of numpy.ndarray where each one represents a contour. |
| 105 | + """ |
| 106 | + if(external_only): |
| 107 | + mode = cv2.RETR_EXTERNAL |
| 108 | + else: |
| 109 | + mode = cv2.RETR_LIST |
| 110 | + method = cv2.CHAIN_APPROX_SIMPLE |
| 111 | + im2, contours, hierarchy =cv2.findContours(input, mode=mode, method=method) |
| 112 | + return contours |
| 113 | + |
| 114 | + @staticmethod |
| 115 | + def __filter_contours(input_contours, min_area, min_perimeter, min_width, max_width, |
| 116 | + min_height, max_height, solidity, max_vertex_count, min_vertex_count, |
| 117 | + min_ratio, max_ratio): |
| 118 | + """Filters out contours that do not meet certain criteria. |
| 119 | + Args: |
| 120 | + input_contours: Contours as a list of numpy.ndarray. |
| 121 | + min_area: The minimum area of a contour that will be kept. |
| 122 | + min_perimeter: The minimum perimeter of a contour that will be kept. |
| 123 | + min_width: Minimum width of a contour. |
| 124 | + max_width: MaxWidth maximum width. |
| 125 | + min_height: Minimum height. |
| 126 | + max_height: Maximimum height. |
| 127 | + solidity: The minimum and maximum solidity of a contour. |
| 128 | + min_vertex_count: Minimum vertex Count of the contours. |
| 129 | + max_vertex_count: Maximum vertex Count. |
| 130 | + min_ratio: Minimum ratio of width to height. |
| 131 | + max_ratio: Maximum ratio of width to height. |
| 132 | + Returns: |
| 133 | + Contours as a list of numpy.ndarray. |
| 134 | + """ |
| 135 | + output = [] |
| 136 | + for contour in input_contours: |
| 137 | + x,y,w,h = cv2.boundingRect(contour) |
| 138 | + if (w < min_width or w > max_width): |
| 139 | + continue |
| 140 | + if (h < min_height or h > max_height): |
| 141 | + continue |
| 142 | + area = cv2.contourArea(contour) |
| 143 | + if (area < min_area): |
| 144 | + continue |
| 145 | + if (cv2.arcLength(contour, True) < min_perimeter): |
| 146 | + continue |
| 147 | + hull = cv2.convexHull(contour) |
| 148 | + solid = 100 * area / cv2.contourArea(hull) |
| 149 | + if (solid < solidity[0] or solid > solidity[1]): |
| 150 | + continue |
| 151 | + if (len(contour) < min_vertex_count or len(contour) > max_vertex_count): |
| 152 | + continue |
| 153 | + ratio = (float)(w) / h |
| 154 | + if (ratio < min_ratio or ratio > max_ratio): |
| 155 | + continue |
| 156 | + output.append(contour) |
| 157 | + return output |
| 158 | + |
| 159 | + |
| 160 | + |
0 commit comments