news 2026/3/11 15:12:38

编写儿童视力保护辅助程序,通过电脑摄像头实时检测坐姿,屏幕距离,超过安全阀值发出警报,统计每天健康用眼时长。

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
编写儿童视力保护辅助程序,通过电脑摄像头实时检测坐姿,屏幕距离,超过安全阀值发出警报,统计每天健康用眼时长。

代码实现(HTML+JavaScript整合版)

<!DOCTYPE html>

<html lang="zh-CN">

<head>

<meta charset="UTF-8">

<title>儿童视力保护辅助程序</title>

<style>

body { font-family: Arial, sans-serif; margin: 0; padding: 20px; display: flex; flex-direction: column; align-items: center; }

.container { max-width: 800px; width: 100%; }

video, canvas { width: 100%; max-width: 640px; border: 1px solid #ccc; margin-bottom: 10px; }

.stats { margin: 20px 0; padding: 10px; border: 1px solid #eee; border-radius: 5px; }

.alert { color: red; font-weight: bold; margin: 10px 0; display: none; }

button { padding: 10px 20px; background: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer; }

button:hover { background: #0056b3; }

</style>

</head>

<body>

<div class="container">

<h1>儿童视力保护辅助程序</h1>

<button id="startBtn">启动检测</button>

<div class="alert" id="alertBox"></div>

<video id="video" autoplay playsinline></video>

<canvas id="canvas"></canvas>

<div class="stats">

<p>今日健康用眼时长:<span id="healthyTime">0</span> 分钟</p>

<p>当前状态:<span id="currentStatus">未启动</span></p>

</div>

</div>

<!-- 引入TensorFlow.js与BlazePose模型 -->

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-core"></script>

<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/blazepose"></script>

<script>

// 全局变量

const video = document.getElementById('video');

const canvas = document.getElementById('canvas');

const ctx = canvas.getContext('2d');

const alertBox = document.getElementById('alertBox');

const healthyTimeEl = document.getElementById('healthyTime');

const currentStatusEl = document.getElementById('currentStatus');

const startBtn = document.getElementById('startBtn');

let model = null;

let isDetecting = false;

let healthyStartTime = null;

let dailyHealthyTime = 0; // 当日健康时长(秒)

const DISTANCE_THRESHOLD = 50; // 安全距离阈值(cm,小于则警报)

const POSTURE_ANGLE_THRESHOLD = 15; // 坐姿倾斜阈值(度,大于则警报)

// 1. 初始化摄像头

async function initCamera() {

try {

const stream = await navigator.mediaDevices.getUserMedia({ video: true });

video.srcObject = stream;

return new Promise((resolve) => {

video.onloadedmetadata = () => resolve();

});

} catch (err) {

throw new Error('摄像头访问失败:' + err.message);

}

}

// 2. 加载BlazePose姿势检测模型

async function loadModel() {

try {

model = await blazepose.load();

console.log('模型加载完成');

} catch (err) {

throw new Error('模型加载失败:' + err.message);

}

}

// 3. 计算眼睛到屏幕的距离(简化:用头部宽度估算)

function calculateDistance(keypoints) {

// 获取双眼关键点(BlazePose索引:33=左眼,263=右眼)

const leftEye = keypoints[33];

const rightEye = keypoints[263];

if (!leftEye || !rightEye) return Infinity;

// 计算两眼间距(像素)

const eyeDistancePx = Math.sqrt(

Math.pow(rightEye.x - leftEye.x, 2) + Math.pow(rightEye.y - leftEye.y, 2)

);

// 经验公式:实际距离(cm) ≈ (已知眼距cm × 图像宽度px) / 眼距px(假设已知成人眼距约6.5cm)

const knownEyeDistanceCm = 6.5;

const imageWidthPx = video.videoWidth;

return (knownEyeDistanceCm * imageWidthPx) / eyeDistancePx;

}

// 4. 检查坐姿(计算肩膀倾斜角度)

function checkPosture(keypoints) {

// 获取左右肩关键点(索引:11=左肩,12=右肩)

const leftShoulder = keypoints[11];

const rightShoulder = keypoints[12];

if (!leftShoulder || !rightShoulder) return 0;

// 计算肩膀连线与水平线的夹角(度)

const dx = rightShoulder.x - leftShoulder.x;

const dy = rightShoulder.y - leftShoulder.y;

const angle = Math.atan2(dy, dx) * (180 / Math.PI);

return Math.abs(angle); // 返回绝对值(倾斜程度)

}

// 5. 触发警报(视觉+听觉)

function triggerAlert(message) {

alertBox.textContent = message;

alertBox.style.display = 'block';

// 播放提示音(用浏览器内置音频)

const audio = new Audio('data:audio/wav;base64,UklGRnoGAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQoGAACBhYqMkJKTlZaXmJmam5ydnp+goaKjpKWmp6ipqqusra6vsLGys7S1tre4ubq7vL2+v8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+Pn6+/z9/v8AAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4CBgoOEhYaHiImKi4yNjo+QkZKTlJWWl5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3+Dh4uPk5ebn6Onq6+zt7u/w8fLz9PX29/j5+vv8/f7/');

audio.play().catch(() => {}); // 忽略自动播放限制错误

setTimeout(() => alertBox.style.display = 'none', 3000);

}

// 6. 更新健康用眼时长(localStorage存储每日数据)

function updateHealthyTime(isHealthy) {

const now = Date.now();

if (isHealthy) {

if (!healthyStartTime) healthyStartTime = now;

} else {

if (healthyStartTime) {

dailyHealthyTime += (now - healthyStartTime) / 1000; // 转为秒

healthyStartTime = null;

}

}

// 存储到localStorage(按日期分割)

const today = new Date().toISOString().split('T')[0];

localStorage.setItem(`healthyTime_${today}`, dailyHealthyTime.toString());

// 更新UI(转为分钟)

healthyTimeEl.textContent = Math.floor(dailyHealthyTime / 60);

}

// 7. 实时检测循环

async function detectLoop() {

if (!isDetecting) return;

// 绘制视频帧到画布

canvas.width = video.videoWidth;

canvas.height = video.videoHeight;

ctx.drawImage(video, 0, 0, canvas.width, canvas.height);

try {

// 检测姿势关键点

const predictions = await model.estimatePoses(canvas);

if (predictions.length > 0) {

const keypoints = predictions[0].keypoints;

// 计算距离与坐姿

const distance = calculateDistance(keypoints);

const postureAngle = checkPosture(keypoints);

// 判断是否健康

const isDistanceOk = distance >= DISTANCE_THRESHOLD;

const isPostureOk = postureAngle <= POSTURE_ANGLE_THRESHOLD;

const isHealthy = isDistanceOk && isPostureOk;

// 更新状态与统计

currentStatusEl.textContent = isHealthy ? '健康' : '需注意';

currentStatusEl.style.color = isHealthy ? 'green' : 'red';

updateHealthyTime(isHealthy);

// 超阈值警报

if (!isDistanceOk) triggerAlert(`距离过近!当前约${Math.round(distance)}cm(建议≥${DISTANCE_THRESHOLD}cm)`);

if (!isPostureOk) triggerAlert(`坐姿倾斜!当前${Math.round(postureAngle)}°(建议≤${POSTURE_ANGLE_THRESHOLD}°)`);

}

} catch (err) {

console.error('检测错误:', err);

}

// 下一帧

requestAnimationFrame(detectLoop);

}

// 启动检测

startBtn.addEventListener('click', async () => {

if (isDetecting) return;

try {

await initCamera();

await loadModel();

isDetecting = true;

startBtn.disabled = true;

currentStatusEl.textContent = '检测中...';

detectLoop();

// 加载当日已存时长

const today = new Date().toISOString().split('T')[0];

dailyHealthyTime = parseFloat(localStorage.getItem(`healthyTime_${today}`)) || 0;

healthyTimeEl.textContent = Math.floor(dailyHealthyTime / 60);

} catch (err) {

alert('启动失败:' + err.message);

}

});

</script>

</body>

</html>

README文件

# 儿童视力保护辅助程序

## 简介

通过电脑摄像头实时检测儿童坐姿(肩膀倾斜≤15°)与屏幕距离(≥50cm),超阈值时弹窗+声音警报,统计每日健康用眼时长(localStorage存储)。

## 安装与使用

1. **环境要求**:现代浏览器(Chrome/Firefox)、摄像头权限。

2. **启动方式**:直接打开`index.html`(建议用本地服务器避免跨域,如`npx http-server`)。

3. **操作流程**:

- 点击「启动检测」→ 允许摄像头访问;

- 程序自动检测,下方显示实时状态与健康时长;

- 超阈值时弹出红色警报(3秒后消失)。

## 核心模块

| 模块名 | 功能 |

|-----------------|-----------------------------------|

| initCamera | 初始化摄像头视频流 |

| loadModel | 加载BlazePose姿势检测模型 |

| calculateDistance | 用头部大小估算屏幕距离(cm) |

| checkPosture | 计算肩膀倾斜角度(度) |

| triggerAlert | 视觉+听觉警报(弹窗+提示音) |

| updateHealthyTime | 统计健康时长(localStorage存储) |

## 依赖说明

- TensorFlow.js Core(CDN引入);

- BlazePose模型(CDN引入,用于姿势检测)。

使用说明

1. 准备工作:确保电脑有可用摄像头,浏览器开启摄像头权限(地址栏锁图标→允许)。

2. 启动程序:双击

"index.html"打开页面,点击「启动检测」按钮。

3. 阈值调整:如需修改安全距离(默认50cm)或坐姿倾斜度(默认15°),直接修改代码中

"DISTANCE_THRESHOLD"和

"POSTURE_ANGLE_THRESHOLD"的值。

4. 数据查看:健康时长存储在浏览器

"localStorage"中,按日期分割(键名如

"healthyTime_2025-12-17")。

核心知识点卡片

1. 模块化设计

- 定义:将程序拆分为独立功能模块(摄像头、检测、警报、统计),降低耦合度。

- 应用:本程序用

"initCamera"/

"loadModel"等函数拆分功能,便于维护。

- 关联课程:战略管理中的分工协作(各模块专注单一目标)。

2. 实时计算机视觉

- 定义:用BlazePose模型实时检测人体关键点(眼睛、肩膀),分析姿势。

- 应用:估算屏幕距离(眼距像素→实际距离)、判断坐姿(肩膀倾斜角度)。

- 关联课程:创新思维中的技术赋能(用AI解决传统监测痛点)。

3. 阈值管理

- 定义:设定安全边界(如距离≥50cm、倾斜≤15°),超界触发反馈。

- 应用:本程序用常量定义阈值,清晰可控。

- 关联课程:战略管理中的目标设定与风险控制。

4. 用户体验反馈

- 定义:通过视觉(红底弹窗)+听觉(提示音)及时提醒,强化正确行为。

- 应用:超阈值时

"triggerAlert"函数触发双模态反馈。

- 关联课程:创新思维中的用户中心设计。

5. 数据驱动的持续改进

- 定义:用

"localStorage"记录每日健康时长,帮助用户跟踪进展。

- 应用:统计时长并在UI展示,支持长期视力保护。

- 关联课程:战略管理中的复盘与迭代。

关注我,有更多编程干货等着你!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/5 10:30:18

【学习心得】Python好库推荐——pyttsx3

pyttsx3&#xff08;Python Text-to-Speech eXtended version 3&#xff09;是一个跨平台的 Python 库&#xff0c;用于将文本转换为语音&#xff08;Text-to-Speech, TTS&#xff09;。它可以在不依赖互联网连接的情况下&#xff0c;在本地将文本朗读出来&#xff0c;支持 Win…

作者头像 李华
网站建设 2026/3/8 20:08:08

Linux 通用软件包 AppImage 打包详解

格式介绍 - AppImageAppImage 是 Linux 系统中一种新型的软件包格式&#xff0c;它与 rpm、deb 这些软件包格式相比最大的不同便是&#xff1a;&#xff08;1&#xff09;无需安装&#xff0c;即用即删。&#xff08;2&#xff09;只需打包一次&#xff0c;便可到处运行。完美的…

作者头像 李华
网站建设 2026/3/4 20:54:15

软件测试工具选型全景指南:从需求对齐到落地实践

为什么工具选型关乎测试成败 在快速迭代的软件开发周期中&#xff0c;测试工具已从辅助手段演进为质量保障的核心基础设施。据统计&#xff0c;超过67%的测试团队曾因工具选型不当导致项目延期或质量漏洞。2025年测试工具生态呈现两大趋势&#xff1a;AI驱动的智能测试平台快速…

作者头像 李华
网站建设 2026/3/5 21:26:16

自动化测试投资回报率(ROI)分析与实践指南

在软件开发周期不断缩短的当下&#xff0c;自动化测试已成为保障产品质量、提升测试效率的关键手段。然而&#xff0c;许多测试团队在推行自动化测试时面临共同困惑&#xff1a;如何量化自动化测试的投入产出比&#xff1f;本文将从测试从业者视角&#xff0c;深入解析自动化测…

作者头像 李华
网站建设 2026/3/5 12:51:28

企业微信群消息定时发送竟然这么简单?三步搞定让效率翻倍!

你是不是还在手动发送每天的晨会提醒&#xff1f;或者每到下班时间就急着往群里发日报&#xff1f;别折腾了&#xff0c;现在有个方法能让你彻底解放双手。想想看&#xff0c;每天固定要发的通知、报表、提醒&#xff0c;如果都能自动完成&#xff0c;那该多省心啊。连趣云控制…

作者头像 李华