-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathimgSeg.py
More file actions
224 lines (160 loc) · 6.96 KB
/
imgSeg.py
File metadata and controls
224 lines (160 loc) · 6.96 KB
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
import cv2
import pandas as pd
import numpy as np
import os
def segment_image(imageObj, k):
'''
Sharp image interfaces.
'''
# # Get Image Filename
# image_file = imageObj.filename
# Read Image
#? Mudar para versão do App
image = cv2.imread(os.path.join(imageObj))
# Convert to RGB
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# Reshape the image to a 2D array of pixels and 3 color values (RGB)
pixel_values = image.reshape((-1, 3))
# convert to float
pixel_values = np.float32(pixel_values)
# Define Stopping Criteria (?)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2)
# Number of pixels of certain colors
colors, counts = np.unique(image.reshape(-1, 3),
return_counts = True,
axis = 0)
# number of clusters (K)
if k <= len(colors):
_, labels, (centers) = cv2.kmeans(pixel_values, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
# convert back to 8 bit values
centers = np.uint8(centers)
# flatten the labels array
labels = labels.flatten()
# convert all pixels to the color of the centroids and back to original shape
segmented_image = centers[labels.flatten()]
segmented_image = segmented_image.reshape(image.shape)
return segmented_image
def formatContours(ContourDataFrame):
"""
Format contours into 3D coordinate system.
Returns a contour dataframe.
"""
Contours = []
for index, row in ContourDataFrame.iterrows():
currentContour = ContourDataFrame.values[index][0]
Rcont = []
# for j in range(0,len(currentContour)):
for point in currentContour:
Rcont.append([point[0][0], point[0][1], 0])
# aux = currentContour[j]
# Rcont.append([ aux[0][0], aux[0][1], 0.0])
Contours.append(np.array(Rcont))
# Rewrite formatted dataframe
Cdata = pd.DataFrame(Contours)
return Cdata
def get_contour_orientation(contours):
'''
Get contour orientation.
'''
for contour in contours:
# get contour centroid coordinates
M = cv2.moments(contour)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
for i, point in enumerate(contour):
# Create vectors:
v_centroid = cx
#! CONTINUAR FUNÇÃO
def create_random_bounded(x, y, w, h, samples):
'''
Creates discrete normal distribution of points bounded inside
(x, x+w) and (y, y+h). Returns a tuple of random coordinates.
'''
# samples = 100
randx = np.random.randint(low =x, high = x+w, size = samples)
randy = np.random.randint(low =y, high = y+h, size = samples)
# Convert to tuple
rand = tuple(map(tuple, np.vstack((randx, randy)).T))
return rand
def get_contour_tag(Cdata, Hdata, gs):
'''
This function returns the color tag from inside contour area.
If outermost contour contains children contours, returns the color tag
from the region between outermost and children contours.
Input:
Cdata -> Contour coordinate system dataframe
Hdata -> Hierarchy dataframe
gs -> Grayscaled image
Output:
Colors -> Color tag ordered by contour index in Cdata
'''
Tag = []
# Get Color tag from outermost region (outside contours)
x = 0; y = 0; w = gs.shape[1]; h = gs.shape[0]
samples = 300
rand = create_random_bounded(x, y, w, h, samples)
# Get Outermost contours
outermost_contours = Hdata[Hdata['Parent'] < 0].index
for pixel in rand:
# Check if pixel is inside any of the outermost contours. cv2.pointPolygonTest returs positive value if point
# is inside contour, zero if point is in contour and negative value if point is outside contour area.
inside_pol = [cv2.pointPolygonTest(Cdata.values[out][0], pixel, True) for out in outermost_contours]
if all(item < 0 for item in inside_pol):
Tag.append(pixel)
break
# Get Color tag from region in / in between contours:
for index, row in Cdata.iterrows():
currentContour = Cdata.values[index][0]
currentHierarchy = Hdata.values[index]
# Create contour bounding box
x, y, w, h = cv2.boundingRect(currentContour)
# Create random tuples from a discrete uniform distribution
samples = 100
rand = create_random_bounded(x, y, w, h, samples)
# Sweep random values inside bounding box
for pixel in rand:
# Check if pixel is inside currentContour
insideParent = cv2.pointPolygonTest(currentContour, pixel, True) # Returns positive if pixel is inside contour, negative if not, zero if on contour
if insideParent < 0:
continue
# Check which contour has currentContour as parent
if currentHierarchy[2] > 0:
# Get childreContours indexes
children = Hdata[Hdata['Parent'] == index].index # returns a pandas iterable structure
# Check if pixel is inside childrenContours
insideChildren = [cv2.pointPolygonTest(Cdata.values[chIndex][0], pixel, True) for chIndex in children]
# Check if pixel is inside currentContour and outside all childrenContours
if insideParent > 0 and all(ch < 0 for ch in insideChildren):
Tag.append(pixel)
break
elif insideParent > 0:
Tag.append(pixel)
break
# Convert Tag into color segment: Tag[(x,y)] -> color[(y,x)]
Colors =[]
for i in range(0,len(Tag)):
x = Tag[i][0]
y = Tag[i][1]
Colors.append(gs[y][x])
return Colors
def get_contours_in_df(imgName, Clusters):
'''
Call auxiliary functions to process contour info into a dataframe.
'''
img = segment_image(imgName,Clusters)
# Convert image in grayscale
gs = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
##### Get contours
contours, hierarchy = cv2.findContours(gs,cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
##### Create pandas dataframe for contour and hierarchy
Cdata = pd.DataFrame(contours,columns =['Contours'],dtype=object)
Hdata = pd.DataFrame(hierarchy[0], columns = ['Next', 'Previous', 'First Child', 'Parent'], dtype=object)
##### Get Color info info
Colors = get_contour_tag(Cdata, Hdata, gs)
# Normalize Color tag
Colors = [int(i/max(Colors)) for i in Colors]
# Format the data
Cdata = formatContours(Cdata)
# Get domain dimension
imgDim = (gs.shape[1], gs.shape[0])
return Cdata, Hdata, Colors, imgDim