在这里插入图片描述
在这里插入图片描述

行空板K10是一款专为快速体验物联网和学习人工智能而设计的开发学习板,100%采用国产芯片,知识产权自主可控,符合信息科技课程中编程学习、物联网及人工智能等教学需求。该板集成2.8寸LCD彩屏、WiFi蓝牙、摄像头、麦克风、扬声器、RGB指示灯、多种传感器及丰富的扩展接口。凭借高度集成的板载资源,教学过程中无需额外连接其他设备,便可轻松实现传感器控制、物联网应用以及人脸识别、语音识别、语音合成等AI人工智能项目。

主要特点
集成摄像头&内置算法,可进行离线图像检测
集成麦克风&内置算法,可进行离线语音识别
集成扬声器&内置算法,可进行离线语音合成
2.8寸彩色屏幕,数据展示更清晰
集成度高,利于教学
接口丰富,兼容软件多,扩展性好

在这里插入图片描述
主打:人工智能模块

在这里插入图片描述

人脸检测相关说明

在这里插入图片描述
在这里插入图片描述

辅助:屏幕显示相关积木

在这里插入图片描述
LED控制模块

在这里插入图片描述

在这里插入图片描述

知识点:行空板 K10 人脸检测

一、什么是行空板人脸检测
行空板 K10 内置 ESP32-S3 AI 硬件加速 NPU,搭配板载摄像头,依托unihiker_k10.h内置 AI 视觉库,本地离线完成人脸检测,不需要联网、不需要云端运算,设备单独就能识别画面里是否存在人脸、输出人脸坐标。
区别于人脸识别:人脸检测只找 “人脸区域”,不区分是谁;人脸识别会比对人脸特征区分不同人。
核心硬件基础
主控:ESP32-S3 内置 AI 加速器,专门处理图像识别算法;
外设:板载前置摄像头,实时采集画面;
输出载体:K10 彩色显示屏、RGB 彩灯、扬声器、按键;
存储:TF 卡可保存人脸截图、训练模型。

二、核心基础功能
1、离线实时检测
摄像头持续刷新画面,AI 实时框选画面内所有人脸,输出人脸左上角、右下角坐标,能获取人脸宽度、高度。
2、画面可视化标记
画布直接绘制红色矩形框,把识别到的人脸圈出来,直观展示检测结果。
3、状态联动反馈
检测到人脸 / 无人脸可联动硬件:
RGB 彩灯:有人脸亮绿灯、无人脸亮红灯;
音频:检测到人脸播放提示音;
屏幕文字:实时打印「检测到人脸」「未识别人脸」;
4、配套拓展功能
人脸抓拍:检测到人脸自动保存截图到 TF 卡;
延时计数:持续 3 秒检测到人脸再触发动作,过滤瞬间路过干扰;
多人脸识别:支持同时识别画面内多张人脸。

三、底层运行逻辑
摄像头采集图像数据流;
NPU 硬件加速运行轻量化人脸检测模型;
算法输出人脸矩形坐标数据;
程序读取坐标,在屏幕画布绘制方框;
循环持续采集 + 推理,实现实时动态追踪人脸。

在这里插入图片描述

四、两种编程实现方式(Mind+)

方式 1:图形化积木(新手首选,无编译报错)
扩展库加载「AI 视觉 - 人脸检测」,积木逻辑:
初始化摄像头、AI 人脸检测;
循环采集画面;
判断是否检测到人脸;
分支:有人脸→画框、亮绿灯、播放提示音;无人脸→清框、红灯;
优势:不用处理库冲突、无多重定义报错,课堂教学首选。

方式 2:C/C++ 代码(进阶自主开发)
依托unihiker_k10.h内置 AI 接口,核心流程:
初始化摄像头 AI 模块 k10.initAI();
循环调用人脸检测函数获取人脸数组;
判断人脸数量大于 0,遍历所有人脸坐标;
画布绘制矩形框标记人脸;
联动灯光、音频、存储。

五、典型落地应用场景
1、人脸门禁提醒装置
检测到人脸自动亮绿灯、播放欢迎音效,无人时红灯待机;可拓展继电器控制门锁。
2、课堂人脸考勤记录仪
持续检测画面内人脸,检测到人脸自动抓拍保存照片到 TF 卡,记录到场人员画面。
3、桌面智能护眼监测
检测人脸距离屏幕过近时,屏幕弹出提示文字、蜂鸣器报警,提醒保持观看距离。
4、智能人体感应灯光
识别到人脸自动开启 RGB 氛围灯,人脸离开几秒后自动关灯。
5、互动趣味装置
对准屏幕人脸触发特效、播放音乐,人脸消失特效关闭。

六、使用优缺点
优势
完全离线本地运行,不用 WiFi、不用物联网平台,断网也能用;
ESP32-S3 硬件 AI 加速,画面流畅不卡顿,不占用 CPU;
配套 K10 屏幕、灯光、音频、TF 卡全套硬件,拓展简单;
Mind + 图形化 + 代码双模式,零基础、进阶学员都适配;
接口高度封装,不用学习复杂 AI 算法,直接调用现成函数。
局限
仅支持人脸检测,原生不自带人脸比对(区分不同人),如需人脸识别需要额外训练模型;
光线过暗、侧脸、遮挡口罩会降低识别准确率;
高帧率连续抓拍会小幅占用内存,多 AI 任务(人脸 + 物体识别)同时运行会卡顿;
抓拍图片默认覆盖存储,如需多图存档需要自定义命名逻辑。

七、实操关键注意事项
光线充足:暗光环境识别率大幅下降,建议室内正常灯光下实验;
人脸正对摄像头:侧脸、低头、口罩遮挡容易漏检;
硬件初始化顺序:必须先k10.begin()、初始化摄像头,再开启 AI 人脸检测;
不要叠加多余图形库(TFT_eSPI),避免多重定义编译报错;
循环内减少delay()阻塞延时,否则人脸画面卡顿、检测失效;
抓拍保存照片需提前执行k10.initSDFile()初始化 TF 卡。

在这里插入图片描述
【花雕动手做】行空板 K10 系列实验之人脸检测的人脸识别门禁提示器
实验开源代码

// 引入行空板K10综合硬件驱动库:封装屏幕、按键、RGB彩灯、摄像头、画布等外设接口
#include "unihiker_k10.h"
// 引入ESP32-S3离线AI视觉库:提供人脸录入、人脸比对识别、AI模式切换相关函数
#include "AIRecognition.h"

// 提前声明A/B按键中断回调函数,setup绑定按键时编译器可识别函数
void onButtonBPressed();
void onButtonAPressed();

// ===================== 硬件对象实例化 =====================
// 行空板K10主控全局对象,所有基础硬件操作均通过该对象调用
UNIHIKER_K10  k10;
// 屏幕旋转参数:2=正向正常显示,可修改0/1/2/3切换画面翻转
uint8_t       screen_dir=2;
// AI人脸识别专用对象,负责人脸模型初始化、录入、比对识别指令下发
AIRecognition ai;
// 音频播放对象,用于识别到家人时播放欢迎提示旋律
Music         music;

// ===================== 全局状态标记变量 =====================
bool startRecogFlag = false;   // 人脸识别总开关:false=待机不识别,true=开启实时人脸比对
bool playFlag = false;         // 音乐单次播放标记:防止loop循环反复重复播放欢迎音乐
float nowFaceID = 0;           // 存储当前识别成功的人脸专属编号ID(录入第一张人脸ID=1,第二张=2)
unsigned long faceLostTimer = 0; // 人脸丢失计时戳:记录最后一次识别到人脸的系统时间,用于延时缓冲
const unsigned long FACE_KEEP_DELAY = 3000; // 人脸消失缓冲时长3000ms=3秒,短暂遮挡不会立刻退出识别

/**
 * @brief 统一绘制待机界面函数
 * @desc 开机、人脸超时退出识别、录入人脸完成后均调用,简化重复代码
 * 功能:清空屏幕、打印操作提示文字、关闭全部RGB氛围灯
 */
void showStandbyUI()
{
  // 清空画布所有原有文字画面
  k10.canvas->canvasClear();
  // 绘制红色24号中英文字体标题,坐标X0 Y0,透明度50,开启自动换行
  k10.canvas->canvasText("       人脸识别门禁", 0, 0, 0xFF0000, k10.canvas->eCNAndENFont24, 50, true);
  // 白色操作指引文字,坐标X0 Y35
  k10.canvas->canvasText("A键录入人脸 B键识别", 0, 35, 0xFFFFFF, k10.canvas->eCNAndENFont24, 50, true);
  // 将画布缓存内容刷新到实体屏幕显示
  k10.canvas->updateCanvas();
  // -1代表控制全部RGB灯珠,0x000000=黑色,关闭所有彩灯
  k10.rgb->write(-1, 0x000000);
}

/**
 * @brief 上电初始化函数,仅开机运行1次
 * 执行顺序:主板硬件初始化→屏幕→AI加速器→摄像头→按键绑定→切换人脸AI模式→加载待机界面
 */
void setup() {
	// 初始化行空板底层总线、IO、供电等全部硬件
	k10.begin();
	// 根据screen_dir参数初始化显示屏驱动
	k10.initScreen(screen_dir);
	// 初始化ESP32-S3内置NPU AI硬件加速器,加载AI推理底层资源
	ai.initAi();
	// 初始化摄像头后台画面渲染功能,支持摄像头画面投屏到屏幕
	k10.initBgCamerImage();
	// 初始化阶段临时关闭摄像头画面,避免画面干扰初始化流程
	k10.setBgCamerImage(false);
	// 创建画布缓存,绘图先存入缓存再统一刷新,消除屏幕闪烁
	k10.creatCanvas();
	// 临时切换AI为无识别模式,清空上一轮残留AI模型,防止模式冲突
	ai.switchAiMode(ai.NoMode);

	// 给A、B物理按键绑定按下中断回调函数,按键触发不受delay阻塞
	k10.buttonB->setPressedCallback(onButtonBPressed);
	k10.buttonA->setPressedCallback(onButtonAPressed);

	// 开启摄像头实时画面投屏,屏幕持续显示镜头取景画面
	k10.setBgCamerImage(true);
	// 切换AI工作模式为人脸识别模式,同时支持人脸录入+人脸特征比对
	ai.switchAiMode(ai.Face);
	// 设置RGB彩灯全局亮度,round(3)亮度等级低,光线柔和不刺眼
	k10.rgb->brightness(round(3));

	// 开机完成硬件初始化,直接加载待机界面,无报警、无识别逻辑
	showStandbyUI();
}

/**
 * @brief 主循环函数,上电后无限循环执行
 * 核心逻辑:分待机状态、识别中状态;识别中区分「识别到家人」「人脸短暂丢失」「人脸超时消失」三类场景
 */
void loop() {
	// 判断总开关:未按下B开启识别,直接终止本次循环,保持待机界面不做任何识别运算
	if (!startRecogFlag) {
		return;
	}

	// ai.isRecognized():true=匹配到已录入的人脸,false=无人脸/陌生人脸
	bool hasFace = ai.isRecognized();
	// 获取系统开机至今累计运行毫秒数,用于无阻塞计时,不卡顿画面
	unsigned long nowTime = millis();

	// ========== 场景1:摄像头识别到已录入的合法家人人脸 ==========
	if (hasFace) {
		faceLostTimer = nowTime; // 刷新人脸计时戳,只要人脸在镜头内就持续重置缓冲倒计时
		nowFaceID = ai.getRecognitionID(); // 读取当前匹配到的人脸编号ID

		// 清空画布,擦除上一轮陌生人/待机文字
		k10.canvas->canvasClear();
		// 打印当前识别到的人脸ID数字
		k10.canvas->canvasText("检测人脸 ID:" + String(nowFaceID), 0, 0, 0x00FF00, k10.canvas->eCNAndENFont24, 50, true);

		// 匹配ID=1:老爷人脸专属提示
		if (nowFaceID == 1.0) {
			k10.canvas->canvasText("欢迎老爷回家!", 0, 40, 0x00FF00, k10.canvas->eCNAndENFont24, 50, true);
			k10.rgb->write(-1, 0x00FF00); // 全彩灯常亮绿色
			// 仅第一次识别到人脸播放一次欢迎音乐,循环内不会重复播放
			if (!playFlag) {
				music.playMusic(DADADADUM);
				playFlag = true;
			}
		}
		// 匹配ID=2:小姐人脸专属提示
		else if (nowFaceID == 2.0) {
			k10.canvas->canvasText("欢迎小姐回家!", 0, 40, 0x00FF00, k10.canvas->eCNAndENFont24, 50, true);
			k10.rgb->write(-1, 0x00FF00); // 全彩灯常亮绿色
			if (!playFlag) {
				music.playMusic(DADADADUM);
				playFlag = true;
			}
		}
		// 刷新画布,把欢迎文字显示到屏幕
		k10.canvas->updateCanvas();
	}
	// ========== 场景2:摄像头未识别到录入人脸(人脸离开/遮挡/陌生人) ==========
	else {
		// 判断人脸丢失时长是否小于3秒缓冲阈值
		if (nowTime - faceLostTimer < FACE_KEEP_DELAY) {
			// 3秒内短暂遮挡、转头、挡脸:不切换界面,直接跳出本次循环,保持上一轮欢迎画面
			return;
		}
		// 人脸完全离开镜头超过3秒:关闭识别总开关,退出识别模式
		startRecogFlag = false;
		playFlag = false; // 重置音乐标记,下次重新识别家人时会再次播放欢迎旋律
		showStandbyUI(); // 调用待机界面函数,回到初始安静界面,无任何报警提示
	}
}

/**
 * @brief A按键按下回调函数:执行人脸录入学习功能
 * 操作流程:显示采集提示→下发录入指令→等待3秒采集人脸特征→提示录入完成→1.2秒后自动切回待机
 */
void onButtonAPressed() {
	k10.canvas->canvasClear();
	// 蓝色采集提示文字,提醒用户正对摄像头
	k10.canvas->canvasText("采集人脸中,请正对镜头", 0, 0, 0x0066FF, k10.canvas->eCNAndENFont24, 50, true);
	k10.canvas->updateCanvas();

	ai.sendFaceCmd(ENROLL); // 下发AI录入指令:采集当前人脸特征,本地存储分配ID
	delay(3000); // 阻塞3秒,给AI充足时间完成人脸特征采集

	k10.canvas->canvasClear();
	// 绿色文字提示录入成功
	k10.canvas->canvasText("人脸录入完成!", 0, 0, 0x00FF00, k10.canvas->eCNAndENFont24, 50, true);
	k10.canvas->canvasText("按B键开启门禁识别",0,35,0xFFFFFF,k10.canvas->eCNAndENFont24,50,true);
	k10.canvas->updateCanvas();

	delay(1200); // 停留1.2秒让用户看清录入成功提示
	showStandbyUI(); // 录入结束自动返回待机界面
}

/**
 * @brief B按键按下回调函数:开启实时人脸识别比对模式
 * 操作流程:开启识别总开关→重置人脸丢失计时→下发识别指令→弹出识别启动提示
 */
void onButtonBPressed() {
	startRecogFlag = true; // 打开识别总开关,loop循环开始执行人脸检测逻辑
	faceLostTimer = millis(); // 初始化人脸丢失计时,按下B瞬间开始计算3秒缓冲
	ai.sendFaceCmd(RECOGNIZE); // 下发AI识别指令,持续比对镜头人脸和本地录入人脸库

	k10.canvas->canvasClear();
	k10.canvas->canvasText("门禁识别已启动", 0, 0, 0x0066FF, k10.canvas->eCNAndENFont24, 50, true);
	k10.canvas->canvasText("正在实时识别人脸",0,35,0xFFFFFF,k10.canvas->eCNAndENFont24,50,true);
	k10.canvas->updateCanvas();
	delay(1000); // 提示界面停留1秒,之后进入loop实时人脸识别
}

代码解读
一、头文件与前置声明

// 行空板K10硬件总库:屏幕、按键、RGB、摄像头、画布全部底层驱动
#include "unihiker_k10.h"
// AI视觉库:ESP32-S3内置NPU人脸检测、人脸录入、人脸比对功能
#include "AIRecognition.h"

// 提前声明按键回调函数,setup绑定按键时编译器识别函数
void onButtonBPressed();
void onButtonAPressed();

二、全局硬件对象

UNIHIKER_K10  k10;    // 主控对象,所有硬件操作入口
uint8_t       screen_dir=2; // 屏幕方向:2=正向正常显示
AIRecognition ai;     // AI人脸识别专用对象
Music         music;  // 音频播放对象,识别到家人播放提示音

三、全局状态控制变量

bool startRecogFlag = false;   // 识别总开关:false=待机不识别,true=开启人脸比对
bool playFlag = false;         // 音乐防重复标记:只在第一次识别到人脸播放音乐
float nowFaceID = 0;           // 存储识别成功的人脸编号,录入第一张人脸ID=1,第二张=2
unsigned long faceLostTimer = 0; // 人脸丢失计时戳,记录最后一次识别到人脸的系统时间
const unsigned long FACE_KEEP_DELAY = 3000; // 人脸缓冲3秒:短暂遮挡不退出识别

四、封装函数:待机界面 showStandbyUI ()
作用
统一管理开机、人脸超时、录入完成后的初始界面,复用代码,不用重复写绘图逻辑。

void showStandbyUI()
{
  k10.canvas->canvasClear(); // 清空屏幕所有文字画面
  // 红色标题文字
  k10.canvas->canvasText("       人脸识别门禁", 0, 0, 0xFF0000, k10.canvas->eCNAndENFont24, 50, true);
  // 白色操作指引:A录入、B启动识别
  k10.canvas->canvasText("A键录入人脸 B键识别", 0, 35, 0xFFFFFF, k10.canvas->eCNAndENFont24, 50, true);
  k10.canvas->updateCanvas(); // 刷新画布到屏幕
  k10.rgb->write(-1, 0x000000); // -1代表全部RGB灯,0x000000关闭彩灯
}

五、setup () 上电初始化(仅运行 1 次)
执行顺序:硬件初始化 → AI 初始化 → 摄像头初始化 → 绑定按键 → 切换人脸 AI 模式 → 加载待机界面

void setup() {
	k10.begin();                // 初始化主板全部底层硬件
	k10.initScreen(screen_dir); // 初始化显示屏
	ai.initAi();                // 开启ESP32-S3内置AI加速器NPU
	k10.initBgCamerImage();     // 初始化摄像头画面投屏功能
	k10.setBgCamerImage(false); // 初始化阶段临时关闭摄像头画面
	k10.creatCanvas();          // 创建画布缓存,消除屏幕闪烁
	ai.switchAiMode(ai.NoMode); // 清空上一轮AI模型,避免冲突

	// 绑定A、B按键中断回调,按下按键立刻执行对应函数,不受delay阻塞
	k10.buttonB->setPressedCallback(onButtonBPressed);
	k10.buttonA->setPressedCallback(onButtonAPressed);

	k10.setBgCamerImage(true);  // 开启摄像头实时画面投屏
	ai.switchAiMode(ai.Face);   // 切换AI模式为人脸识别(支持录入+比对)
	k10.rgb->brightness(round(3)); // 设置RGB亮度,数值越小灯光越柔和

	showStandbyUI(); // 开机直接显示待机界面,无识别、无报警
}

六、loop () 主循环(上电无限循环,核心业务逻辑)
逻辑分层:待机拦截 → 识别到人脸 → 人脸丢失分两种情况(短暂遮挡 / 超时离开)

void loop() {
	// 1. 识别总开关关闭:保持待机,直接跳出循环,不执行任何识别运算
	if (!startRecogFlag) {
		return;
	}

	bool hasFace = ai.isRecognized(); // 判断是否匹配到已录入人脸
	unsigned long nowTime = millis(); // 获取系统运行毫秒数,无阻塞计时

	// ========== 场景1:识别到录入的家人人脸 ==========
	if (hasFace) {
		faceLostTimer = nowTime; // 持续刷新计时,只要人脸在镜头内就重置3秒倒计时
		nowFaceID = ai.getRecognitionID(); // 读取人脸ID

		k10.canvas->canvasClear();
		k10.canvas->canvasText("检测人脸 ID:" + String(nowFaceID), 0, 0, 0x00FF00, k10.canvas->eCNAndENFont24, 50, true);

		// ID=1 老爷专属欢迎提示
		if (nowFaceID == 1.0) {
			k10.canvas->canvasText("欢迎老爷回家!", 0, 40, 0x00FF00, k10.canvas->eCNAndENFont24, 50, true);
			k10.rgb->write(-1, 0x00FF00); // 绿灯常亮
			if (!playFlag) { // 仅第一次识别播放音乐,防止循环重复播放
				music.playMusic(DADADADUM);
				playFlag = true;
			}
		}
		// ID=2 小姐专属欢迎提示
		else if (nowFaceID == 2.0) {
			k10.canvas->canvasText("欢迎小姐回家!", 0, 40, 0x00FF00, k10.canvas->eCNAndENFont24, 50, true);
			k10.rgb->write(-1, 0x00FF00);
			if (!playFlag) {
				music.playMusic(DADADADUM);
				playFlag = true;
			}
		}
		k10.canvas->updateCanvas();
	}
	// ========== 场景2:未识别到人脸(遮挡/离开/陌生人) ==========
	else {
		// 子场景1:人脸消失不足3秒,属于短暂遮挡,保持当前欢迎画面,不切换界面
		if (nowTime - faceLostTimer < FACE_KEEP_DELAY) {
			return;
		}
		// 子场景2:人脸完全离开超过3秒,自动退出识别模式
		startRecogFlag = false; // 关闭识别总开关
		playFlag = false;       // 重置音乐标记,下次识别重新播放
		showStandbyUI();        // 切回干净待机界面,无任何报警提示
	}
}

七、A 按键回调函数:人脸录入功能 onButtonAPressed ()

void onButtonAPressed() {
	k10.canvas->canvasClear();
	k10.canvas->canvasText("采集人脸中,请正对镜头", 0, 0, 0x0066FF, k10.canvas->eCNAndENFont24, 50, true);
	k10.canvas->updateCanvas();

	ai.sendFaceCmd(ENROLL); // 下发AI录入指令:采集人脸特征,自动分配ID
	delay(3000); // 阻塞3秒,给AI充足时间完成人脸采集

	k10.canvas->canvasClear();
	k10.canvas->canvasText("人脸录入完成!", 0, 0, 0x00FF00, k10.canvas->eCNAndENFont24, 50, true);
	k10.canvas->canvasText("按B键开启门禁识别",0,35,0xFFFFFF,k10.canvas->eCNAndENFont24,50,true);
	k10.canvas->updateCanvas();

	delay(1200); // 停留1.2秒,让用户看清录入成功提示
	showStandbyUI(); // 录入结束自动返回待机界面
}

八、B 按键回调函数:开启人脸识别 onButtonBPressed ()

void onButtonBPressed() {
	startRecogFlag = true;          // 打开识别总开关,loop开始执行人脸检测
	faceLostTimer = millis();       // 初始化人脸丢失计时,启动3秒缓冲倒计时
	ai.sendFaceCmd(RECOGNIZE);      // 下发AI比对指令,实时匹配人脸库

	k10.canvas->canvasClear();
	k10.canvas->canvasText("门禁识别已启动", 0, 0, 0x0066FF, k10.canvas->eCNAndENFont24, 50, true);
	k10.canvas->canvasText("正在实时识别人脸",0,35,0xFFFFFF,k10.canvas->eCNAndENFont24,50,true);
	k10.canvas->updateCanvas();
	delay(1000); // 启动提示界面停留1秒,之后进入实时识别
}

九、整体运行流程总结
开机:直接待机,屏幕只显示操作指引,彩灯熄灭,无识别、无报警文字;
按 A 键:录入人脸,3 秒采集完成,1.2 秒后自动回到待机;
按 B 键:启动人脸识别工作模式,摄像头实时比对人脸;
识别到 ID1 老爷 / ID2 小姐:屏幕显示专属欢迎文字、绿灯常亮、仅播放一次欢迎音乐;
人脸短暂遮挡、转头、挡脸(3 秒内):画面不跳转,持续保留欢迎界面;
人脸完全离开镜头超过 3 秒:自动关闭识别,切回干净待机界面,无红灯、无陌生人警告;
如需再次识别,必须重新按下 B 键启动识别。

Mind+图形编程(仅供参考)

在这里插入图片描述
实际测试的人脸图片(来源网络)

在这里插入图片描述
在这里插入图片描述

实验场景图与视频记录

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐