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👇