如何解决如何将 filter_detection(tf.image.non_max_suppression) 的输出转换为 numpy nd 数组
我在自定义图像数据集上使用 EfficientDet 模型进行对象检测。我正在尝试在 Jetson 上进行部署,但目前 Jetson 上的 cuda 库不支持 NMS 功能。因此我不得不在后处理管道中实现 nms 功能。 nms 函数的输出是张量。我曾尝试使用 eval()、numpy() 和 session 转换它们,但它们不起作用。这是下面的代码。
def filter_detections(
Boxes,classification,alphas=None,ratios=None,class_specific_filter=True,nms=True,score_threshold=0.01,max_detections=100,nms_threshold=0.5,detect_quadrangle=False,):
"""
Filter detections using the Boxes and classification values.
Args
Boxes: Tensor of shape (num_Boxes,4) containing the Boxes in (x1,y1,x2,y2) format.
classification: Tensor of shape (num_Boxes,num_classes) containing the classification scores.
other: List of tensors of shape (num_Boxes,...) to filter along with the Boxes and classification scores.
class_specific_filter: Whether to perform filtering per class,or take the best scoring class and filter those.
nms: Flag to enable/disable non maximum suppression.
score_threshold: Threshold used to prefilter the Boxes with.
max_detections: Maximum number of detections to keep.
nms_threshold: Threshold for the IoU value to determine when a Box should be suppressed.
Returns
A list of [Boxes,scores,labels,other[0],other[1],...].
Boxes is shaped (max_detections,4) and contains the (x1,y2) of the non-suppressed Boxes.
scores is shaped (max_detections,) and contains the scores of the predicted class.
labels is shaped (max_detections,) and contains the predicted label.
other[i] is shaped (max_detections,...) and contains the filtered other[i] data.
In case there are less than max_detections detections,the tensors are padded with -1's.
"""
def _filter_detections(scores_,labels_):
# threshold based on score
# (num_score_keeps,1)
indices_ = tf.where(keras.backend.greater(scores_,score_threshold))
if nms:
# (num_score_keeps,4)
filtered_Boxes = tf.gather_nd(Boxes,indices_)
# In [4]: scores = np.array([0.1,0.5,0.4,0.2,0.7,0.2])
# In [5]: tf.greater(scores,0.4)
# Out[5]: <tf.Tensor: id=2,shape=(6,),dtype=bool,numpy=array([False,True,False,False])>
# In [6]: tf.where(tf.greater(scores,0.4))
# Out[6]:
# <tf.Tensor: id=7,shape=(2,1),dtype=int64,numpy=
# array([[1],# [4]])>
#
# In [7]: tf.gather(scores,tf.where(tf.greater(scores,0.4)))
# Out[7]:
# <tf.Tensor: id=15,dtype=float64,numpy=
# array([[0.5],# [0.7]])>
filtered_scores = keras.backend.gather(scores_,indices_)[:,0]
# perform NMS
# filtered_Boxes = tf.concat([filtered_Boxes[...,1:2],filtered_Boxes[...,0:1],# filtered_Boxes[...,3:4],2:3]],axis=-1)
nms_indices = tf.image.non_max_suppression(filtered_Boxes,filtered_scores,max_output_size=max_detections,IoU_threshold=nms_threshold)
# filter indices based on NMS
# (num_score_nms_keeps,1)
indices_ = keras.backend.gather(indices_,nms_indices)
# add indices to list of all indices
# (num_score_nms_keeps,)
labels_ = tf.gather_nd(labels_,indices_)
# (num_score_nms_keeps,2)
indices_ = keras.backend.stack([indices_[:,0],labels_],axis=1)
return indices_
if class_specific_filter:
all_indices = []
# perform per class filtering
for c in range(int(classification.shape[1])):
scores = classification[:,c]
labels = c * tf.ones((keras.backend.shape(scores)[0],dtype='int64')
all_indices.append(_filter_detections(scores,labels))
# concatenate indices to single tensor
# (concatenated_num_score_nms_keeps,2)
indices = keras.backend.concatenate(all_indices,axis=0)
else:
scores = keras.backend.max(classification,axis=1)
labels = keras.backend.argmax(classification,axis=1)
indices = _filter_detections(scores,labels)
# select top k
scores = tf.gather_nd(classification,indices)
labels = indices[:,1]
scores,top_indices = tf.nn.top_k(scores,k=keras.backend.minimum(max_detections,keras.backend.shape(scores)[0]))
# filter input using the final set of indices
indices = keras.backend.gather(indices[:,top_indices)
Boxes = keras.backend.gather(Boxes,indices)
labels = keras.backend.gather(labels,top_indices)
# zero pad the outputs
pad_size = keras.backend.maximum(0,max_detections - keras.backend.shape(scores)[0])
Boxes = tf.pad(Boxes,[[0,pad_size],[0,0]],constant_values=-1)
scores = tf.pad(scores,pad_size]],constant_values=-1)
labels = tf.pad(labels,constant_values=-1)
labels = keras.backend.cast(labels,'int32')
# set shapes,since we kNow what they are
Boxes.set_shape([max_detections,4])
scores.set_shape([max_detections])
labels.set_shape([max_detections])
if detect_quadrangle:
alphas = keras.backend.gather(alphas,indices)
ratios = keras.backend.gather(ratios,indices)
alphas = tf.pad(alphas,constant_values=-1)
ratios = tf.pad(ratios,constant_values=-1)
alphas.set_shape([max_detections,4])
ratios.set_shape([max_detections])
return [Boxes,alphas,ratios,labels]
else:
return [Boxes,labels]
class FilterDetections(keras.layers.Layer):
"""
Keras layer for filtering detections using score threshold and NMS.
"""
def __init__(
self,parallel_iterations=32,**kwargs
):
"""
Filters detections using score threshold,NMS and selecting the top-k detections.
Args
nms: Flag to enable/disable NMS.
class_specific_filter: Whether to perform filtering per class,or take the best scoring class and filter those.
nms_threshold: Threshold for the IoU value to determine when a Box should be suppressed.
score_threshold: Threshold used to prefilter the Boxes with.
max_detections: Maximum number of detections to keep.
parallel_iterations: Number of batch items to process in parallel.
"""
self.nms = nms
self.class_specific_filter = class_specific_filter
self.nms_threshold = nms_threshold
self.score_threshold = score_threshold
self.max_detections = max_detections
self.parallel_iterations = parallel_iterations
self.detect_quadrangle = detect_quadrangle
super(FilterDetections,self).__init__(**kwargs)
def call(self,inputs,**kwargs):
"""
Constructs the NMS graph.
Args
inputs : List of [Boxes,...] tensors.
"""
Boxes = inputs[0]
classification = inputs[1]
if self.detect_quadrangle:
alphas = inputs[2]
ratios = inputs[3]
# wrap nms with our parameters
def _filter_detections(args):
Boxes_ = args[0]
classification_ = args[1]
alphas_ = args[2] if self.detect_quadrangle else None
ratios_ = args[3] if self.detect_quadrangle else None
return filter_detections(
Boxes_,classification_,alphas_,ratios_,nms=self.nms,class_specific_filter=self.class_specific_filter,score_threshold=self.score_threshold,max_detections=self.max_detections,nms_threshold=self.nms_threshold,detect_quadrangle=self.detect_quadrangle,)
# call filter_detections on each batch item
if self.detect_quadrangle:
outputs = tf.map_fn(
_filter_detections,elems=[Boxes,ratios],dtype=['float32','float32','int32'],parallel_iterations=self.parallel_iterations
)
else:
outputs = tf.map_fn(
_filter_detections,classification],parallel_iterations=self.parallel_iterations
)
return outputs
def compute_output_shape(self,input_shape):
"""
Computes the output shapes given the input shapes.
Args
input_shape : List of input shapes [Boxes,classification].
Returns
List of tuples representing the output shapes:
[filtered_Boxes.shape,filtered_scores.shape,filtered_labels.shape,filtered_other[0].shape,filtered_other[1].shape,...]
"""
if self.detect_quadrangle:
return [
(input_shape[0][0],self.max_detections,4),(input_shape[1][0],self.max_detections),]
else:
return [
(input_shape[0][0],]
def compute_mask(self,mask=None):
"""
This is required in Keras when there is more than 1 output.
"""
return (len(inputs) + 1) * [None]
def get_config(self):
"""
Gets the configuration of this layer.
Returns
Dictionary containing the parameters of this layer.
"""
config = super(FilterDetections,self).get_config()
config.update({
'nms': self.nms,'class_specific_filter': self.class_specific_filter,'nms_threshold': self.nms_threshold,'score_threshold': self.score_threshold,'max_detections': self.max_detections,'parallel_iterations': self.parallel_iterations,})
return config
推理文件如下:
import tensorflow as tf
import numpy as np
import cv2
import os
from contextlib import redirect_stdout
import glob
import nms_2 as nm
from tensorflow import keras
from nms import FilterDetections
import time
#from utils import preprocess_image
from tensorflow.python.platform import gfile
def postprocess_Boxes(Boxes,scale,height,width):
scale_x = 768/width
scale_y = 768/height
Boxes[:,0] = Boxes[:,0]/scale_x
Boxes[:,1] = Boxes[:,1]/scale_y
Boxes[:,2] = Boxes[:,2]/scale_x
Boxes[:,3] = Boxes[:,3]/scale_y
return Boxes
def preprocess_image(image,image_size):
image = cv2.resize(image,(768,768))
image = image.astype(np.float32)
image /= 255.
return image,0.2
def get_frozen_graph(graph_file):
with tf.gfile.FastGFile(graph_file,"rb") as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
with tf.Graph().as_default() as graph:
tf.import_graph_def(graph_def,name='')
return graph
def main():
phi = 2
model_path = '/EfficientDet/checkpoints/model.pb'
image_sizes = (512,640,768,896,1024,1280,1408)
image_size = image_sizes[phi]
classes = ['case',]
num_classes = len(classes)
score_threshold = 0.5
colors = [np.random.randint(0,256,3).tolist() for i in range(num_classes)]
output_names = {
'output_Boxes': 'clipped_Boxes/stack:0',#'output_scores': 'filtered_detections/map/TensorArrayStack_1/TensorArrayGatherV3:0','output_class': 'classification/concat:0'
}
common_config = tf.ConfigProto()
common_config.gpu_options.allow_growth = True
# common_config.gpu_options.per_process_gpu_memory_fraction = 0.4
graph = get_frozen_graph(model_path)
sess = tf.Session(config=common_config,graph=graph)
output_Boxes = sess.graph.get_tensor_by_name(output_names["output_Boxes"])
#output_scores = sess.graph.get_tensor_by_name(output_names['output_scores'])
output_class = sess.graph.get_tensor_by_name(output_names['output_class'])
frames_path = '/images/*.jpg'
#cap = cv2.VideoCapture(video_path)
for img in glob.glob(frames_path):
st = time.time()
image = cv2.imread(img)
#if not ret:
# break
image = image[:,:,::-1]
h,w = image.shape[:2]
image,scale = preprocess_image(image,image_size=image_size)
image_batch = np.expand_dims(image,axis=0)
# print("Image time : ",(time.time() - st))
start = time.time()
Feed_dict = {"input_1:0": image_batch}
Boxes,classes = sess.run([output_Boxes,output_class],Feed_dict)
# Boxes = np.squeeze(Boxes)
# classes = classes)
# print(classes)
# print(Boxes)
tensor1,tensor2,tensor3 = FilterDetections(score_threshold=score_threshold)([Boxes,classes])
#**This part is not working as I am unable to convert the tesnors**
# a,b,c = sess.run([tensor1,tensor3],Feed_dict)
# print(tensor1,tensor3)
# print(tensor1)
# print(tf.make_ndarray(tensor2.op.get_attr('value')))
# print("Model time : ",(time.time() - start))
Boxes = postprocess_Boxes(Boxes=Boxes,scale=0.2,height=h,width=w)
# print(Boxes)
# select indices which have a score above the threshold
#indices = np.where(scores[:] > score_threshold)[0]
# select those detections
#Boxes = Boxes[indices]
#labels = labels[indices]
# print("Total Time : ",(time.time() - st))
if __name__ == '__main__':
main()
我试图将盒子作为 nd 数组,但我得到了张量,我无法转换它们,因为模型图没有 nms 层。我需要转换方面的帮助。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。