123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- <template>
- <div class="videoContainer">
- <video
- ref="video"
- id="video"
- :width="1280"
- :height="800"
- autoplay
- muted
- playsinline
- ></video>
- <div id="timestamp" v-show="false">
- {{ datetimeData.date + " " + datetimeData.time }}
- </div>
- <canvas id="blurred-canvas" :width="1280" :height="800"></canvas>
- <!-- <el-button @click="startCamera">开启摄像头</el-button>
- <el-button @click="stopCamera" :disabled="!isCameraActive"
- >关闭摄像头</el-button
- > -->
- </div>
- </template>
- <script>
- /* eslint-disable */
- import * as tf from "@tensorflow/tfjs";
- import * as bodyPix from "@tensorflow-models/body-pix";
- import { GetPersonByFace, GetPersonByFaceBase64 } from "@/API/custom";
- import Dayjs from "dayjs";
- export default {
- props: {
- processStep: {
- type: String,
- require: true,
- },
- isUpload: {
- type: String,
- require: false,
- },
- cameraData: {
- type: Object,
- default: () => ({}),
- },
- },
- watch: {
- processStep: {
- handler(step) {
- if (step == 0 || step == 9) {
- this.startCamera();
- } else {
- this.stopCamera();
- }
- },
- deep: true,
- immediate: true,
- },
- isUpload: {
- handler(val) {
- console.log("上传子级开关", val);
- if (val) {
- this.uploadImage();
- } else {
- this.isUpload = false;
- }
- },
- deep: true,
- immediate: true,
- },
- },
- data() {
- return {
- isCameraActive: false,
- video: null,
- stream: null,
- captureInterval: null, // 新增定时器变量
- datetimeData: {
- date: Dayjs(new Date()).format("YYYY-MM-DD"),
- time: Dayjs(new Date()).format("HH:mm:ss"),
- week: Dayjs(new Date()).format("dddd"),
- },
- // BodyPix模型加载
- net: null,
- localModelPath: "/js/model/bodypix/model-stride16.json",
- // 修改默认值为 true,自动开启背景虚化
- showBlurred: true,
- loading: true,
- };
- },
- methods: {
- refreshTime() {
- let speed = 1000;
- let timer = null;
- let theNowTime = () => {
- // this.datePersonData.time = Dayjs(new Date()).format('HH:mm:ss')
- this.datetimeData.time = Dayjs(new Date()).format("HH:mm:ss");
- this.datetimeData.date = Dayjs(new Date()).format("YYYY-MM-DD");
- this.datetimeData.week = Dayjs(new Date()).format("dddd");
- };
- timer = setInterval(theNowTime, speed);
- this.$once("hook:beforeDestroy", () => {
- clearInterval(timer);
- timer = null;
- });
- },
- async loadBodyPix() {
- this.net = await bodyPix.load({ modelUrl: this.localModelPath });
- console.log("BodyPix模型加载返回", this.net);
- this.processVideoFrame();
- },
- async processVideoFrame() {
- // 确保 video 和 blurredCanvas 存在
- if (this.showBlurred && this.video && this.blurredCanvas) {
- try {
- const segmentation = await this.net.segmentPerson(this.video);
- const backgroundBlurAmount = 10;
- const edgeBlurAmount = 3;
- const flipHorizontal = false;
- bodyPix.drawBokehEffect(
- this.blurredCanvas,
- this.video,
- segmentation,
- backgroundBlurAmount,
- edgeBlurAmount,
- flipHorizontal
- );
- } catch (err) {
- console.error("处理视频帧时出错:", err);
- }
- }
- requestAnimationFrame(() => this.processVideoFrame());
- },
- async startCamera() {
- try {
- this.stream = await navigator.mediaDevices.getUserMedia({
- video: true,
- });
- this.video = document.getElementById("video");
- this.isCameraActive = true;
- if (this.video) {
- this.video.srcObject = this.stream;
- this.loading = false;
- this.loadBodyPix();
- } else {
- this.error = "未能找到视频元素,请检查 HTML 结构。";
- this.loading = false;
- }
- if (this.isUpload) {
- setTimeout(() => {
- this.uploadImage();
- }, 1000);
- } else {
- // 新增定时截图功能
- this.captureInterval = setInterval(() => {
- this.captureImage();
- console.log("截图上传");
- }, 2500);
- }
- } catch (err) {
- console.error("摄像头访问错误:", err);
- alert(`摄像头访问失败: ${err.message}`);
- this.loading = false;
- }
- },
- stopCamera() {
- if (this.stream) {
- this.stream.getTracks().forEach((track) => track.stop());
- this.isCameraActive = false;
- this.video.srcObject = null;
- this.stream = null;
- // 停止定时器
- if (this.captureInterval) {
- clearInterval(this.captureInterval);
- this.captureInterval = null;
- }
- }
- },
- async captureImage() {
- if (this.video.paused) return;
- const canvas = document.createElement("canvas");
- const cropWidth = this.video.videoWidth * 0.5;
- const cropHeight = this.video.videoHeight * 0.98;
- // 设置canvas尺寸为选择区域大小
- canvas.width = cropWidth;
- canvas.height = cropHeight;
- const x = (this.video.videoWidth - cropWidth) / 2;
- const y = (this.video.videoHeight - cropHeight) / 2;
- const ctx = canvas.getContext("2d");
- //中心60%区域
- ctx.drawImage(
- this.video,
- x,
- y,
- cropWidth,
- cropHeight,
- 0,
- 0,
- cropWidth,
- cropHeight
- );
- // canvas.width = video.videoWidth;
- // canvas.height = video.videoHeight;
- // const ctx = canvas.getContext("2d");
- // ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
- try {
- const base64Data = canvas.toDataURL("image/png");
- // console.log("上传数据:Base64", base64Data);
- // 替换YOUR_SERVER_URL为你的实际服务器地址
- const response = await fetch(
- "/yapi/System/Person/GetPersonByFaceBase64",
- {
- method: "POST",
- headers: {
- token: localStorage.getItem("token"),
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- data: base64Data,
- fileModule: 2,
- }),
- }
- );
- const result = await response.json();
- // console.log("上传反馈", response, result);
- if (result.code === 20000) {
- // console.log("服务器返回数据:", result);
- this.$emit("output", result.data);
- this.uploadImage();
- // setTimeout(() => {
- // this.stopCamera();
- // }, 200);
- }
- } catch (err) {
- console.error("上传过程中出错:", err);
- }
- },
- async uploadImage() {
- const canvas = document.createElement("canvas");
- const cropWidth = this.video.videoWidth * 0.5;
- const cropHeight = this.video.videoHeight * 0.98;
- // 设置canvas尺寸为选择区域大小
- canvas.width = cropWidth;
- canvas.height = cropHeight;
- const x = (this.video.videoWidth - cropWidth) / 2;
- const y = (this.video.videoHeight - cropHeight) / 2;
- const ctx = canvas.getContext("2d");
- // console.log(
- // "???????????????????",
- // x,
- // y,
- // cropWidth,
- // cropHeight,
- // this.video,
- // this.blurredCanvas,
- // canvas
- // );
- //中心60%区域-原图
- // ctx.drawImage(
- // this.video,
- // x,
- // y,
- // cropWidth,
- // cropHeight,
- // 0,
- // 0,
- // cropWidth,
- // cropHeight
- // );
- // 虚化背景处理绘制
- ctx.drawImage(
- this.showBlurred ? this.blurredCanvas : this.video,
- this.blurredCanvas.width * 0.25,
- this.blurredCanvas.height * 0.01,
- this.blurredCanvas.width * 0.5,
- this.blurredCanvas.height * 0.98,
- 0,
- 0,
- cropWidth,
- cropHeight
- );
- // ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
- const timestampDiv = document.getElementById("timestamp");
- // 在canvas上绘制时间戳
- ctx.font = "24px Arial";
- ctx.fillStyle = "white";
- ctx.fillText(timestampDiv.textContent, 20, canvas.height - 20);
- try {
- const base64Data = canvas.toDataURL("image/png");
- // console.log("上传数据:Base64", base64Data);
- // 替换YOUR_SERVER_URL为你的实际服务器地址
- const response = await fetch("/yapi/File/UploadBase64", {
- method: "POST",
- headers: {
- token: localStorage.getItem("token"),
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- data: base64Data,
- fileModule: 1,
- }),
- });
- const result = await response.json();
- // console.log("上传反馈", response, result);
- if (result.code === 20000) {
- console.log("服务器上传返回数据:", result);
- this.$emit("outputPath", result.data);
- setTimeout(() => {
- this.stopCamera();
- }, 200);
- }
- this.isUpload = false;
- } catch (err) {
- console.error("上传过程中出错:", err);
- }
- },
- },
- mounted() {
- if (this.loading) {
- this.blurredCanvas = document.getElementById("blurred-canvas");
- if (this.blurredCanvas) {
- this.ctx = this.blurredCanvas.getContext("2d");
- }
- }
- },
- created() {
- this.startCamera();
- this.refreshTime();
- },
- beforeDestroy() {
- this.stopCamera();
- },
- };
- </script>
- <style scoped>
- .videoContainer {
- position: relative;
- width: 50%; /* 容器宽度设为50% */
- height: 100%; /* 容器高度设为100% */
- margin: 0 auto; /* 居中显示 */
- overflow: hidden; /* 隐藏溢出部分 */
- }
- video {
- height: 800px;
- width: 1280px;
- transform: translate(-25%, 0%);
- /* width: 100%;
- max-width: 500px; */
- background: #000;
- }
- #timestamp {
- position: absolute;
- bottom: 20px;
- left: 20px;
- color: white;
- font-size: 24px;
- background-color: rgba(0, 0, 0, 0.5);
- padding: 5px;
- }
- #blurred-video {
- display: none;
- }
- </style>
|