예제 #1
0
def rotated_square_filter(contour_list,
                          min_area_ratio=0.8,
                          min_ratio=0.95,
                          max_ratio=1.05):
    """
    Action: receives a list of contours
    and returns only the ones that are approximately square
    Relation checked is [minimum ratio < (Circle radius / width * height * (square root of 2)) < maximum ratio]
    :param contour_list: List of Contours to filter
    :param max_ratio: maximum ratio between radius and sides of bounding rectangle
    :type max_ratio: float
    :param min_ratio: minimum ratio between radius and sides of bounding rectangle
    :type min_ratio: float
    :param min_area_ratio: minimum ratio between the area of the contours and the bounding shape
    :return: the contour list filtered.
     """
    ratio_list = []
    output_list = []
    if type(contour_list) is not list:
        contour_list = [contour_list]
    for currentContour in contour_list:
        fill_ratio, w, h = Geometry.get_fill_ratio_rotating(currentContour)
        _, enclosing_radius = cv2.minEnclosingCircle(currentContour)
        peri = cv2.arcLength(currentContour, True)
        approx = cv2.approxPolyDP(currentContour, 0.02 * peri, True)
        if fill_ratio > min_area_ratio and len(approx) == 4:
            p1 = root(2, 2) * root(w * h, 2)
            p2 = 2 * enclosing_radius
            radius_ratio = p2 / p1
            if min_ratio < radius_ratio < max_ratio:
                output_list.append(currentContour)
                if radius_ratio > 1:
                    radius_ratio = 1 / radius_ratio
                ratio_list.append(fill_ratio * radius_ratio)
    return output_list, ratio_list
예제 #2
0
def regular_polygon_filter(contour_list,
                           side_amount=6,
                           min_angle_ratio=0.9,
                           min_area_ratio=0.85,
                           min_len_ratio=0.9,
                           approx_coef=0.02):
    """
    Action: A filter that Detects regular polygon of n-sides sides
    :param contour_list: the list of contours to be filtered
    :param side_amount: the amount of sides the wanted polygon has.
    :param min_angle_ratio: the minimum ratio between the each angle and the average angle and the average angle and the
                            target angle of a shape of side_amount
    :param min_area_ratio: The minimum ratio between the contour's area and the target area
    :param min_len_ratio: The minimum ratio between the length of each side and the average length and
                          between the average length.
    :param approx_coef: the coefficient for the function cv2.approxPolyDP.
    :return:
    """
    if side_amount < 3:
        return []
    output = []
    ratio_list = []
    if type(contour_list) is not list:
        contour_list = [contour_list]
    for currentContour in contour_list:
        vertices, lengths, angles = Geometry.get_lengths_and_angles(
            currentContour, approx_coef)
        if len(vertices) == side_amount:
            target_angle = Geometry.n_polygon_angle(side_amount)
            average_length = round(sum(lengths) / float(len(lengths)), 3)
            average_angle = round(sum(angles) / float(len(lengths)), 3)
            invalid_value = False
            for length in lengths:
                if 1 - (root((length - average_length)**2, 2) /
                        average_length) < min_len_ratio:
                    invalid_value = True
                    break
            if not invalid_value:
                for angle in angles:
                    if 1 - (root((angle - average_angle)**2, 2) /
                            average_angle) < min_angle_ratio:
                        invalid_value = True
                        break
                if not invalid_value:
                    if 1 - (root((target_angle - average_angle)**2, 2) /
                            target_angle) < min_angle_ratio:
                        invalid_value = True
                    if not invalid_value:
                        ratio = cv2.contourArea(
                            currentContour) / Geometry.n_polygon_area(
                                average_length, side_amount)
                        if min_area_ratio <= ratio <= 1 / min_area_ratio:
                            ratio_list.append(ratio)
                            output.append(currentContour)
    return output, ratio_list
예제 #3
0
파일: Geometry.py 프로젝트: esh4/Ovl-Python
def distance_between_points(p1, p2):
    """
    Action: Calculates the Distance between 2 points.
    :param p1: tuple of x and y value of point 1
    :param p2: tuple of x and y value of point 2
    :return: Float value of the distance between the 2 points
    :rtype: float
    """
    return root((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2, 2)
예제 #4
0
파일: Geometry.py 프로젝트: esh4/Ovl-Python
def circle_rating(contour, area_factor=0.9, radius_factor=0.8):
    """
    Action: returns a rating of how close is the circle to being a circle
    :param contour: the contour that its rating is calculated
    :param area_factor: the factor (p-value) that separates an area ratio that is a circle and one that isn't
    :param radius_factor: the factor (p-value) that separates an radius ratio that is a circle and one that isn't
    :return:
    """
    fill_ratio, radius = get_fill_ratio_circle(contour)
    _, _, w, h = cv2.boundingRect(contour)
    radius_ratio = root(((radius * 2)**2) / float(w) * h, 2)
    rating = (radius_ratio * radius_factor) * (fill_ratio * area_factor)
    return rating
예제 #5
0
def circle_filter(contour_list, min_area_ratio=0.80, min_len_ratio=0.9):
    """
    Action: filters out contour which are not approximately circle.
    :param contour_list: list of arrays (numpy uint8 ndarrays (contours) to be filtered
    :param min_area_ratio: minimum ratio between the area of the enclosing
                      circle and the contour (contour /enclosing circle)
    :param min_len_ratio: minimum ratio between the radius of the enclosing circle and the enclosing rectangle.
    :return: the list of contours that fit the criteria
    """
    output = []
    ratio_list = []
    if type(contour_list) is not list:
        contour_list = [contour_list]
    for currentContour in contour_list:
        fill_ratio, radius = Geometry.get_fill_ratio_circle(currentContour)
        _, _, w, h = cv2.boundingRect(currentContour)
        radius_ratio = ((2 * radius)**2) / float(w) * h
        if min_len_ratio <= root(radius_ratio, 2):
            if min_area_ratio <= fill_ratio:
                output.append(currentContour)
                ratio_list.append((fill_ratio, radius_ratio))
    return output, ratio_list