-
Notifications
You must be signed in to change notification settings - Fork 0
/
process_contour.py
186 lines (120 loc) · 6.93 KB
/
process_contour.py
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
import os
import cv2
from find_dayJSON_match_for_contour import find_dayJSON_match_for_contour
from cv_utils import extract_segment
from json_utils import append_to_json_list
def process_contour(i, contour, logger, json_data, matching, date_string, nodules_dir, right_image, left_image, max_id):
# Extract date and id components from max_id string
logger.info(f"@process_contour: max_id: {max_id}")
# logger.info("Contour:")
# logger.info(f"{contour}\n"
# Find the moments of the contour
# Moments are used to find the centroid of the contour, a moment is a weighted average of the image pixels
M = cv2.moments(contour)
logger.info(f"Moments: {M}")
# If the area of the contour is 0, skip it
if M["m00"] == 0:
logger.info(f"Skipping contour#{i + 1} because area is 0.\n\n")
return None
# Find the centroid of the contour
cX, cY = int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"])
logger.info(f"Centroid: {cX}, {cY}")
# Calculate the bounding rectangle of the contour
x, y, w, h = cv2.boundingRect(contour)
# Calculate the area of the contour
area = cv2.contourArea(contour)
cords = {'x' : x, 'y': y}
rect = {'x' : x, 'y': y, 'w': w, 'h': h}
# Print the results to the console
logger.info(f"Processing contour#{i + 1}: area: {area} centroid: {cX}, {cY} rectangle: ({x}, {y}, {w}, {h})")
# Find the matching contour in the JSON data
# NEEDS WORK
matched_contour = find_dayJSON_match_for_contour(x, y, w, h, area, json_data, logger)
# If a matching contour was found, use its ID, otherwise create a new ID
if matched_contour is not None:
logger.info(f"Match with input JSON(nodules) ID: {matched_contour['id']}")
# If no matching contour was found, create a new ID
else:
logger.info(f"No input JSON(nodules) match, ID:{max_id} area: {area} position: {cords}")
# Get the JSON entry corresponding to the matched contour
logger.info(f"Matched contour: {matched_contour}")
JSON_entry = matched_contour['id'] if matched_contour is not None else "ERROR"
logger.info(f"JSON_entry: {JSON_entry}")
entry_id = max_id
match = {}
if matching is not None:
for match_entry in matching:
current_id = match_entry['c']['id']
previous_id = match_entry['p']['id']
name = match_entry['id']
#logger.info(f"first_id: {first_id} second_id: {second_id} name: {name}")
if JSON_entry == current_id:
logger.info(f"Matched with first_id: {current_id} second_id: {previous_id} name: {name}")
# Save the name of the matching entry [first_id, second_id, name]
#match = [first_id, second_id, name]
match = match_entry
entry_id = name
break
else:
print("WARNING: matching is None")
logger.info("WARNING: matching is None")
if match == {}:
logger.info("WARNING: match is empty")
current = {'id': JSON_entry}
match = {'id': max_id, 'p': {}, 'c': current,'n': {},}
#look through the matching and find the corresponding entry, the set the entry_id to the 'name' in the matching entry
# for first_id, second_id, name in matching:
# logger.info(f"first_id: {first_id} second_id: {second_id} name: {name}")
# if JSON_entry == first_id:
# logger.info(f"Matched with {name}")
# entry_id = name
# break
# Create a new entry for the results list 'm' is the matching entry in the matching list
entry = {'m':match, 'c': cords, 'a': area, 'r': rect, 'e': matched_contour}
# if JSON_entry == "ERROR":
# logger.info(f"ERROR: No input JSON(nodules) match, ID:{max_id} area: {area} position: {cords}")
# else:
# # Add the entry to the results list
# results.append(entry)
logger.info(f"entry_id:{entry_id}, entry saved to results list")
# Nodule images will be saved to 'output/crop1001/nodules/{last_detected_string}/{entry_id_number_component}/current_date.jpg'
# separate the date and number from the entry_id, entry_id = '20210401_0' -> date_component = '20210401', id_component = '0'
# get the date_component
entry_id_date_component = entry_id.split('_')[0]
# get the id_component
entry_id_number_component = entry_id.split('_')[1]
#nodule_images_path = os.path.join(nodules_dir, entry_id)
#os.makedirs(nodule_images_path, exist_ok=True)
# # instead of output/crop975/nodules/20230607_202 use output/crop975/nodules/20230607/202
# Extract the image segment corresponding to the contour from both right and left images
right_nodule_img, left_nodule_img = extract_segment(right_image, left_image, cX, cY)
# chech that the size of the images is 50x50 (50, 50, 3)
if right_nodule_img.shape != (50, 50, 3):
logger.info(f"WARNING: right_nodule_img.shape != (50, 50, 3) != {right_nodule_img.shape}")
return entry
if left_nodule_img.shape != (50, 50, 3):
logger.info(f"WARNING: left_nodule_img.shape != (50, 50, 3) != {left_nodule_img.shape}")
return entry
#make sure the 'ouput/crop1001/nodules/{last_detected_string}/{entry_id_number_component}' directory exists, otherwise create it
formatted_entry_id_date_component = entry_id_date_component[0:4] + '-' + entry_id_date_component[4:6] + '-' + entry_id_date_component[6:8]
#last_detected_string = f"Last-Detected-{formatted_entry_id_date_component}"
last_detected_string = f"{formatted_entry_id_date_component}"
nodule_images_path = os.path.join(nodules_dir, last_detected_string, entry_id_number_component)
os.makedirs(nodule_images_path, exist_ok=True)
nodule_images_detection_path = os.path.join(nodule_images_path, "detection")
os.makedirs(nodule_images_detection_path, exist_ok=True)
os.makedirs(nodule_images_path, exist_ok=True)
logger.info(f"created dirs at nodule_detection_path: {nodule_images_detection_path} and nodule_images_original_path: {nodule_images_path}")
# convert date_string to format '20210401' to '2021-04-01'
formated_date_string = date_string[0:4] + '-' + date_string[4:6] + '-' + date_string[6:8]
image_file_name = f"{formated_date_string}.jpg"
right_nodule_image_file_path = os.path.join(nodule_images_detection_path, image_file_name)
cv2.imwrite(right_nodule_image_file_path, right_nodule_img)
logger.info(f"Segmented nodule image saved as {right_nodule_image_file_path}")
left_nodule_image_file_path = os.path.join(nodule_images_path, image_file_name)
cv2.imwrite(left_nodule_image_file_path, left_nodule_img)
logger.info(f"Original nodule image saved as {left_nodule_image_file_path}")
logger.info(f"\n")
nodule_json_entry = {'date': formated_date_string, 'entry': entry}
append_to_json_list(nodule_images_path+"/_.json", nodule_json_entry)
return entry