Spaces:
Running
Running
Delete cv2_utils.py
Browse files- cv2_utils.py +0 -174
cv2_utils.py
DELETED
|
@@ -1,174 +0,0 @@
|
|
| 1 |
-
|
| 2 |
-
from scipy.spatial import distance as dist
|
| 3 |
-
from imutils import perspective
|
| 4 |
-
from imutils import contours
|
| 5 |
-
import numpy as np
|
| 6 |
-
import argparse
|
| 7 |
-
import imutils
|
| 8 |
-
import cv2
|
| 9 |
-
from functools import reduce
|
| 10 |
-
from scipy.interpolate import interp1d
|
| 11 |
-
import math
|
| 12 |
-
|
| 13 |
-
def midpoint(ptA, ptB):
|
| 14 |
-
return ((ptA[0] + ptB[0]) * 0.5, (ptA[1] + ptB[1]) * 0.5)
|
| 15 |
-
|
| 16 |
-
def extract_bboxes(fused):
|
| 17 |
-
"""Compute bounding boxes from masks.
|
| 18 |
-
mask: [height, width]..
|
| 19 |
-
Returns: bbox array [num_instances, (y1, x1, y2, x2)].
|
| 20 |
-
"""
|
| 21 |
-
mask = cv2.cvtColor(fused, cv2.COLOR_BGR2GRAY)
|
| 22 |
-
mask[mask < 40] = 0
|
| 23 |
-
mask[mask >= 40] = 1
|
| 24 |
-
mask = mask.reshape(256, 256, 1)
|
| 25 |
-
boxes = np.zeros([mask.shape[-1], 4], dtype=np.int32)
|
| 26 |
-
for i in range(mask.shape[-1]):
|
| 27 |
-
m = mask[:, :, i]
|
| 28 |
-
# Bounding box.
|
| 29 |
-
horizontal_indicies = np.where(np.any(m, axis=0))[0]
|
| 30 |
-
vertical_indicies = np.where(np.any(m, axis=1))[0]
|
| 31 |
-
if horizontal_indicies.shape[0]:
|
| 32 |
-
x1, x2 = horizontal_indicies[[0, -1]]
|
| 33 |
-
y1, y2 = vertical_indicies[[0, -1]]
|
| 34 |
-
# x2 and y2 should not be part of the box. Increment by 1.
|
| 35 |
-
x2 += 1
|
| 36 |
-
y2 += 1
|
| 37 |
-
else:
|
| 38 |
-
# No mask for this instance. Might happen due to
|
| 39 |
-
# resizing or cropping. Set bbox to zeros
|
| 40 |
-
x1, x2, y1, y2 = 0, 0, 0, 0
|
| 41 |
-
boxes[i] = np.array([y1, x1, y2, x2])
|
| 42 |
-
return boxes.astype(np.int32)
|
| 43 |
-
|
| 44 |
-
def getContours(npImage, overlay_img, realHeight, realWidth, unit, confidence, angle_th=30):
|
| 45 |
-
# load the image, convert it to grayscale, and blur it slightly
|
| 46 |
-
image = npImage.copy()#cv2.imread(imagePath)
|
| 47 |
-
# image size
|
| 48 |
-
imgHeight = image.shape[0]
|
| 49 |
-
imgWidth = image.shape[1]
|
| 50 |
-
|
| 51 |
-
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
| 52 |
-
gray = cv2.GaussianBlur(gray, (3, 3), 0)
|
| 53 |
-
|
| 54 |
-
# perform edge detection, then perform a dilation + erosion to
|
| 55 |
-
# close gaps in between object edges
|
| 56 |
-
edged = cv2.Canny(gray, 50, 80)
|
| 57 |
-
|
| 58 |
-
edged = cv2.dilate(edged, None, iterations=1)
|
| 59 |
-
edged = cv2.erode(edged, None, iterations=1)
|
| 60 |
-
# find contours in the edge map
|
| 61 |
-
cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
|
| 62 |
-
cv2.CHAIN_APPROX_SIMPLE)
|
| 63 |
-
#cv2.drawContours(image=overlay_img, contours=cnts[0], contourIdx=-1, color=(0, 255, 0), thickness=2, lineType=cv2.LINE_AA)
|
| 64 |
-
cnts = imutils.grab_contours(cnts)
|
| 65 |
-
|
| 66 |
-
# sort the contours from left-to-right and initialize the
|
| 67 |
-
# 'pixels per metric' calibration variable
|
| 68 |
-
(cnts, _) = contours.sort_contours(cnts)
|
| 69 |
-
pixelsPerMetricHeight = realHeight/imgHeight
|
| 70 |
-
pixelsPerMetricWidth = realWidth/imgWidth
|
| 71 |
-
#draw bounding box
|
| 72 |
-
y1, x1, y2, x2 = extract_bboxes(npImage)[0]
|
| 73 |
-
cv2.rectangle(overlay_img,(x1,y1),(x2, y2),(0,255,0),2)
|
| 74 |
-
# loop over the contours individually
|
| 75 |
-
|
| 76 |
-
for c in cnts:
|
| 77 |
-
# if the contour is not sufficiently large, ignore it
|
| 78 |
-
if cv2.contourArea(c) < 100:
|
| 79 |
-
continue
|
| 80 |
-
# compute the rotated bounding box of the contour
|
| 81 |
-
orig = overlay_img.copy()
|
| 82 |
-
box = cv2.minAreaRect(c)
|
| 83 |
-
box = cv2.boxPoints(box)
|
| 84 |
-
box = np.array(box, dtype="int")
|
| 85 |
-
# order the points in the contour such that they appear
|
| 86 |
-
# in top-left, top-right, bottom-right, and bottom-left
|
| 87 |
-
# order, then draw the outline of the rotated bounding
|
| 88 |
-
# box
|
| 89 |
-
box = perspective.order_points(box)
|
| 90 |
-
|
| 91 |
-
# unpack the ordered bounding box, then compute the midpoint
|
| 92 |
-
# between the top-left and top-right coordinates, followed by
|
| 93 |
-
# the midpoint between bottom-left and bottom-right coordinates
|
| 94 |
-
(tl, tr, br, bl) = box
|
| 95 |
-
(tltrX, tltrY) = midpoint(tl, tr)
|
| 96 |
-
(blbrX, blbrY) = midpoint(bl, br)
|
| 97 |
-
# compute the midpoint between the top-left and top-right points,
|
| 98 |
-
# followed by the midpoint between the top-righ and bottom-right
|
| 99 |
-
(tlblX, tlblY) = midpoint(tl, bl)
|
| 100 |
-
(trbrX, trbrY) = midpoint(tr, br)
|
| 101 |
-
|
| 102 |
-
# draw lines between the midpoints
|
| 103 |
-
#cv2.line(orig, (int(tltrX), int(tltrY)), (int(blbrX), int(blbrY)),
|
| 104 |
-
#(255, 0, 0), 1)
|
| 105 |
-
cv2.line(orig, (int(tlblX), int(tlblY)), (int(trbrX), int(trbrY)),
|
| 106 |
-
(0, 0, 255), 1)
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
top_p = min([(int(tlblX), int(tlblY)), (int(trbrX), int(trbrY))], key=lambda x : x[1])
|
| 110 |
-
bot_p = max([(int(tlblX), int(tlblY)), (int(trbrX), int(trbrY))], key=lambda x : x[1])
|
| 111 |
-
D_ad = ((top_p[1] - bot_p[1]) ** 2 + (top_p[0] - bot_p[0])**2) ** 0.5 + 1e-7
|
| 112 |
-
|
| 113 |
-
P1 = min(top_p, bot_p, key=lambda x:x[0])
|
| 114 |
-
P2 = max(top_p, bot_p, key=lambda x:x[0])
|
| 115 |
-
slope = (P1[1] - P2[1]) / (P2[0] - P1[0]) if (P2[0] - P1[0]) != 0 else 0
|
| 116 |
-
cat = ''
|
| 117 |
-
angle = 0
|
| 118 |
-
if slope > 0:
|
| 119 |
-
angle = np.arccos((top_p[0] - bot_p[0])/D_ad) * 180 / math.pi
|
| 120 |
-
cv2.putText(orig, "angle={:.1f}".format(angle),
|
| 121 |
-
(max(top_p[0]-100, 0), top_p[1] + 15), cv2.FONT_HERSHEY_DUPLEX,
|
| 122 |
-
0.45, (0, 0, 255), 1)
|
| 123 |
-
else:
|
| 124 |
-
angle = np.arccos((bot_p[0] - top_p[0])/D_ad) * 180 / math.pi
|
| 125 |
-
cv2.putText(orig, "angle={:.1f}".format(angle),
|
| 126 |
-
(top_p[0], top_p[1] + 15), cv2.FONT_HERSHEY_DUPLEX,
|
| 127 |
-
0.45, (0, 0, 255), 1)
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
# compute the Euclidean distance between the midpoints
|
| 131 |
-
dA = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))
|
| 132 |
-
dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))
|
| 133 |
-
length = cv2.arcLength(c, True) / 2. * pixelsPerMetricWidth
|
| 134 |
-
M = cv2.moments(c)
|
| 135 |
-
cX = int(M["m10"] / M["m00"])
|
| 136 |
-
cY = int(M["m01"] / M["m00"])
|
| 137 |
-
|
| 138 |
-
# width
|
| 139 |
-
mask = gray.copy()
|
| 140 |
-
mask[mask < 40] = 0
|
| 141 |
-
width = cv2.countNonZero(mask[cY][:])
|
| 142 |
-
right_most_x = np.max(np.nonzero(mask[cY][:]))
|
| 143 |
-
left_most_x = np.min(np.nonzero(mask[cY][:]))
|
| 144 |
-
cv2.line(orig, (int(left_most_x), int(cY)), (int(right_most_x), int(cY)),
|
| 145 |
-
(0, 0, 255), 1)
|
| 146 |
-
width *= pixelsPerMetricWidth
|
| 147 |
-
# compute the size of the object
|
| 148 |
-
dimA = dA * pixelsPerMetricHeight
|
| 149 |
-
dimB = dB * pixelsPerMetricWidth
|
| 150 |
-
if angle < angle_th:
|
| 151 |
-
cat +='H'
|
| 152 |
-
cv2.putText(orig, "L={:.1f}".format(length) + unit,
|
| 153 |
-
(int(tltrX), int(tltrY) + 40), cv2.FONT_HERSHEY_DUPLEX,
|
| 154 |
-
0.45, (0, 0, 255), 1)
|
| 155 |
-
cv2.putText(orig, "W={:.1f}".format(width) + unit,
|
| 156 |
-
(int(tltrX), int(tltrY) + 55), cv2.FONT_HERSHEY_DUPLEX,
|
| 157 |
-
0.45, (0, 0, 255), 1)
|
| 158 |
-
else:
|
| 159 |
-
cat += 'V'
|
| 160 |
-
cv2.putText(orig, "L={:.1f}".format(length) + unit,
|
| 161 |
-
(int(tltrX), int(tltrY)), cv2.FONT_HERSHEY_DUPLEX,
|
| 162 |
-
0.45, (0, 0, 255), 1)
|
| 163 |
-
cv2.putText(orig, "W={:.1f}".format(width) + unit,
|
| 164 |
-
(int(tltrX), int(tltrY) + 15), cv2.FONT_HERSHEY_DUPLEX,
|
| 165 |
-
0.45, (0, 0, 255), 1)
|
| 166 |
-
if slope > 0:
|
| 167 |
-
cat += 'L'
|
| 168 |
-
else:
|
| 169 |
-
cat += 'R'
|
| 170 |
-
cv2.putText(orig, "Crack {:.2f}%".format(confidence.item()*100) + " cat="+ cat, (x1, max(0, y1-5)), cv2.FONT_HERSHEY_SIMPLEX, 0.45, (36,255,12), 1)
|
| 171 |
-
|
| 172 |
-
return orig
|
| 173 |
-
|
| 174 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|