This week, I continued to work on my project's WebUI. I wrote the instruction page and the face recognition page.
Here is my code👇
about.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>关于此项目</title>
<link rel="stylesheet" href="../static/home.css">
</head>
<body>
<div class="container">
<h1 id="title">关于此项目</h1>
<p id="description">本系统由宁波赫德KAINGMING班的Jackson搭建</p>
<p id="moreInfo">该项目使用计算机视觉算法,来帮助我们的用户进行大规模的视力筛查</p>
<button class="btn" id="backButton" onclick="goBack()">返回首页</button>
</div>
<script>
// 获取 URL 中的语言参数
const urlParams = new URLSearchParams(window.location.search);
const lang = urlParams.get('lang');
// 切换语言
function switchLanguage() {
const title = document.getElementById("title");
const description = document.getElementById("description");
const moreInfo = document.getElementById("moreInfo");
const backButton = document.getElementById("backButton");
if (lang === 'en') {
title.textContent = "About This Project";
description.textContent = "This system was built by Jackson from HDNB KAINGMING class";
moreInfo.textContent = "This project uses computer vision algorithms to help our users conduct large-scale vision screening";
backButton.textContent = "Back to Home";
} else {
title.textContent = "关于此项目";
description.textContent = "本系统由宁波赫德KAINGMING班的Jackson搭建";
moreInfo.textContent = "该项目使用计算机视觉算法,来帮助我们的用户进行大规模的视力筛查";
backButton.textContent = "返回首页";
}
}
// 页面加载时切换语言
window.onload = switchLanguage;
// 返回首页函数
function goBack() {
const url = lang === 'en' ? "/?lang=en" : "/?lang=zh";
window.location.href = url;
}
</script>
</body>
</html>
faceRecognition.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>人脸识别</title>
<style>
/* 设置页面的背景色和字体 */
body {
background: #ffffff;
/* 纯白背景 */
font-family: 'Arial', sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
margin: 0;
color: #2d572c;
/* 绿色文字 */
text-align: center;
}
/* 设置标题的样式 */
p {
font-size: 2rem;
font-weight: bold;
margin-bottom: 20px;
border-bottom: 3px solid #2d572c;
/* 绿色下划线 */
display: inline-block;
padding-bottom: 5px;
animation: fadeIn 1.5s ease-out;
}
/* 盒子设计 */
.image-container {
background: #ffffff;
padding: 15px;
border-radius: 15px;
border: 3px solid #2d572c;
/* 绿色边框 */
box-shadow: 0 5px 15px rgba(45, 87, 44, 0.2);
/* 绿色阴影 */
transition: transform 0.3s ease-in-out;
}
.image-container:hover {
transform: scale(1.02);
}
/* 让图片更有质感 */
#faceImage {
border-radius: 10px;
width: 100%;
max-width: 500px;
height: auto;
box-shadow: 0 8px 15px rgba(45, 87, 44, 0.2);
transition: opacity 0.5s ease-in-out;
opacity: 0;
}
/* 图片加载时的渐变效果 */
#faceImage.loaded {
opacity: 1;
}
/* 标题和内容淡入效果 */
@keyframes fadeIn {
0% {
opacity: 0;
transform: translateY(-20px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
</style>
</head>
<body>
<p id="title">第一步:人脸识别</p>
<div class="image-container">
<img id="faceImage" src="../static/image/temp.jpeg?timestamp=0" alt="人脸识别">
</div>
<script>
let lastSuccessfulSrc = "../static/image/temp.jpeg?timestamp=0"; // 记录最后一张成功加载的图片
function updateImage() {
const imgElement = document.getElementById('faceImage');
const timestamp = new Date().getTime();
const newSrc = `../static/image/temp.jpeg?timestamp=${timestamp}`;
// 创建新的 Image 对象预加载
const tempImg = new Image();
tempImg.src = newSrc;
tempImg.onload = function () {
// 加载成功后,更新图片
lastSuccessfulSrc = newSrc;
imgElement.classList.remove('loaded');
imgElement.src = newSrc;
imgElement.classList.add('loaded');
};
tempImg.onerror = function () {
console.error("图片加载失败,保留上一帧");
imgElement.src = lastSuccessfulSrc; // 加载失败时,保持上一帧
};
}
setInterval(updateImage, 500); // 每0.5秒更新一次图片
// 页面首次加载时,确保图片显示出来
window.onload = function () {
setTimeout(function () {
document.getElementById('faceImage').classList.add('loaded');
}, 100);
}
// 获取 URL 中的语言参数
const urlParams = new URLSearchParams(window.location.search);
const lang = urlParams.get('lang');
// 切换语言
function switchLanguage() {
const title = document.getElementById("title");
if (lang === 'en') {
title.textContent = "Step 1: Face recognition";
} else {
title.textContent = "第一步:人脸识别";
}
}
// 页面加载时切换语言
window.onload = switchLanguage;
</script>
</body>
</html>
home.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>自动测视力系统</title>
<link rel="stylesheet" href="../static/home.css">
</head>
<body>
<button class="language-switcher" id="languageSwitcher" onclick="toggleLanguage()">中文</button>
<button class="about-button" id="aboutButton" onclick="goToAboutPage()">关于此项目</button>
<div class="container">
<h1 id="title">欢迎使用自动测视力系统</h1>
<p id="description">本系统将帮助您检测视力,提供专业的测试方法和建议。</p>
<button class="btn" id="startButton" onclick="goToIntroductionPage()">开始测试</button>
</div>
<script>
let isChinese = true; // 默认语言为中文
// 切换语言函数
function toggleLanguage() {
isChinese = !isChinese;
const title = document.getElementById("title");
const description = document.getElementById("description");
const startButton = document.getElementById("startButton");
const languageSwitcher = document.getElementById("languageSwitcher");
const aboutButton = document.getElementById("aboutButton");
// 添加旋转动画类
languageSwitcher.classList.add('animate');
aboutButton.classList.add('animate');
// 动画结束后移除旋转动画类,确保动画只触发一次
setTimeout(() => {
languageSwitcher.classList.remove('animate');
aboutButton.classList.remove('animate');
}, 500); // 旋转动画持续时间是 500ms
if (isChinese) {
title.textContent = "欢迎使用自动测视力系统";
description.textContent = "本系统使用计算机视觉算法来自动测量视力";
startButton.textContent = "开始测试";
languageSwitcher.textContent = "中文";
aboutButton.textContent = "关于此项目";
} else {
title.textContent = "Welcome to the Automated Vision Test System";
description.textContent = "This system uses computer vision algorithm to measure vision automatically";
startButton.textContent = "Start Test";
languageSwitcher.textContent = "English";
aboutButton.textContent = "About This Project"; // 英文界面下的文本
}
}
// 跳转到关于页面,并传递当前语言信息
function goToAboutPage() {
const url = isChinese ? "/about?lang=zh" : "/about?lang=en";
window.location.href = url;
}
function goToIntroductionPage() {
const url = isChinese ? "/introduction?lang=zh" : "/introduction?lang=en";
window.location.href = url;
}
</script>
</body>
</html>
introduction.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>关于此项目</title>
<link rel="stylesheet" href="../static/home.css">
</head>
<body>
<div class="container">
<h1 id="title">准备开始</h1>
<p id="description">稍后我们将展示测试视力的图标</p>
<p id="moreInfo">请将手放在摄像机可以捕捉到的位置,并指向对应的方向</p>
<button class="btn" id="backButton" onclick="startTest()">返回首页</button>
</div>
<script>
// 获取 URL 中的语言参数
const urlParams = new URLSearchParams(window.location.search);
const lang = urlParams.get('lang');
// 切换语言
function switchLanguage() {
const title = document.getElementById("title");
const description = document.getElementById("description");
const moreInfo = document.getElementById("moreInfo");
const backButton = document.getElementById("backButton");
if (lang === 'en') {
title.textContent = "Ready to start";
description.textContent = "Later we will show you the icon to test your eyesight";
moreInfo.textContent = "Please place your hand where the camera can capture it and point it in the corresponding direction";
backButton.textContent = "Understood!";
} else {
title.textContent = "准备开始";
description.textContent = "稍后我们将展示测试视力的图标";
moreInfo.textContent = "请将手放在摄像机可以捕捉到的位置,并指向对应的方向";
backButton.textContent = "了解!";
}
}
// 页面加载时切换语言
window.onload = switchLanguage;
// 返回首页函数
function startTest() {
const url = lang === 'en' ? "/face?lang=en" : "/face?lang=zh";
window.location.href = url;
}
</script>
</body>
</html>
home.css
/* 通用样式 */
body,
html {
height: 100%;
margin: 0;
font-family: 'Arial', sans-serif;
display: flex;
justify-content: center;
align-items: center;
background: #f2f2f2;
overflow: hidden;
}
.container {
text-align: center;
background: #fff;
border-radius: 15px;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
padding: 50px 30px;
width: 80%;
max-width: 500px;
animation: fadeIn 2s ease-in-out;
}
/* 标题样式 */
h1 {
font-size: 36px;
color: #4CAF50;
animation: slideInFromTop 1s ease-out;
}
/* 动画效果:从上方滑入 */
@keyframes slideInFromTop {
0% {
transform: translateY(-50px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
/* 动画效果:淡入 */
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
/* 按钮样式 */
.btn {
background-color: #4CAF50;
color: white;
border: none;
padding: 15px 30px;
font-size: 18px;
border-radius: 10px;
cursor: pointer;
margin-top: 20px;
transition: background-color 0.3s ease;
}
.btn:hover {
background-color: #45a049;
}
/* 按钮浮动动画 */
.btn:hover {
animation: bounce 0.5s infinite alternate;
}
@keyframes bounce {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-10px);
}
}
/* 语言切换按钮和关于按钮样式 */
.language-switcher,
.about-button {
position: absolute;
top: 20px;
background-color: #fff;
border: 1px solid #ccc;
padding: 5px 10px;
border-radius: 5px;
cursor: pointer;
transition: transform 0.3s ease, background-color 0.3s ease;
}
/* 语言切换按钮点击时的动画效果 */
.language-switcher:active,
.about-button:active {
transform: scale(0.95);
background-color: #f0f0f0;
}
/* 按钮旋转的动画效果 */
@keyframes rotateEffect {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.language-switcher.animate,
.about-button.animate {
animation: rotateEffect 0.5s ease-in-out;
}
/* 设置按钮的具体位置 */
.language-switcher {
right: 150px;
/* 调整间距,增加按钮之间的距离 */
}
.about-button {
right: 20px;
}
In this week, I had a big trouble about how to embed the images captured by the Raspberry Pi camera into my webpage in real time, I tried the WebRTC framework from Google, but it is too hard for me. In the end, I use a very stupid way to solve this problem: The Raspberry Pi takes a frame from the camera. First save the frame to the hard disk, let the web display the picture and refresh it in real time. Although this frame rate is a little lower and the performance overhead is much greater, it has also achieved the expected goal. After the project is completed, during the optimization stage, I need to adopt a more efficient solution.
And here is the result👇