-
Notifications
You must be signed in to change notification settings - Fork 0
/
region_proposal_detection.py
173 lines (143 loc) · 5.9 KB
/
region_proposal_detection.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
# USAGE
# python region_proposal_detection.py --image beagle.png
# import the necessary packages
from tensorflow.keras.applications import ResNet50
from tensorflow.keras.applications.resnet50 import preprocess_input
from tensorflow.keras.applications import imagenet_utils
from tensorflow.keras.preprocessing.image import img_to_array
from imutils.object_detection import non_max_suppression
import numpy as np
import argparse
import cv2
def selective_search(image, method="fast"):
# initialize OpenCV's selective search implementation and set the
# input image
ss = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()
ss.setBaseImage(image)
# check to see if we are using the *fast* but *less accurate* version
# of selective search
if method == "fast":
ss.switchToSelectiveSearchFast()
# otherwise we are using the *slower* but *more accurate* version
else:
ss.switchToSelectiveSearchQuality()
# run selective search on the input image
rects = ss.process()
# return the region proposal bounding boxes
return rects
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
help="path to the input image")
ap.add_argument("-m", "--method", type=str, default="fast",
choices=["fast", "quality"],
help="selective search method")
ap.add_argument("-c", "--conf", type=float, default=0.9,
help="minimum probability to consider a classification/detection")
ap.add_argument("-f", "--filter", type=str, default=None,
help="comma separated list of ImageNet labels to filter on")
args = vars(ap.parse_args())
# grab the label filters command line argument
labelFilters = args["filter"]
# if the label filter is not empty, break it into a list
if labelFilters is not None:
labelFilters = labelFilters.lower().split(",")
# load ResNet from disk (with weights pre-trained on ImageNet)
print("[INFO] loading ResNet...")
model = ResNet50(weights="imagenet")
# load the input image from disk and grab its dimensions
image = cv2.imread(args["image"])
(H, W) = image.shape[:2]
# run selective search on the input image
print("[INFO] performing selective search with '{}' method...".format(
args["method"]))
rects = selective_search(image, method=args["method"])
print("[INFO] {} regions found by selective search".format(len(rects)))
# initialize the list of region proposals that we'll be classifying
# along with their associated bounding boxes
proposals = []
boxes = []
# loop over the region proposal bounding box coordinates generated by
# running selective search
for (x, y, w, h) in rects:
# if the width or height of the region is less than 10% of the
# image width or height, ignore it (i.e., filter out small
# objects that are likely false-positives)
if w / float(W) < 0.1 or h / float(H) < 0.1:
continue
# extract the region from the input image, convert it from BGR to
# RGB channel ordering, and then resize it to 224x224 (the input
# dimensions required by our pre-trained CNN)
roi = image[y:y + h, x:x + w]
roi = cv2.cvtColor(roi, cv2.COLOR_BGR2RGB)
roi = cv2.resize(roi, (224, 224))
# further preprocess by the ROI
roi = img_to_array(roi)
roi = preprocess_input(roi)
# update our proposals and bounding boxes lists
proposals.append(roi)
boxes.append((x, y, w, h))
# convert the proposals list into NumPy array and show its dimensions
proposals = np.array(proposals)
print("[INFO] proposal shape: {}".format(proposals.shape))
# classify each of the proposal ROIs using ResNet and then decode the
# predictions
print("[INFO] classifying proposals...")
preds = model.predict(proposals)
preds = imagenet_utils.decode_predictions(preds, top=1)
# initialize a dictionary which maps class labels (keys) to any
# bounding box associated with that label (values)
labels = {}
# loop over the predictions
for (i, p) in enumerate(preds):
# grab the prediction information for the current region proposal
(imagenetID, label, prob) = p[0]
# only if the label filters are not empty *and* the label does not
# exist in the list, then ignore it
if labelFilters is not None and label not in labelFilters:
continue
# filter out weak detections by ensuring the predicted probability
# is greater than the minimum probability
if prob >= args["conf"]:
# grab the bounding box associated with the prediction and
# convert the coordinates
(x, y, w, h) = boxes[i]
box = (x, y, x + w, y + h)
# grab the list of predictions for the label and add the
# bounding box + probability to the list
L = labels.get(label, [])
L.append((box, prob))
labels[label] = L
# loop over the labels for each of detected objects in the image
for label in labels.keys():
# clone the original image so that we can draw on it
print("[INFO] showing results for '{}'".format(label))
clone = image.copy()
# loop over all bounding boxes for the current label
for (box, prob) in labels[label]:
# draw the bounding box on the image
(startX, startY, endX, endY) = box
cv2.rectangle(clone, (startX, startY), (endX, endY),
(0, 255, 0), 2)
# show the results *before* applying non-maxima suppression, then
# clone the image again so we can display the results *after*
# applying non-maxima suppression
cv2.imshow("Before", clone)
clone = image.copy()
# extract the bounding boxes and associated prediction
# probabilities, then apply non-maxima suppression
boxes = np.array([p[0] for p in labels[label]])
proba = np.array([p[1] for p in labels[label]])
boxes = non_max_suppression(boxes, proba)
# loop over all bounding boxes that were kept after applying
# non-maxima suppression
for (startX, startY, endX, endY) in boxes:
# draw the bounding box and label on the image
cv2.rectangle(clone, (startX, startY), (endX, endY),
(0, 255, 0), 2)
y = startY - 10 if startY - 10 > 10 else startY + 10
cv2.putText(clone, label, (startX, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 255, 0), 2)
# show the output after apply non-maxima suppression
cv2.imshow("After", clone)
cv2.waitKey(0)