🧪 New tutorials are being published — build from robot arms to sensors step by step
Skip to content

Chapter 5: Cat Face Detection

Buy in Store

Chapter goal: Have the NanoCam detect cats' faces, and understand how it differs from the face detection model.

Principle

Cat face detection uses the CatFaceDetectMN03 model, trained specifically for cat facial features (triangular ears / wide eye spacing / nose). Input: a 320x240 RGB565 image; output: a list of cat face bounding boxes. It shares the same print_detection_result output format with Chapter 4's face detection.

Cat Face vs. Face Detection Model Differences

ComparisonFace detection (ai_mode:2)Cat face detection (ai_mode:1)
ModelMSR01 + MNP01 two-stage cascadeCatFaceDetectMN03 single-stage
Keypoints10 (both eyes / nose tip / mouth corners)None (the model does not output them)
Confidence thresholdMSR01=0.3, MNP01=0.40.4
Detection box drawingGreen hollow rectangle + 5 keypointsGreen hollow rectangle (no keypoints)

Steps

5.1 Switching the Mode

Plain
ai_mode:1

The device reboots automatically into cat face detection mode

For the complete commands, see the Serial Protocol Manual.

5.2 Observing the Effect

Put a cat or a picture of a cat in front of the camera; open http://<IP> in a browser to see a green detection box marking the cat's face.

5.3 Serial Output

When a cat face is detected, the serial port outputs:

Plain
I (xxxxx) detection_result: [ 0]: ( 45,  30, 180, 210)
  • Format: [index] (x, y, w, h) — top-left corner coordinates of the cat face box + width and height

  • The cat face model does not output keypoints (unlike face detection)

Code

Core Detection Logic

components/modules/ai/who_cat_face_detection.cpp:

C++
CatFaceDetectMN03 detector(0.4F, 0.3F, 10, 0.3F);
std::list<dl::detect::result_t> &detect_results = detector.infer(
    (uint16_t *)frame->buf, {(int)frame->height, (int)frame->width, 3});

if (detect_results.size() > 0) {
    draw_detection_result((uint16_t *)frame->buf, frame->height, frame->width, detect_results);
    print_detection_result(detect_results);  // Output coordinates over serial
}

Arduino: Reading Coordinates to Control a Servo

C++
// Parse the $face:x,y,w,h# format
if (nanoSerial.available()) {
    String line = nanoSerial.readStringUntil('\n');
    if (line.startsWith("$face:")) {
        int x = line.substring(6).toInt();
        int y = line.substring(line.indexOf(',')+1).toInt();
        servoX.write(map(x, 0, 320, 0, 180));
    }
}

Python Serial Reading

Python
import serial
ser = serial.Serial("COM3", 115200)
while True:
    line = ser.readline().decode().strip()
    if "detection_result" in line:
        print(line)

Result

A cat appears → a green box is drawn on the image → coordinates are output over serial. You can read the coordinates with Arduino/Python to drive a servo and track it.

Next chapter: Chapter 6: Color Recognition