Hello,
I got this error while generating embeddings:
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Users\gengstah\Anaconda3\envs\facenet\lib\threading.py", line 916, in _bootstrap_inner
self.run()
File "C:\Users\gengstah\Anaconda3\envs\facenet\lib\threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "contributed\face-recognition.py", line 84, in capture
faces = self.face_recognition.identify(frame)
File "C:\Users\gengstah\python-workspace\facenet\contributed\face.py", line 80, in identify
face.embedding = self.encoder.generate_embedding(face)
File "C:\Users\gengstah\python-workspace\facenet\contributed\face.py", line 110, in generate_embedding
images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
File "C:\Users\gengstah\Anaconda3\envs\facenet\lib\site-packages\tensorflow\python\framework\ops.py", line 2734, in get_tensor_by_name
return self.as_graph_element(name, allow_tensor=True, allow_operation=False)
File "C:\Users\gengstah\Anaconda3\envs\facenet\lib\site-packages\tensorflow\python\framework\ops.py", line 2584, in as_graph_element
return self._as_graph_element_locked(obj, allow_tensor, allow_operation)
File "C:\Users\gengstah\Anaconda3\envs\facenet\lib\site-packages\tensorflow\python\framework\ops.py", line 2627, in _as_graph_element_locked
"graph." % (repr(name), repr(op_name)))
KeyError: "The name 'input:0' refers to a Tensor which does not exist. The operation, 'input', does not exist in the graph."
I rewrote the contributed/real_time_face_recognition.py to use tkinter. Since the continuous loop of grabbing an image from camera, predicting the face, and displaying it in a tk.Label (tkinter) is causing the application not to be responsive, I decided to implement these processes in a separate thread. After doing so, I get the error above. Here is a snippet of what I have done so far:
def __init__(self, master=None):
super().__init__(master)
print("Loading Face Recognition...")
self.face_recognition = face.Recognition()
print("Done")
def start(self):
print("start")
self.stop_event = threading.Event()
self.channel1 = threading.Thread(target=self.capture, args=("0", self.face_recognition))
self.channel1.start()
def capture(self, channel, face_recognition):
frame_interval = 3 # Number of frames after which to run face detection
fps_display_interval = 5 # seconds
frame_rate = 0
frame_count = 0
start_time = time.time()
while(not self.stop_event.is_set()):
try:
url_response = urllib.request.urlopen("[SNAPSHOT_IMAGE_FROM_IP_CAMERA]")
except Exception as e:
print("Failed to get feed from channel {}: {}".format(channel, e))
break
img_array = np.array(bytearray(url_response.read()), dtype=np.uint8)
frame = cv2.imdecode(img_array, -1)
# Identify faces
if (frame_count % frame_interval) == 0:
faces = face_recognition.identify(frame)
# Check our current fps
end_time = time.time()
if (end_time - start_time) > fps_display_interval:
frame_rate = int(frame_count / (end_time - start_time))
start_time = time.time()
frame_count = 0
self.add_overlays(frame, faces, frame_rate)
frame_count += 1
b,g,r = cv2.split(frame)
frame = cv2.merge((r,g,b))
img = Image.fromarray(frame)
imagetk = ImageTk.PhotoImage(image=img)
if channel == "0":
self.imageview1.configure(image=imagetk)
self.imageview1.image = imagetk
EDIT 1: I am using the frozen graph provided by David and generated my own classifier. The model and classifier is working nicely using my webcam.
EDIT 2: I tried to store the face.Recognition object to thread local and tested it in one thread. It works but having more than 1 thread (more than 1 face.Recognition object) eats up all my memory. How can I use only one face.Recognition for many threads without getting the error above?
Ok, I got it working by modifying face.py. I learned that tf.get_default_graph() returns a Graph for the current thread. This works fine in a single-threaded application but since I'm working on a multi-threaded application, the tf.get_default_graph() returns a Graph that doesn't have my model loaded.
I changed the following lines:
images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")
to
images_placeholder = self.sess.graph.get_tensor_by_name("input:0")
embeddings = self.sess.graph.get_tensor_by_name("embeddings:0")
phase_train_placeholder = self.sess.graph.get_tensor_by_name("phase_train:0")
This change enables multi-threading.
Most helpful comment
Ok, I got it working by modifying
face.py. I learned thattf.get_default_graph()returns aGraphfor the current thread. This works fine in a single-threaded application but since I'm working on a multi-threaded application, thetf.get_default_graph()returns aGraphthat doesn't have my model loaded.I changed the following lines:
to
This change enables multi-threading.