🐛 fixed the logic of judging screenshots

This commit is contained in:
2025-01-23 19:15:36 +08:00
parent 0255e6b75e
commit a2e80b9a91
3 changed files with 54 additions and 46 deletions

View File

@@ -2,11 +2,11 @@ import localforage from 'localforage';
interface UploadPredictResult {
isAnime: boolean;
hasFace: boolean;
objectArray: string[] | unknown[];
landscape: 'building' | 'forest' | 'glacier' | 'mountain' | 'sea' | 'street' | 'none';
isScreenshot: boolean;
topCategory: string | undefined;
exif: object | null;
}
@@ -15,14 +15,13 @@ export const useUploadStore = defineStore(
() => {
const openUploadDrawer = ref<boolean>(false);
const exifData = ref<any>();
const predictResult = reactive<UploadPredictResult>({
isAnime: false,
hasFace: false,
objectArray: [],
landscape: 'none',
isScreenshot: false,
topCategory: ''
topCategory: '',
exif: {}
});
/**
@@ -37,18 +36,17 @@ export const useUploadStore = defineStore(
*/
function clearPredictResult() {
predictResult.isAnime = false;
predictResult.hasFace = false;
predictResult.objectArray = [];
predictResult.landscape = 'none';
predictResult.isScreenshot = false;
predictResult.topCategory = '';
predictResult.exif = {};
}
return {
openUploadDrawer,
predictResult,
exifData,
openUploadDrawerFn,
clearPredictResult,
};

View File

@@ -16,8 +16,11 @@ async function isScreenshot(file) {
'screenshot', '屏幕截图', '截屏', 'Snip', 'Capture', 'Snapshot', '截图'
];
// 获取文件的 MIME 类型
const fileType = file.type.toLowerCase();
try {
// 文件名匹配
// 判断文件名是否包含截图相关关键词
const fileName = file.name.toLowerCase();
const matchesFilename = screenshotFilenameKeywords.some(keyword =>
fileName.includes(keyword.toLowerCase())
@@ -26,7 +29,11 @@ async function isScreenshot(file) {
return true; // 如果文件名包含截图相关关键词,直接判断为截图
}
// 提取 EXIF 数据
// 判断文件类型是否为支持的格式
const isSupportedFormat = ['image/jpeg', 'image/tiff', 'image/heif', 'image/png'].includes(fileType);
if (isSupportedFormat) {
// 如果是支持的格式,提取 EXIF 数据
const exifData = await exifr.parse(file, ['ImageWidth', 'ImageHeight', 'Software', 'XResolution', 'YResolution']);
const {ImageWidth, ImageHeight, Software} = exifData || {};
@@ -55,16 +62,15 @@ async function isScreenshot(file) {
return true;
}
}
}
// 无 EXIF 数据或不匹配时,通过宽高比的容差检测
const img: any = await getImageDimensions(file);
const imgAspectRatio = img.width / img.height;
const imgMatchesAspectRatio = commonAspectRatios.some(
return commonAspectRatios.some(
(ratio) => Math.abs(ratio - imgAspectRatio) <= aspectRatioTolerance
);
return imgMatchesAspectRatio;
} catch (error) {
console.error('判断截图时发生错误:', error);
return false;

View File

@@ -21,6 +21,8 @@
:disabled="predicting"
:progress="progress"
@remove="removeFile"
@reject="rejectFile"
:openFileDialogOnClick="true"
accept="image/*"
list-type="picture"
method="post"
@@ -52,7 +54,6 @@ import i18n from "@/locales";
import {NSFWJS} from "nsfwjs";
import {animePredictImagePro} from "@/utils/tfjs/anime_classifier_pro.ts";
import {fnDetectFace} from "@/utils/tfjs/face_extraction.ts";
import {cocoSsdPredict} from "@/utils/tfjs/mobilenet.ts";
import {predictLandscape} from "@/utils/tfjs/landscape_recognition.ts";
import {useRequest} from 'alova/client';
@@ -92,8 +93,9 @@ const progress: UploadProps['progress'] = {
/**
* 图片上传前的校验
* @param file
* @param fileList
*/
async function beforeUpload(file: File) {
async function beforeUpload(file: File, fileList: File[]) {
predicting.value = true;
upload.clearPredictResult();
progressPercent.value = 0; // 初始化进度条
@@ -132,16 +134,18 @@ async function beforeUpload(file: File) {
if (isNSFW) {
message.error(i18n.global.t('comment.illegalImage'));
predicting.value = false;
progressPercent.value = 100; // 重置进度条
progressStatus.value = 'exception'; // 异常状态
fileList.pop(); // 清空文件列表
predicting.value = false;
return false;
}
// 提取 EXIF 数据
const exifData = await extractAllExifData(file);
if (exifData) {
upload.exifData = exifData;
upload.predictResult.exif = exifData;
}
// 判断是否为截图
@@ -158,14 +162,7 @@ async function beforeUpload(file: File) {
progressPercent.value = 100; // 直接完成
return true;
}
// 人脸检测
const faceImageData = await fnDetectFace(image);
if (faceImageData) {
upload.predictResult.hasFace = true;
predicting.value = false;
progressPercent.value = 100; // 直接完成
return true;
}
//目标检测和风景检测并行处理
const [cocoResults, landscape] = await Promise.all([
cocoSsdPredict(image), // 目标检测
@@ -218,7 +215,6 @@ async function customUploadRequest(file: any) {
formData.append("data", JSON.stringify({
fileType: file.file.type,
...upload.predictResult,
exif: JSON.stringify(upload.exifData) || '',
}));
watch(
() => uploading.value,
@@ -248,6 +244,14 @@ function cancelUpload() {
progressPercent.value = 0; // 重置进度条
}
/**
* 拒绝文件回调
* @param fileList
*/
function rejectFile(fileList: any) {
fileList.value.pop();
}
/**
* 删除文件
* @param file