Je pense que la visualisation de la base du jugement est souvent considérée comme une tendance récente. J'ai commencé python à l'université, et comme je m'occupe un peu de yolov3, j'aimerais pouvoir visualiser la carte des fonctionnalités. De plus, comme je suis débutant, je ne suis pas familier avec le programme ou n'ai pas un style d'écriture de base, alors soyez gentil avec moi. Ici, le code de yolov3 que je traite maintenant est Github : "qqwweee/keras-yolo3" Est le code de. J'aimerais jouer un peu avec ce code pour visualiser la carte des fonctionnalités.
yolov3 semble en sortir trois, petit, moyen et grand, alors j'en ai sorti trois. Les parties que j'ai manipulées dans yolo.py sont le premier init, la dernière partie de generate et detect_image. Veuillez jeter un œil aux commentaires.
def __init__(self, **kwargs):
self.__dict__.update(self._defaults) # set up default values
self.__dict__.update(kwargs) # and update with user overrides
self.class_names = self._get_class()
self.anchors = self._get_anchors()
self.sess = K.get_session()
Augmentation de #feature_get.
self.boxes, self.scores, self.classes ,self.feature_get= self.generate()
def generate(self):
model_path = os.path.expanduser(self.model_path)
assert model_path.endswith('.h5'), 'Keras model or weights must be a .h5 file.'
# Load model, or construct model and load weights.
num_anchors = len(self.anchors)
num_classes = len(self.class_names)
is_tiny_version = num_anchors==6 # default setting
try:
self.yolo_model = load_model(model_path, compile=False)
except:
self.yolo_model = tiny_yolo_body(Input(shape=(None,None,3)), num_anchors//2, num_classes) \
if is_tiny_version else yolo_body(Input(shape=(None,None,3)), num_anchors//3, num_classes)
self.yolo_model.load_weights(self.model_path) # make sure model, anchors and classes match
else:
assert self.yolo_model.layers[-1].output_shape[-1] == \
num_anchors/len(self.yolo_model.output) * (num_classes + 5), \
'Mismatch between model and given anchor and class sizes'
print('{} model, anchors, and classes loaded.'.format(model_path))
# Generate colors for drawing bounding boxes.
hsv_tuples = [(x / len(self.class_names), 1., 1.)
for x in range(len(self.class_names))]
self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples))
self.colors = list(
map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)),
self.colors))
np.random.seed(10101) # Fixed seed for consistent colors across runs.
np.random.shuffle(self.colors) # Shuffle colors to decorrelate adjacent classes.
np.random.seed(None) # Reset seed to default.
# Generate output tensor targets for filtered bounding boxes.
self.input_image_shape = K.placeholder(shape=(2, ))
if self.gpu_num>=2:
self.yolo_model = multi_gpu_model(self.yolo_model, gpus=self.gpu_num)
boxes, scores, classes = yolo_eval(self.yolo_model.output, self.anchors,
len(self.class_names), self.input_image_shape,
score_threshold=self.score, iou_threshold=self.iou)
# Ajoutez ce qui suit. Choisissez 3 couches pour lesquelles vous souhaitez obtenir une carte d'entités
J'ai regardé #summary et regardé la couche d'activation juste avant la sortie.
feature_get = [self.yolo_model.get_layer("leaky_re_lu_58").output , self.yolo_model.get_layer("leaky_re_lu_65").output , self.yolo_model.get_layer("leaky_re_lu_72").output]
return boxes, scores, classes, feature_get
def detect_image(self, image):
start = timer()
if self.model_image_size != (None, None):
assert self.model_image_size[0]%32 == 0, 'Multiples of 32 required'
assert self.model_image_size[1]%32 == 0, 'Multiples of 32 required'
boxed_image = letterbox_image(image, tuple(reversed(self.model_image_size)))
else:
new_image_size = (image.width - (image.width % 32),
image.height - (image.height % 32))
boxed_image = letterbox_image(image, new_image_size)
image_data = np.array(boxed_image, dtype='float32')
print(image_data.shape)
image_data /= 255.
image_data = np.expand_dims(image_data, 0) # Add batch dimension.
Augmentation de #feature_get de un
out_boxes, out_scores, out_classes, feature_get= self.sess.run(
[self.boxes, self.scores, self.classes, self.feature_get],
feed_dict={
self.yolo_model.input: image_data,
self.input_image_shape: [image.size[1], image.size[0]],
K.learning_phase(): 0
})
print('Found {} boxes for {}'.format(len(out_boxes), 'img'))
font = ImageFont.truetype(font='font/FiraMono-Medium.otf',
size=np.floor(3e-2 * image.size[1] + 0.5).astype('int32'))
thickness = (image.size[0] + image.size[1]) // 300
for i, c in reversed(list(enumerate(out_classes))):
predicted_class = self.class_names[c]
box = out_boxes[i]
score = out_scores[i]
label = '{} {:.2f}'.format(predicted_class, score)
draw = ImageDraw.Draw(image)
label_size = draw.textsize(label, font)
top, left, bottom, right = box
top = max(0, np.floor(top + 0.5).astype('int32'))
left = max(0, np.floor(left + 0.5).astype('int32'))
bottom = min(image.size[1], np.floor(bottom + 0.5).astype('int32'))
right = min(image.size[0], np.floor(right + 0.5).astype('int32'))
print(label, (left, top), (right, bottom))
if top - label_size[1] >= 0:
text_origin = np.array([left, top - label_size[1]])
else:
text_origin = np.array([left, top + 1])
# My kingdom for a good redistributable image drawing library.
for i in range(thickness):
draw.rectangle(
[left + i, top + i, right - i, bottom - i],
outline=self.colors[c])
draw.rectangle(
[tuple(text_origin), tuple(text_origin + label_size)],
fill=self.colors[c])
draw.text(text_origin, label, fill=(0, 0, 0), font=font)
del draw
end = timer()
return image, feature_get
Maintenant, écrivez le code pour obtenir la carte des caractéristiques Si vous le sortez tel quel, il sortira beaucoup, donc pour le moment, je vais essayer d'extraire la carte avec la valeur moyenne la plus élevée pour petit, moyen et grand respectivement.
import numpy as np
import keras.backend as K
from keras.models import load_model
from keras.layers import Input
from PIL import Image, ImageDraw,ImageOps
import tensorflow as tf
import cv2
import math
import collections
def feature(conv_list):
#Je veux obtenir la carte avec la valeur moyenne la plus élevée.
conv_list1 = np.asarray(conv_list[0])
conv_list2 = np.asarray(conv_list[1])
conv_list3 = np.asarray(conv_list[2])
bg = np.zeros((720,720))
ave1 = []
ave2 = []
ave3 = []
for i in range(conv_list1.shape[3]):
conv = conv_list1[0,:,:,i]
norm1 = np.max(conv)
conv = conv / norm1
ave1.append(np.mean(conv))
max1 = np.max(ave1)
index1 = ave1.index(max1)
conv1 = conv_list1[0,:,:,index1]
norm1 = np.max(conv1)
conv1 = conv1 / norm1
for i in range(conv_list2.shape[3]):
conv = conv_list2[0,:,:,i]
norm2 = np.max(conv)
conv = conv / norm2
ave2.append(np.mean(conv))
max2 = np.max(ave2)
index2 = ave2.index(max2)
conv2 = conv_list2[0,:,:,index2]
norm2 = np.max(conv2)
conv2 = conv2 / norm2
for i in range(conv_list3.shape[3]):
conv = conv_list3[0,:,:,i]
norm3 = np.max(conv)
conv = conv / norm3
ave3.append(np.mean(conv))
max3 = np.max(ave3)
index3 = ave3.index(max3)
conv3 = conv_list3[0,:,:,index3]
norm3 = np.max(conv3)
conv3 = conv3 / norm3
conv1 = conv1 * 255
conv2 = conv2 * 255
conv3 = conv3 * 255
conv1 = cv2.resize(conv1, (350, 350), interpolation=cv2.INTER_NEAREST)
conv2 = cv2.resize(conv2, (350, 350), interpolation=cv2.INTER_NEAREST)
conv3 = cv2.resize(conv3, (350, 350), interpolation=cv2.INTER_NEAREST)
bg[5:355,5:355] = conv1
bg[5:355,365:715] = conv2
bg[365:715,5:355] = conv3
return bg
Enfin, j'ai joué avec yolo_video.py.
def detect_img(yolo):
while True:
img = input('Input image filename:')
try:
image = Image.open(img)
except:
print('Open Error! Try again!')
continue
else:
r_image , feature_get = yolo.detect_image(image)
#Afficher la carte des fonctionnalités Procédez comme suit.
img_feature = feature_img.feature(feature_get)
cv2.imwrite("feature_map.png " , img_feature)
r_image.show()
yolo.close_session()
Vous devriez maintenant obtenir une carte des fonctionnalités en exécutant yolo_video.py --image.
Cette fois, j'ai emprunté un chat à Pakutaso, un matériau gratuit, je vais donc essayer de le détecter. À propos, le poids utilisé par défaut yolo.h5 ↓ C'est un chat détecté
La carte des caractéristiques ressemble à ceci
Je ne suis pas sûr. On dirait que les yeux et la bouche du chat sont caractéristiques. À propos, le chat dans l'image d'entrée est redimensionné en le collant sur l'image grise 416 x 416 avec la largeur ajustée lorsqu'il est mis dans le réseau. La carte des caractéristiques est adaptée à sa taille. Yolov3 est-il centré sur les cellules de la grille? Je ne sais pas où je regarde au centre, et je ne sais pas laquelle des trois cartes je regarde pour déterminer que c'est un chat, donc je dois le rendre visible. Je pensais que ce ne serait pas le cas. De plus, cette fois, j'ai regardé le dernier calque activé, mais si vous regardez un autre calque, il peut changer de différentes manières. Je ne sais pas comment traiter la valeur de la carte acquise, donc je pense qu'il existe un meilleur moyen.
J'ai écrit un article comme celui-ci pour la première fois et j'espère qu'il sera utile pour les mêmes débutants.
Recommended Posts