Created
May 4, 2019 04:03
-
-
Save dzil123/3afdad8d12a02b7bb1c334b22d0e21fc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cv2 | |
import numpy | |
import math | |
from enum import Enum | |
class GripPipeline: | |
""" | |
An OpenCV pipeline generated by GRIP. | |
""" | |
def __init__(self): | |
"""initializes all values to presets or None if need to be set | |
""" | |
self.__blur_type = BlurType.Box_Blur | |
self.__blur_radius = 4.504504504504505 | |
self.blur_output = None | |
self.__hsl_threshold_input = self.blur_output | |
self.__hsl_threshold_hue = [74.46043165467626, 88.31918505942276] | |
self.__hsl_threshold_saturation = [18.195477451822065, 66.6509592463525] | |
self.__hsl_threshold_luminance = [64.20863309352518, 155.4244482173175] | |
self.hsl_threshold_output = None | |
self.__cv_erode_src = self.hsl_threshold_output | |
self.__cv_erode_kernel = None | |
self.__cv_erode_anchor = (-1, -1) | |
self.__cv_erode_iterations = 7.0 | |
self.__cv_erode_bordertype = cv2.BORDER_CONSTANT | |
self.__cv_erode_bordervalue = (-1) | |
self.cv_erode_output = None | |
self.__cv_dilate_src = self.cv_erode_output | |
self.__cv_dilate_kernel = None | |
self.__cv_dilate_anchor = (-1, -1) | |
self.__cv_dilate_iterations = 16.0 | |
self.__cv_dilate_bordertype = cv2.BORDER_CONSTANT | |
self.__cv_dilate_bordervalue = (-1) | |
self.cv_dilate_output = None | |
self.__find_contours_input = self.cv_dilate_output | |
self.__find_contours_external_only = False | |
self.find_contours_output = None | |
self.__convex_hulls_contours = self.find_contours_output | |
self.convex_hulls_output = None | |
self.__filter_contours_contours = self.convex_hulls_output | |
self.__filter_contours_min_area = 0 | |
self.__filter_contours_min_perimeter = 0 | |
self.__filter_contours_min_width = 0 | |
self.__filter_contours_max_width = 1000 | |
self.__filter_contours_min_height = 0 | |
self.__filter_contours_max_height = 1000 | |
self.__filter_contours_solidity = [0, 100] | |
self.__filter_contours_max_vertices = 1000000 | |
self.__filter_contours_min_vertices = 0 | |
self.__filter_contours_min_ratio = 0 | |
self.__filter_contours_max_ratio = 1000 | |
self.filter_contours_output = None | |
def process(self, source0): | |
""" | |
Runs the pipeline and sets all outputs to new values. | |
""" | |
# Step Blur0: | |
self.__blur_input = source0 | |
(self.blur_output) = self.__blur(self.__blur_input, self.__blur_type, self.__blur_radius) | |
# Step HSL_Threshold0: | |
self.__hsl_threshold_input = self.blur_output | |
(self.hsl_threshold_output) = self.__hsl_threshold(self.__hsl_threshold_input, self.__hsl_threshold_hue, self.__hsl_threshold_saturation, self.__hsl_threshold_luminance) | |
# Step CV_erode0: | |
self.__cv_erode_src = self.hsl_threshold_output | |
(self.cv_erode_output) = self.__cv_erode(self.__cv_erode_src, self.__cv_erode_kernel, self.__cv_erode_anchor, self.__cv_erode_iterations, self.__cv_erode_bordertype, self.__cv_erode_bordervalue) | |
# Step CV_dilate0: | |
self.__cv_dilate_src = self.cv_erode_output | |
(self.cv_dilate_output) = self.__cv_dilate(self.__cv_dilate_src, self.__cv_dilate_kernel, self.__cv_dilate_anchor, self.__cv_dilate_iterations, self.__cv_dilate_bordertype, self.__cv_dilate_bordervalue) | |
# Step Find_Contours0: | |
self.__find_contours_input = self.cv_dilate_output | |
(self.find_contours_output) = self.__find_contours(self.__find_contours_input, self.__find_contours_external_only) | |
# Step Convex_Hulls0: | |
self.__convex_hulls_contours = self.find_contours_output | |
(self.convex_hulls_output) = self.__convex_hulls(self.__convex_hulls_contours) | |
# Step Filter_Contours0: | |
self.__filter_contours_contours = self.convex_hulls_output | |
(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) | |
@staticmethod | |
def __blur(src, type, radius): | |
"""Softens an image using one of several filters. | |
Args: | |
src: The source mat (numpy.ndarray). | |
type: The blurType to perform represented as an int. | |
radius: The radius for the blur as a float. | |
Returns: | |
A numpy.ndarray that has been blurred. | |
""" | |
if(type is BlurType.Box_Blur): | |
ksize = int(2 * round(radius) + 1) | |
return cv2.blur(src, (ksize, ksize)) | |
elif(type is BlurType.Gaussian_Blur): | |
ksize = int(6 * round(radius) + 1) | |
return cv2.GaussianBlur(src, (ksize, ksize), round(radius)) | |
elif(type is BlurType.Median_Filter): | |
ksize = int(2 * round(radius) + 1) | |
return cv2.medianBlur(src, ksize) | |
else: | |
return cv2.bilateralFilter(src, -1, round(radius), round(radius)) | |
@staticmethod | |
def __hsl_threshold(input, hue, sat, lum): | |
"""Segment an image based on hue, saturation, and luminance ranges. | |
Args: | |
input: A BGR numpy.ndarray. | |
hue: A list of two numbers the are the min and max hue. | |
sat: A list of two numbers the are the min and max saturation. | |
lum: A list of two numbers the are the min and max luminance. | |
Returns: | |
A black and white numpy.ndarray. | |
""" | |
out = cv2.cvtColor(input, cv2.COLOR_BGR2HLS) | |
return cv2.inRange(out, (hue[0], lum[0], sat[0]), (hue[1], lum[1], sat[1])) | |
@staticmethod | |
def __cv_erode(src, kernel, anchor, iterations, border_type, border_value): | |
"""Expands area of lower value in an image. | |
Args: | |
src: A numpy.ndarray. | |
kernel: The kernel for erosion. A numpy.ndarray. | |
iterations: the number of times to erode. | |
border_type: Opencv enum that represents a border type. | |
border_value: value to be used for a constant border. | |
Returns: | |
A numpy.ndarray after erosion. | |
""" | |
return cv2.erode(src, kernel, anchor, iterations = (int) (iterations +0.5), | |
borderType = border_type, borderValue = border_value) | |
@staticmethod | |
def __cv_dilate(src, kernel, anchor, iterations, border_type, border_value): | |
"""Expands area of higher value in an image. | |
Args: | |
src: A numpy.ndarray. | |
kernel: The kernel for dilation. A numpy.ndarray. | |
iterations: the number of times to dilate. | |
border_type: Opencv enum that represents a border type. | |
border_value: value to be used for a constant border. | |
Returns: | |
A numpy.ndarray after dilation. | |
""" | |
return cv2.dilate(src, kernel, anchor, iterations = (int) (iterations +0.5), | |
borderType = border_type, borderValue = border_value) | |
@staticmethod | |
def __find_contours(input, external_only): | |
"""Sets the values of pixels in a binary image to their distance to the nearest black pixel. | |
Args: | |
input: A numpy.ndarray. | |
external_only: A boolean. If true only external contours are found. | |
Return: | |
A list of numpy.ndarray where each one represents a contour. | |
""" | |
if(external_only): | |
mode = cv2.RETR_EXTERNAL | |
else: | |
mode = cv2.RETR_LIST | |
method = cv2.CHAIN_APPROX_SIMPLE | |
im2, contours, hierarchy =cv2.findContours(input, mode=mode, method=method) | |
return contours | |
@staticmethod | |
def __convex_hulls(input_contours): | |
"""Computes the convex hulls of contours. | |
Args: | |
input_contours: A list of numpy.ndarray that each represent a contour. | |
Returns: | |
A list of numpy.ndarray that each represent a contour. | |
""" | |
output = [] | |
for contour in input_contours: | |
output.append(cv2.convexHull(contour)) | |
return output | |
@staticmethod | |
def __filter_contours(input_contours, min_area, min_perimeter, min_width, max_width, | |
min_height, max_height, solidity, max_vertex_count, min_vertex_count, | |
min_ratio, max_ratio): | |
"""Filters out contours that do not meet certain criteria. | |
Args: | |
input_contours: Contours as a list of numpy.ndarray. | |
min_area: The minimum area of a contour that will be kept. | |
min_perimeter: The minimum perimeter of a contour that will be kept. | |
min_width: Minimum width of a contour. | |
max_width: MaxWidth maximum width. | |
min_height: Minimum height. | |
max_height: Maximimum height. | |
solidity: The minimum and maximum solidity of a contour. | |
min_vertex_count: Minimum vertex Count of the contours. | |
max_vertex_count: Maximum vertex Count. | |
min_ratio: Minimum ratio of width to height. | |
max_ratio: Maximum ratio of width to height. | |
Returns: | |
Contours as a list of numpy.ndarray. | |
""" | |
output = [] | |
for contour in input_contours: | |
x,y,w,h = cv2.boundingRect(contour) | |
if (w < min_width or w > max_width): | |
continue | |
if (h < min_height or h > max_height): | |
continue | |
area = cv2.contourArea(contour) | |
if (area < min_area): | |
continue | |
if (cv2.arcLength(contour, True) < min_perimeter): | |
continue | |
hull = cv2.convexHull(contour) | |
solid = 100 * area / cv2.contourArea(hull) | |
if (solid < solidity[0] or solid > solidity[1]): | |
continue | |
if (len(contour) < min_vertex_count or len(contour) > max_vertex_count): | |
continue | |
ratio = (float)(w) / h | |
if (ratio < min_ratio or ratio > max_ratio): | |
continue | |
output.append(contour) | |
return output | |
BlurType = Enum('BlurType', 'Box_Blur Gaussian_Blur Median_Filter Bilateral_Filter') | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment