Evaluate and Enumeration Panel
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -0,0 +1,314 @@
|
||||
import math
|
||||
import numpy as np
|
||||
import cv2
|
||||
import matplotlib.pyplot as plt
|
||||
from scipy import ndimage
|
||||
from scipy import signal
|
||||
import georasters as gr
|
||||
|
||||
|
||||
def order_points_rect(pts):
|
||||
# initialzie a list of coordinates that will be ordered
|
||||
# such that the first entry in the list is the top-left,
|
||||
# the second entry is the top-right,
|
||||
# the third is the bottom-right, and
|
||||
#the fourth is the bottom-left
|
||||
rect = np.zeros((4, 2), dtype = "float32")
|
||||
# the top-left point will have the smallest sum, whereas
|
||||
# the bottom-right point will have the largest sum
|
||||
s = pts.sum(axis = 1)
|
||||
rect[0] = pts[np.argmin(s)]
|
||||
rect[2] = pts[np.argmax(s)]
|
||||
# now, compute the difference between the points, the
|
||||
# top-right point will have the smallest difference,
|
||||
# whereas the bottom-left will have the largest difference
|
||||
diff = np.diff(pts, axis = 1)
|
||||
rect[1] = pts[np.argmin(diff)]
|
||||
rect[3] = pts[np.argmax(diff)]
|
||||
# return the ordered coordinates
|
||||
return rect
|
||||
|
||||
|
||||
def perspectiveTransform(Points):
|
||||
#Transform cuadrilater image segmentation to rectangle image
|
||||
# Return Matrix Transform
|
||||
Points = np.array(Points)
|
||||
Points_order = order_points_rect(Points)
|
||||
#dst = np.asarray([[0, 0], [0, 1], [1, 1], [1, 0]], dtype = "float32")
|
||||
|
||||
(tl, tr, br, bl) = Points_order
|
||||
# compute the width of the new image, which will be the
|
||||
# maximum distance between bottom-right and bottom-left
|
||||
# x-coordiates or the top-right and top-left x-coordinates
|
||||
widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
|
||||
widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
|
||||
maxWidth = max(int(widthA), int(widthB))
|
||||
# compute the height of the new image, which will be the
|
||||
# maximum distance between the top-right and bottom-right
|
||||
# y-coordinates or the top-left and bottom-left y-coordinates
|
||||
heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
|
||||
heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
|
||||
maxHeight = max(int(heightA), int(heightB))
|
||||
# now that we have the dimensions of the new image, construct
|
||||
# the set of destination points to obtain a "birds eye view",
|
||||
# (i.e. top-down view) of the image, again specifying points
|
||||
# in the top-left, top-right, bottom-right, and bottom-left
|
||||
# order
|
||||
dst = np.array([
|
||||
[0, 0],
|
||||
[maxWidth , 0],
|
||||
[maxWidth , maxHeight ],
|
||||
[0, maxHeight ]], dtype = "float32")
|
||||
|
||||
M = cv2.getPerspectiveTransform(Points_order, dst)
|
||||
return M, maxWidth, maxHeight
|
||||
|
||||
def subdivision_rect(factors, maxWidth, maxHeight, merge_percentaje = 0):
|
||||
## From a rect (top-left, top-right, bottom-right, bottom-left) subidive in rectangle
|
||||
|
||||
#factors = factors_number(n_divide)[-1] # First factor is smaller
|
||||
|
||||
#if maxWidth > maxHeight:
|
||||
# split_Width = [maxWidth / factors[1] * i for i in range(factors[1] + 1)]
|
||||
# split_Height = [maxHeight / factors[0] * i for i in range(factors[0] + 1)]
|
||||
#else:
|
||||
# split_Width = [maxWidth / factors[0] * i for i in range(factors[0] + 1)]
|
||||
# split_Height = [maxHeight / factors[1] * i for i in range(factors[1] + 1)]
|
||||
merge_Width = maxWidth * merge_percentaje
|
||||
merge_Height = maxHeight * merge_percentaje
|
||||
split_Width = [maxWidth / factors[0] * i for i in range(factors[0] + 1)]
|
||||
split_Height = [maxHeight / factors[1] * i for i in range(factors[1] + 1)]
|
||||
|
||||
sub_division = []
|
||||
for j in range(len(split_Height) - 1):
|
||||
for i in range(len(split_Width) - 1):
|
||||
|
||||
sub_division.append([(max(split_Width[i] - merge_Width, 0) , max(split_Height[j] - merge_Height , 0)),
|
||||
(min(split_Width[i+1] + merge_Width , maxWidth - 1), max(split_Height[j] - merge_Height , 0)),
|
||||
(min(split_Width[i+1] + merge_Width , maxWidth - 1), min(split_Height[j+1] + merge_Height, maxHeight - 1)),
|
||||
(max(split_Width[i] - merge_Width, 0), min(split_Height[j+1] + merge_Height, maxHeight - 1))])
|
||||
|
||||
return np.array(sub_division)
|
||||
|
||||
|
||||
def skeleton(bin_image, n_important = 100):
|
||||
#From binary image (0,255) transform to skeleton edge
|
||||
|
||||
kernel_size = 3
|
||||
edges = cv2.GaussianBlur((bin_image.copy()).astype(np.uint8),(kernel_size, kernel_size),0)
|
||||
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(5, 5))
|
||||
height,width = edges.shape
|
||||
skel = np.zeros([height,width],dtype=np.uint8) #[height,width,3]
|
||||
temp_nonzero = np.count_nonzero(edges)
|
||||
|
||||
while (np.count_nonzero(edges) != 0 ):
|
||||
eroded = cv2.erode(edges,kernel)
|
||||
#cv2.imshow("eroded",eroded)
|
||||
temp = cv2.dilate(eroded,kernel)
|
||||
#cv2.imshow("dilate",temp)
|
||||
temp = cv2.subtract(edges,temp)
|
||||
skel = cv2.bitwise_or(skel,temp)
|
||||
edges = eroded.copy()
|
||||
|
||||
"""This function returns the count of labels in a mask image."""
|
||||
label_im, nb_labels = ndimage.label(skel)#, structure= np.ones((2,2))) ## Label each connect region
|
||||
label_areas = np.bincount(label_im.ravel())[1:]
|
||||
keys_max_areas = np.array(sorted(range(len(label_areas)), key=lambda k: label_areas[k], reverse = True)) + 1
|
||||
keys_max_areas = keys_max_areas[:n_important]
|
||||
L = np.zeros(label_im.shape)
|
||||
for i in keys_max_areas:
|
||||
L[label_im == i] = i
|
||||
|
||||
labels = np.unique(L)
|
||||
label_im = np.searchsorted(labels, L)
|
||||
|
||||
return label_im>0
|
||||
|
||||
def angle_lines(skel_filter, n_important = 100, angle_resolution = 360, threshold = 100, min_line_length = 200, max_line_gap = 50, plot = False):
|
||||
#Measure the angle of lines in skel_filter. Obs the angle is positive in clockwise.
|
||||
|
||||
rho = 1 # distance resolution in pixels of the Hough grid
|
||||
theta = np.pi / angle_resolution # angular resolution in radians of the Hough grid
|
||||
#threshold = 100 # minimum number of votes (intersections in Hough grid cell)
|
||||
#min_line_length = 200 # minimum number of pixels making up a line
|
||||
#max_line_gap = 50 # maximum gap in pixels between connectable line segments
|
||||
|
||||
lines = cv2.HoughLines(np.uint8(skel_filter),rho, theta, threshold)
|
||||
lines_P = cv2.HoughLinesP(np.uint8(skel_filter),rho, theta, threshold, np.array([]) ,min_line_length, max_line_gap)
|
||||
|
||||
if lines_P is None:
|
||||
print("linea no encontrada")
|
||||
return 0
|
||||
|
||||
theta_P = [np.pi/2 + np.arctan2(line[0][3] - line[0][1],line[0][2]-line[0][0]) for line in lines_P[:n_important]]
|
||||
|
||||
theta = lines[0:n_important,0,1]
|
||||
|
||||
h = np.histogram(np.array(theta), bins = angle_resolution, range=(-np.pi,np.pi))
|
||||
peaks = signal.find_peaks_cwt(h[0], widths= np.arange(2,4))
|
||||
h_P = np.histogram(np.array(theta_P), bins = angle_resolution, range=(-np.pi,np.pi))
|
||||
peaks_P = signal.find_peaks_cwt(h_P[0], widths= np.arange(2,4))
|
||||
|
||||
#h= np.histogram(np.array(theta), bins = angle_resolution, range=(-np.pi,np.pi))
|
||||
#peaks = argrelextrema(h[0], np.greater)
|
||||
#h_P = np.histogram(np.array(theta_P), bins = angle_resolution, range=(-np.pi,np.pi))
|
||||
#peaks_P = argrelextrema(h_P[0], np.greater)
|
||||
|
||||
mesh = np.array(np.meshgrid(h[1][peaks], h_P[1][peaks_P]))
|
||||
combinations = mesh.T.reshape(-1, 2)
|
||||
index_min = np.argmin([abs(a-b) for a,b in combinations])
|
||||
theta_prop = np.mean(combinations[index_min])
|
||||
|
||||
if plot:
|
||||
print('Theta in HoughLines: ', h[1][peaks])
|
||||
print('Theta in HoughLinesP: ', h_P[1][peaks_P])
|
||||
print('combinations: ', combinations)
|
||||
print('Theta prop: ', theta_prop)
|
||||
|
||||
|
||||
Z1 = np.ones((skel_filter.shape))*255
|
||||
Z2 = np.ones((skel_filter.shape))*255
|
||||
|
||||
for line in lines[0:n_important]:
|
||||
rho,theta = line[0]
|
||||
a = np.cos(theta)
|
||||
b = np.sin(theta)
|
||||
x0 = a*rho
|
||||
y0 = b*rho
|
||||
x1 = int(x0 + 1000*(-b))
|
||||
y1 = int(y0 + 1000*(a))
|
||||
x2 = int(x0 - 1000*(-b))
|
||||
y2 = int(y0 - 1000*(a))
|
||||
#print((x1,y1,x2,y2))
|
||||
cv2.line(Z1,(x1,y1),(x2,y2),(0,0,255),2)
|
||||
|
||||
for line in lines_P[:n_important]:
|
||||
x1,y1,x2,y2 = line[0]
|
||||
cv2.line(Z2,(x1,y1),(x2,y2),(0,0,255),2)
|
||||
|
||||
plt.figure(0)
|
||||
plt.figure(figsize=(16,8))
|
||||
|
||||
plt.imshow(skel_filter)
|
||||
plt.title('Skel_filter')
|
||||
|
||||
fig, axs = plt.subplots(1, 2, figsize=(16,8))
|
||||
axs[0].imshow(Z1)
|
||||
axs[0].title.set_text('Lines HoughLines')
|
||||
|
||||
axs[1].imshow(Z2)
|
||||
axs[1].title.set_text('Lines HoughLinesP')
|
||||
|
||||
fig, axs = plt.subplots(1, 2, figsize=(16,8))
|
||||
axs[0].hist(lines[0:n_important,0,1], bins = 45, range=[-np.pi,np.pi])
|
||||
axs[0].title.set_text('Lines HoughLines theta Histogram')
|
||||
|
||||
|
||||
axs[1].hist(theta_P, bins = 45, range=[-np.pi,np.pi])
|
||||
axs[1].title.set_text('Lines HoughLinesP theta Histogram')
|
||||
#print(lines.shape)
|
||||
#print(lines_P.shape)
|
||||
|
||||
|
||||
return theta_prop
|
||||
|
||||
def rgb2hsv(rgb):
|
||||
""" convert RGB to HSV color space
|
||||
|
||||
:param rgb: np.ndarray
|
||||
:return: np.ndarray
|
||||
"""
|
||||
|
||||
rgb = rgb.astype('float')
|
||||
maxv = np.amax(rgb, axis=2)
|
||||
maxc = np.argmax(rgb, axis=2)
|
||||
minv = np.amin(rgb, axis=2)
|
||||
minc = np.argmin(rgb, axis=2)
|
||||
|
||||
hsv = np.zeros(rgb.shape, dtype='float')
|
||||
hsv[maxc == minc, 0] = np.zeros(hsv[maxc == minc, 0].shape)
|
||||
hsv[maxc == 0, 0] = (((rgb[..., 1] - rgb[..., 2]) * 60.0 / (maxv - minv + np.spacing(1))) % 360.0)[maxc == 0]
|
||||
hsv[maxc == 1, 0] = (((rgb[..., 2] - rgb[..., 0]) * 60.0 / (maxv - minv + np.spacing(1))) + 120.0)[maxc == 1]
|
||||
hsv[maxc == 2, 0] = (((rgb[..., 0] - rgb[..., 1]) * 60.0 / (maxv - minv + np.spacing(1))) + 240.0)[maxc == 2]
|
||||
hsv[maxv == 0, 1] = np.zeros(hsv[maxv == 0, 1].shape)
|
||||
hsv[maxv != 0, 1] = (1 - minv / (maxv + np.spacing(1)))[maxv != 0]
|
||||
hsv[..., 2] = maxv
|
||||
|
||||
return hsv
|
||||
|
||||
|
||||
def doubleMADsfromMedian(y,thresh=3.5):
|
||||
# warning: this function does not check for NAs
|
||||
# nor does it address issues when
|
||||
# more than 50% of your data have identical values
|
||||
m = np.median(y)
|
||||
abs_dev = np.abs(y - m)
|
||||
left_mad = np.median(abs_dev[y <= m])
|
||||
right_mad = np.median(abs_dev[y >= m])
|
||||
y_mad = left_mad * np.ones(len(y))
|
||||
y_mad[y > m] = right_mad
|
||||
modified_z_score = 0.6745 * abs_dev / y_mad
|
||||
modified_z_score[y == m] = 0
|
||||
return modified_z_score > thresh
|
||||
|
||||
|
||||
def watershed_marked(thresh, min_Area = 100, threshold_median_Area = 3):
|
||||
## Thresh is the segmentation image use to watershed
|
||||
##
|
||||
|
||||
# Perform the distance transform algorithm
|
||||
dist = cv2.distanceTransform(thresh, cv2.DIST_L2, 3)
|
||||
# Normalize the distance image for range = {0.0, 1.0}
|
||||
# so we can visualize and threshold it
|
||||
cv2.normalize(dist, dist, 0, 1.0, cv2.NORM_MINMAX)
|
||||
# Threshold to obtain the peaks
|
||||
# This will be the markers for the foreground objects
|
||||
_, dist = cv2.threshold((dist*255).astype(np.uint8), 0, 255 , cv2.THRESH_BINARY + cv2.THRESH_OTSU)
|
||||
# Dilate a bit the dist image
|
||||
kernel1 = np.ones((3,3), dtype=np.uint8)
|
||||
dist = cv2.dilate(dist, kernel1 , iterations = 1)
|
||||
dist = cv2.erode(dist, kernel1 , iterations = 1)
|
||||
|
||||
|
||||
#dist[0: 10,-10:] = 255
|
||||
dist[-10:,-10:] = 255
|
||||
|
||||
dist_8u = dist.astype('uint8')
|
||||
|
||||
# Find total markers
|
||||
contours, _ = cv2.findContours(dist_8u, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
|
||||
# Create the marker image for the watershed algorithm
|
||||
markers = np.zeros(dist.shape, dtype=np.int32)
|
||||
# Draw the foreground markers
|
||||
for i in range(len(contours)):
|
||||
cv2.drawContours(markers, contours, i, (i+1), -1)
|
||||
|
||||
|
||||
markers = cv2.watershed(cv2.cvtColor(thresh,cv2.COLOR_GRAY2RGB), markers)
|
||||
markers[markers == 1] = 0
|
||||
markers[markers == -1] = 0
|
||||
|
||||
Areas = []
|
||||
for i in range(1,np.max(markers) + 1):
|
||||
if np.sum(markers == i) < min_Area:
|
||||
markers[markers == i] = 0
|
||||
else:
|
||||
Areas.append([i, np.sum(markers == i)])
|
||||
|
||||
Areas = np.array(Areas)
|
||||
L_Areas = doubleMADsfromMedian(Areas[:,1], threshold_median_Area)
|
||||
for i,Logic in zip(Areas[:,0], L_Areas) :
|
||||
if Logic:
|
||||
markers[markers == i] = 0
|
||||
|
||||
return Areas[L_Areas,:], dist_8u,markers
|
||||
|
||||
def pixel2gps(points, geot):
|
||||
# transform pixel to gps coordinate
|
||||
return np.vstack(gr.map_pixel_inv(points[:,1], points[:,0],geot[1],geot[-1], geot[0],geot[3])).T
|
||||
|
||||
|
||||
|
||||
def gps2pixel(points_coord, geot):
|
||||
# transform gps coordinate to pixel
|
||||
return np.flip(np.vstack(gr.map_pixel(points_coord[:,0], points_coord[:,1],geot[1],geot[-1], geot[0],geot[3])).T,1)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
Reference in New Issue
Block a user