Files
@ 7cb01d4080c9
Branch filter:
Location: OneEye/src/analyzer/corners.py - annotation
7cb01d4080c9
3.9 KiB
text/x-python
a hinted neural network (failed)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | a601f040413e a601f040413e a601f040413e a601f040413e a601f040413e 3798475f45c1 3798475f45c1 3798475f45c1 002858d37174 c96bd773ec28 f125391c937d f125391c937d 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 a601f040413e a601f040413e 3798475f45c1 a601f040413e 3798475f45c1 3798475f45c1 3798475f45c1 a601f040413e 3798475f45c1 3798475f45c1 3798475f45c1 a601f040413e f125391c937d 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 f125391c937d 28ca21b89e43 28ca21b89e43 28ca21b89e43 28ca21b89e43 28ca21b89e43 3798475f45c1 a601f040413e 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 28ca21b89e43 3798475f45c1 3798475f45c1 3798475f45c1 28ca21b89e43 3798475f45c1 3798475f45c1 a601f040413e 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 a601f040413e 3798475f45c1 a601f040413e a601f040413e 3798475f45c1 3798475f45c1 3798475f45c1 a601f040413e 3798475f45c1 f125391c937d 28ca21b89e43 3798475f45c1 3798475f45c1 a601f040413e a601f040413e a601f040413e a601f040413e a601f040413e a601f040413e a601f040413e 3798475f45c1 f125391c937d f125391c937d f125391c937d 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 3798475f45c1 | import logging
from .epoint import EPoint
log=logging.getLogger(__name__)
class Corners:
def __init__(self,cornerList=[]):
self._corners=list(cornerList)
self._is_canon=False
self._canonizeOrder()
## Adds a new corner if there are less than four, replaces the closest otherwise.
def add(self,x,y):
a=EPoint(x,y)
# for i,c in enumerate(self.corners): # move an improperly placed point
# if a.dist(c)<20:
# self.corners[i]=a
# return
if len(self._corners)<4: # add a new corner
self._corners.append(a)
if len(self._corners)<4:
return
index,minDist=0,float('inf') # replace the corner closest to the clicked point
for i,c in enumerate(self._corners):
if a.dist(c)<minDist:
index,minDist=i,a.dist(c)
self._corners[index]=a
self._canonizeOrder()
## Order the corners (0,1,2,3) so they make a quadrangle with vertices KLMN in counter-clockwise order, K being in the upper left.
#
# For four points ABCD, there are 24 possible permutations corresponding to the desired KLMN.
# When we relax the condition of K being the upper left one, we get six groups of four equivalent permutations. KLMN ~ LMNK ~ MNKL ~ NKLM.
#
# We determine which of the points' triplets are oriented clockwise and which counter-clockwise (minus/plus in the table below)
# and swap them so that all triangles turn counter-clockwise.
#
# xxxx -> KLMN | ABC | ABD | ACD | BCD | index | swap
# ------------ | :-: | :-: | :-: | :-: | ----: | ----
# A BCD | + | + | + | + | 15 | 0
# A BDC | + | + | - | - | 12 | CD
# A CBD | - | + | + | - | 6 | BC
# A CDB | - | - | + | + | 3 | AB
# A DBC | + | - | - | + | 9 | AD
# A DCB | - | - | - | - | 0 | BD
#
# For every non-degenerate quadrangle, there must be 1-3 edges going right-left (from a higher to a lower x coordinate).
# From these pick the one with the lowest slope (dy/dx) and declare its ending point the upper left corner. For the same slope pick the one further left.
#
# @return True for a convex quadrangle, False for concave and degenerate cases.
def _canonizeOrder(self):
def false():
self._is_canon=False
return False
if len(self._corners)!=4: return false()
a,b,c,d=self._corners
abc=doubleTriangleArea(a,b,c)
abd=doubleTriangleArea(a,b,d)
acd=doubleTriangleArea(a,c,d)
bcd=doubleTriangleArea(b,c,d)
if any(x==0 for x in (abc,abd,acd,bcd)): return false() # collinear degenerate
swaps=[(1,3),(0,1),(1,2),(0,3),(2,3),(0,0)]
index=(8 if abc>0 else 0)|(4 if abd>0 else 0)|(2 if acd>0 else 0)|(1 if bcd>0 else 0)
if index%3!=0: return false() # concave degenerate
swap=swaps[index//3]
self._corners[swap[0]], self._corners[swap[1]] = self._corners[swap[1]], self._corners[swap[0]] # counter-clockwise order
kIndex=None
lowestSlope=float("inf")
for i,corner in enumerate(self._corners): # find the NK edge: going right-left with the lowest slope, secondarily the one going down
ii=(i+1)%4
slope=abs(getSlope(corner, self._corners[ii]))
if corner.x>self._corners[ii].x and (slope < lowestSlope or (slope == lowestSlope and corner.y < self._corners[ii].y)):
kIndex=ii
lowestSlope=slope
self._corners= self._corners[kIndex:] + self._corners[:kIndex] # rotate the upper left corner to the first place
self._is_canon=True # success
return True
def scale(self,scale):
self._corners=[c * scale for c in self._corners]
def __iter__(self):
return iter(self._corners)
def __len__(self):
return len(self._corners)
def is_canon(self):
return self._is_canon
## Computes twice the area of the triangle formed by points a,b,c.
#
# @return positive value for points oriented counter-clockwise, negative for clockwise, zero for degenerate cases.
def doubleTriangleArea(a,b,c):
return (a.x-b.x)*(c.y-a.y)-(c.x-a.x)*(a.y-b.y)
def getSlope(a,b):
if(b.x==a.x): return float("inf")
return (b.y-a.y)/(b.x-a.x)
|