File size: 4,205 Bytes
7eebac0
42a8761
 
 
 
9f95f84
97f0d9d
9f95f84
 
 
9c14df6
9f95f84
 
 
324f00f
9f95f84
 
 
870f731
15e568c
9f95f84
 
 
bbe7475
9f95f84
 
bbe7475
 
42a8761
 
 
 
 
 
 
 
 
 
 
 
8f0ccb2
 
 
 
2fe6395
07938c8
b94470a
8f0ccb2
 
 
 
54b68aa
8f0ccb2
 
 
 
 
 
 
 
9897471
8fd94b4
2516acd
9897471
8f0ccb2
 
4aa12df
8f0ccb2
 
 
4aa12df
 
bcbdd06
b94470a
 
 
 
 
cc41846
 
 
 
 
e7a8bfc
42a8761
09c4a22
42a8761
7766475
dc75d3f
e7a8bfc
 
 
7766475
a9852e7
85700c7
42a8761
 
 
b94470a
e1b1c67
dc75d3f
82e1477
 
e1b1c67
 
82e1477
 
 
b94470a
 
2f5e44a
e7a8bfc
b94470a
dc75d3f
42a8761
9897471
42a8761
e7a8bfc
42a8761
e7a8bfc
42a8761
 
931bb21
 
 
 
42a8761
3ea24a6
 
 
e7a8bfc
3ea24a6
931bb21
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import gradio as gr
import cv2
import numpy as np

def preprocess(img):
    # Convert to grayscale
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    cv2.imwrite("1_gray.png", img_gray)

    # Blur the image
    img_blur = cv2.GaussianBlur(img_gray, (3, 3), 1)
    cv2.imwrite("2_blur.png", img_blur)

    # Detect edges with Canny
    img_canny = cv2.Canny(img_blur, 100, 200)
    cv2.imwrite("3_canny.png", img_canny)

    # Dilate the edges
    kernel = np.ones((3, 3))
    img_dilate = cv2.dilate(img_canny, kernel, iterations=1)
    cv2.imwrite("4_dilate.png", img_dilate)

    # Erode the dilated edges
    img_erode = cv2.erode(img_dilate, kernel, iterations=0)
    cv2.imwrite("5_erode.png", img_erode)

    
    return img_erode

def find_tip(points, convex_hull):
    length = len(points)
    indices = np.setdiff1d(range(length), convex_hull)

    for i in range(2):
        j = indices[i] + 2
        if j > length - 1:
            j = length - j
        if np.all(points[j] == points[indices[i - 1] - 2]):
            return tuple(points[j])

def get_length(p1, p2):
    line_length = ((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) ** 0.5
    return line_length

def get_clockwise_angle(tip, tail):
    return (np.degrees(np.arctan2(tip[1] - tail[1], tip[0] - tail[0]))*-1)
    
def get_max_distance_point(cnt, tip):
    max_distance = 0
    max_point = None

    for [x, y] in cnt:
        distance = get_length((x, y), tip)

        if distance > max_distance:
            max_distance = distance
            max_point = (x, y)

    return max_point

def find_tail(points, tip):
    tip = np.array(tip, dtype=np.float32)
    points = np.array(points, dtype=np.int32)

    # Find the tail point based on maximum distance
    tail_point = get_max_distance_point(points, tip)

    # Ensure that the tail point is sufficiently different from the tip
    if np.linalg.norm(np.array(tail_point) - np.array(tip)) > 5:
        return tail_point

    return None

def draw_arrow(img_result, tip, tail, length, angle):
    # Draw arrow on the blank image with inverted tip and tail
    cv2.arrowedLine(img_result, tuple(tail), tuple(tip), (0, 255, 0), 3)

    # Add length and angle as text next to the tip point
    text_length = f"Length: {length:.2f}"
    text_angle = f"Angle: {angle:.2f}"
    
    cv2.putText(img_result, text_length, (tip[0] + 10, tip[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)
    cv2.putText(img_result, text_angle, (tip[0] + 10, tip[1] - 30), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)
    
def infer(image_in):
    img = cv2.imread(image_in)

    contours, hierarchy = cv2.findContours(preprocess(img), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # Create a blank image to accumulate arrows
    img_result = np.zeros_like(img)

    for cnt in contours:
        peri = cv2.arcLength(cnt, True)
        approx = cv2.approxPolyDP(cnt, 0.025 * peri, True)
        hull = cv2.convexHull(approx, returnPoints=False)
        sides = len(hull)

        if 8 >= sides > 3 and sides + 2 == len(approx):
            arrow_tip = find_tip(approx[:,0,:], hull.squeeze())
            
            
            if arrow_tip :
                cv2.drawContours(img, [cnt], -1, (0, 255, 0), 3)
                cv2.circle(img, arrow_tip, 3, (0, 0, 255), cv2.FILLED)
                arrow_tail = find_tail(approx[:,0,:], arrow_tip)
                if arrow_tail :
                    cv2.circle(img, arrow_tail, 3, (255, 0, 0), cv2.FILLED)
                    # Calculate length and angle
                    arrow_length = get_length(arrow_tip, arrow_tail)
                    arrow_angle = get_clockwise_angle(arrow_tip, arrow_tail)
                    # Draw arrow on the same blank image
                    draw_arrow(img_result, arrow_tip, arrow_tail, arrow_length, arrow_angle)



    cv2.imwrite("Image_result.png", img)
    cv2.imwrite("Arrows_on_same_blank.png", img_result)

    return "Image_result.png", "Arrows_on_same_blank.png"

gr.Interface(
    fn=infer,
    inputs=gr.Image(
        sources=["upload"],
        type="filepath"
    ),
    outputs=[
        gr.Image(),
        gr.Image(),
        
    ]
).launch()