1

下面的代码所做的一件事是在检查新 ID 是否已经存在之后,将不同的学生 ID 放入小型数据库中。代码如下 -

#enroll.py

# USAGE
# python enroll.py --id S1901 --name somename --conf config/config.json

# import the necessary packages
from pyimagesearch.utils import Conf
from imutils.video import VideoStream
from tinydb import TinyDB
from tinydb import where
import face_recognition
import argparse
import imutils
import pyttsx3
import time
import cv2
import os

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--id", required=True, 
    help="Unique student ID of the student")
ap.add_argument("-n", "--name", required=True, 
    help="Name of the student")
ap.add_argument("-c", "--conf", required=True, 
    help="Path to the input configuration file")
args = vars(ap.parse_args())

# load the configuration file
conf = Conf(args["conf"])

# initialize the database and student table objects
db = TinyDB(conf["db_path"])
studentTable = db.table("student")

# retrieve student details from the database
student = studentTable.search(where(args["id"]))

# check if an entry for the student id does *not* exist, if so, then
# enroll the student
if len(student) == 0: 
    # initialize the video stream and allow the camera sensor to warmup
    print("[INFO] warming up camera...")
    vs = VideoStream(src=0).start()
    time.sleep(2.0)

    # initialize the number of face detections and the total number
    # of images saved to disk 
    faceCount = 0
    total = 0

    # ask the student to stand in front of the camera
    print("{} please stand in front of the camera until you" \
        "receive further instructions".format(args["name"]))

    # initialize the status as detecting
    status = "detecting"

    # create the directory to store the student's data
    os.makedirs(os.path.join(conf["dataset_path"], conf["class"], 
        args["id"]), exist_ok=True)

    # loop over the frames from the video stream
    while True:
        # grab the frame from the threaded video stream, resize it (so
        # face detection will run faster), flip it horizontally, and
        # finally clone the frame (just in case we want to write the
        # frame to disk later)
        frame = vs.read()
        frame = imutils.resize(frame, width=400)
        frame = cv2.flip(frame, 1)
        orig = frame.copy()

        # convert the frame from from RGB (OpenCV ordering) to dlib
        # ordering (RGB) and detect the (x, y)-coordinates of the
        # bounding boxes corresponding to each face in the input image
        rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        boxes = face_recognition.face_locations(rgb,
            model=conf["detection_method"])

        # loop over the face detections
        for (top, right, bottom, left) in boxes:
            # draw the face detections on the frame
            cv2.rectangle(frame, (left, top), (right, bottom), 
                (0, 255, 0), 2)

            # check if the total number of face detections are less
            # than the threshold, if so, then skip the iteration
            if faceCount < conf["n_face_detection"]:
                # increment the detected face count and set the
                # status as detecting face
                faceCount += 1
                status = "detecting"
                continue

            # save the frame to correct path and increment the total 
            # number of images saved
            p = os.path.join(conf["dataset_path"], conf["class"],
                args["id"], "{}.png".format(str(total).zfill(5)))
            cv2.imwrite(p, orig[top:bottom, left:right])
            total += 1

            # set the status as saving frame 
            status = "saving"

        # draw the status on to the frame
        cv2.putText(frame, "Status: {}".format(status), (10, 20),
            cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)

        # show the output frame
        cv2.imshow("Frame", frame)
        cv2.waitKey(1)

        # if the required number of faces are saved then break out from
        # the loop 
        if total == conf["face_count"]:
            # let the student know that face enrolling is over
            print("Thank you {} you are now enrolled in the {} " \
                "class.".format(args["name"], conf["class"]))
            break

    # insert the student details into the database
    studentTable.insert({args["id"]: [args["name"], "enrolled"]})

    # print the total faces saved and do a bit of cleanup
    print("[INFO] {} face images stored".format(total))
    print("[INFO] cleaning up...")
    cv2.destroyAllWindows()
    vs.stop()

# otherwise, a entry for the student id exists
else:
    # get the name of the student
    name = student[0][args["id"]][0]
    print("[INFO] {} has already already been enrolled...".format(
        name))

# close the database
db.close()


问题: 当我第一次运行此代码时,一切正常。

>> python3 enroll.py --id S1111 --name thor --conf config/config.json

我在我的 json 文件中获得了我的 ID,如下所示 -

{"student": {"1": {"S1111": ["thor", "enrolled"]}}}

但是当我尝试输入另一个 ID 时 -

python3 enroll.py --id S1112 --name hulk --conf config/config.json

我收到以下错误 -

错误:

Traceback (most recent call last):
  File "enroll.py", line 35, in <module>
    student = studentTable.search(where(args["id"]))
  File "/usr/lib/python3.5/site-packages/tinydb/table.py", line 222, in search
    docs = [doc for doc in self if cond(doc)]
  File "/usr/lib/python3.5/site-packages/tinydb/table.py", line 222, in <listcomp>
    docs = [doc for doc in self if cond(doc)]
  File "/usr/lib/python3.5/site-packages/tinydb/queries.py", line 59, in __call__
    return self._test(value)
  File "/usr/lib/python3.5/site-packages/tinydb/queries.py", line 136, in notest
    raise RuntimeError('Empty query was evaluated')
RuntimeError: Empty query was evaluated

如果我将表名从更改student为其他名称,那么它只会第一次存储 id 然后给出相同的错误。我不确定这里有什么问题。

4

0 回答 0