diff --git a/api/exam.pt b/api/exam.pt
new file mode 100644
index 0000000..aa344f4
Binary files /dev/null and b/api/exam.pt differ
diff --git a/api/main.py b/api/main.py
index 0dfb193..7175416 100644
--- a/api/main.py
+++ b/api/main.py
@@ -1,8 +1,13 @@
from flask import Flask, request, jsonify
from pymongo import MongoClient
+from ultralytics import YOLO
+from PIL import Image
+import base64
+from io import BytesIO
from bson import ObjectId
import hashlib
import json
+import os
from flask import Flask, request
from flask_socketio import SocketIO, emit, join_room, leave_room
import time
@@ -20,6 +25,12 @@ clients = []
adminSid = ""
# 初始化考试状态
studentStatus = {}
+current_dir = os.path.dirname(os.path.abspath(__file__))
+weights = os.path.join(current_dir, "exam.pt")
+print(89744, weights)
+model = YOLO(weights)
+frame_rate_divider = 300 # 设置帧率除数
+frame_count = 0 # 初始化帧计数器
def dealStudentStatus():
@@ -60,12 +71,50 @@ def handle_video_frame(message):
# 广播视频帧给老师
global adminSid
global studentStatus
+ global model
+ global frame_rate_divider
+ global frame_count
+
# print(f"Received video frame from {message['userId']}")
socketio.emit(
"teacherVideo" + message["userId"], message, to=adminSid, namespace="/ws/video"
)
- if studentStatus[message["userId"]]:
- print(f"学生{message['userId']}已作弊", f"{studentStatus[message['userId']]}")
+ if frame_count % frame_rate_divider == 0:
+ # 这里省略了实际的base64数据
+ base64_str = message["data"]
+ # 解码base64字符串
+ _, img_data = base64_str.split(",")
+ img_data = base64.b64decode(img_data)
+ # 将字节流转换为PIL图像对象
+ image = Image.open(BytesIO(img_data))
+ results = model.predict(source=image, iou=0.5, conf=0.25)
+ det = results[0]
+ checkVedioResult(det)
+ frame_count += 1 # 更新帧计数器
+ frame_count %= frame_rate_divider # 更新帧计数器
+ # print(99777,frame_count)
+ # if studentStatus[message["userId"]]:
+ # print(f"学生{message['userId']}已作弊", f"{studentStatus[message['userId']]}")
+
+
+def checkVedioResult(det):
+ # 如果有有效的检测结果
+ # {"cheating": "疑似作弊", "good": "良好", "normal": "正常"}
+ if det is not None and len(det):
+ results = [] # 初始化结果列表
+ for res in det.boxes:
+ for box in res:
+ # 提前计算并转换数据类型
+ class_id = int(box.cls.cpu())
+ bbox = box.xyxy.cpu().squeeze().tolist()
+ bbox = [int(coord) for coord in bbox] # 转换边界框坐标为整数
+ result = {
+ "bbox": bbox, # 边界框
+ "score": box.conf.cpu().squeeze().item(), # 置信度
+ "class_id": class_id, # 类别ID
+ }
+ results.append(result) # 将结果添加到列表
+ print(587744, results)
@socketio.on("talk", namespace="/ws/video")
@@ -241,6 +290,7 @@ def insert_data():
"banji": userJson["banji"],
"xueshengxingming": userJson["xueshengxingming"],
"xuehao": userJson["xuehao"],
+ "kaoshengtupian": userJson["kaoshengtupian"],
"mima": md5_encrypt(userJson["mima"]),
"chengji": userJson["chengji"],
"zuobiqingkuang": userJson["zuobiqingkuang"],
@@ -310,6 +360,7 @@ def update_data():
"banji": userJson["banji"],
"xueshengxingming": userJson["xueshengxingming"],
"xuehao": userJson["xuehao"],
+ "kaoshengtupian": userJson["kaoshengtupian"],
"chengji": userJson["chengji"],
"zuobiqingkuang": userJson["zuobiqingkuang"],
"kaoshileixing": userJson["kaoshileixing"],
diff --git a/front/src/api/teacher.js b/front/src/api/teacher.js
index 71f7812..46af355 100644
--- a/front/src/api/teacher.js
+++ b/front/src/api/teacher.js
@@ -51,3 +51,11 @@ export function updatePassword(data = {}) {
data: { ...data, id: localStorage.getItem("userId") },
});
}
+//查找作弊信息
+export function getzuobi(data = {}) {
+ return _axios({
+ url: `/v1/getzuobi`,
+ method: "POST",
+ data: { id: localStorage.getItem("userId"), ...data },
+ });
+}
\ No newline at end of file
diff --git a/front/src/component/changeItem.vue b/front/src/component/changeItem.vue
index e76fd48..6e75dfa 100644
--- a/front/src/component/changeItem.vue
+++ b/front/src/component/changeItem.vue
@@ -13,7 +13,24 @@
:end-placeholder="headerItem.endplaceholder" width="330px" />
- {{ formData[headerItem.prop] }}
+ {{ formData[headerItem.prop] }}
+ 无
+
+
+
+
+ 修改
+ 新增
+ 图片
+
+
+
+
+
+
+
@@ -52,7 +69,35 @@ export default {
async mounted() { },
beforeUnmount() { },
- methods: {},
+ methods: {
+ /**
+* 上传检查图片
+*/
+ beforeAvatarUpload(rawFile) {
+ let imgList = ["image/jpeg", "image/png"]
+ if (imgList.indexOf(rawFile.type) === -1) {
+ this.$msgbox.alert('请上传.png,.jpg,.jpeg格式的图片!')
+ return false
+ } else if (rawFile.size / 1024 / 1024 > 50) {
+ this.$msgbox.alert('图片文件的大小为小于50MB,过大时会处理过慢')
+ return true
+ }
+ return true
+ },
+ //上传图片保存
+ async successSubmit(opts) {
+ let that = this
+ let file = opts.file
+ let fileReader = new FileReader()
+ fileReader.onload = async function (e) {
+ that.formData["kaoshengtupian"] = e.target.result
+ }
+ fileReader.onerror = function (error) {
+ console.error('Error reading file:', error)
+ }
+ fileReader.readAsDataURL(file)
+ },
+ },
};
diff --git a/front/src/component/table.vue b/front/src/component/table.vue
index 4b1b183..1f54f2c 100644
--- a/front/src/component/table.vue
+++ b/front/src/component/table.vue
@@ -25,6 +25,13 @@
+
+
+
+
+
******
{{ scope.row[headerItem.prop] }}
@@ -101,8 +108,9 @@ export default {