Advertisement
dan-masek

https://stackoverflow.com/questions/68902521/how-many-points-of-intersections-are-possible-rectangle

Aug 24th, 2021
1,813
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.76 KB | None | 0 0
  1. import itertools
  2. import math
  3.  
  4. import numpy as np
  5. import cv2
  6.  
  7. # ============================================================================
  8.  
  9. intersections = [
  10.     (406, 254), (123, 304), (120, 304), (405, 254)
  11.     , (410, 253), (124, 303), (222, 286), (262, 56)
  12.     , (381, 220), (278, 78), (260, 54), (408, 257)
  13.     , (21, 86), (57, 162), (22, 87), (81, 215)
  14.     , (122, 302), (22, 85), (266, 55), (261, 56)
  15.     , (125, 73), (18, 86), (23, 87), (68, 189)
  16.     , (119, 303), (331, 148), (264, 53), (407, 257)
  17.     , (260, 54), (412, 256), (19, 88), (124, 302)
  18. ]
  19.  
  20. # NB: Overriding the original point array with a set
  21. # of simpler lines for testing and demonstration...
  22. intersections = [(10,10), (160,10), (80,10), (270,10), (81,110), (160,111)]
  23.  
  24. # ============================================================================
  25.  
  26. def draw_intersections(intersections):
  27.     output = np.zeros((320,480,3), np.uint8)
  28.  
  29.     for intersection in intersections:
  30.         cv2.drawMarker(output, intersection, (191,255,191))
  31.  
  32.     return output
  33.  
  34. # ============================================================================
  35.  
  36. def distance(a, b):
  37.     dx, dy = (b[0] - a[0]), (b[1] - a[1])
  38.     return math.sqrt(dx * dx + dy * dy)
  39.    
  40. def is_triangle_clockwise(pA, pB, pC):
  41.     # https://stackoverflow.com/a/1165943/3962537
  42.     total = ((pB[0] - pA[0]) * (pB[1] + pA[1])
  43.         + (pC[0] - pB[0]) * (pC[1] + pB[1])
  44.         + (pA[0] - pC[0]) * (pA[1] + pC[1]))
  45.     return total >= 0
  46.  
  47. def get_inner_angle(pC, pA, pB):
  48.     vAB = [(pA[0] - pB[0]), (pA[1] - pB[1])]
  49.     vAC = [(pA[0] - pC[0]), (pA[1] - pC[1])]
  50.     dot_product = (vAB[0] * vAC[0]) + (vAB[1] * vAC[1])
  51.     dAB = distance(pA, pB)
  52.     dAC = distance(pA, pC)
  53.     cos_angle = np.clip(dot_product / dAB / dAC, -1.0, 1.0)
  54.     angle = math.acos(cos_angle)
  55.     angle_deg = math.degrees(angle)
  56.     return angle_deg
  57.  
  58. # ============================================================================
  59.  
  60. def detect_rectangle(points):
  61.     MINIMUM_DISTANCE = 20
  62.     MAX_ANGLE_SUM_ERROR = 1.0
  63.     MAX_CORNER_ANGLE_ERROR = 10.0
  64.  
  65.     pA = points[0] # Select anchror point
  66.  
  67.     distances = [
  68.         distance(pA, points[1])
  69.         , distance(pA, points[2])
  70.         , distance(pA, points[3])
  71.     ]
  72.     order = np.argsort(distances)
  73.     if distances[order[0]] < MINIMUM_DISTANCE:
  74.         return None
  75.        
  76.     pC = points[order[2]+1] # Diagonal, most distant point
  77.     pB, pD = points[order[0]+1], points[order[1]+1] # The other two corners
  78.    
  79.     # Make sure the points are in clockwise order (assuming it's a rectangle)...
  80.     if not is_triangle_clockwise(pA, pB, pC):
  81.         pB, pD = pD, pB
  82.        
  83.     angleA = get_inner_angle(pD, pA, pB)
  84.     angleB = get_inner_angle(pA, pB, pC)
  85.     angleC = get_inner_angle(pB, pC, pD)
  86.     angleD = get_inner_angle(pC, pD, pA)
  87.     angle_sum = angleA + angleB + angleC + angleD
  88.     if math.fabs(360.0 - angle_sum) > MAX_ANGLE_SUM_ERROR:
  89.         return None
  90.        
  91.     corner_angle_errors = np.abs(90.0 - np.array([angleA, angleB, angleC, angleD]))
  92.     if np.max(corner_angle_errors) > MAX_CORNER_ANGLE_ERROR:
  93.         return None
  94.        
  95.     return ([pA, pB, pC, pD], [angleA, angleB, angleC, angleD], angle_sum)
  96.  
  97. # ============================================================================
  98.  
  99. # Eliminate duplicate points
  100. intersections = list(set(intersections))
  101.  
  102. # Process all combinations of 4 intersection points
  103. for points in itertools.combinations(intersections, 4):
  104.     result = detect_rectangle(points)
  105.     if result:
  106.         print(result)
  107.         polygon = np.array(result[0], np.int32).reshape((-1,1,2))
  108.         output = draw_intersections(intersections)
  109.         cv2.polylines(output, [polygon], True, (0,255,255))
  110.         cv2.imshow("", output)
  111.         cv2.waitKey()
  112.    
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement