|
@@ -4,8 +4,8 @@
|
|
|
<!-- 表格 header 按钮 -->
|
|
|
<template #tableHeader="scope">
|
|
|
<el-button type="primary" v-auth="['demo:videoStable:add']" icon="CirclePlus" @click="openDialog(1, '视频去抖动新增')"> 新增 </el-button>
|
|
|
- <el-button type="primary" v-auth="['demo:videoStable:import']" icon="Upload" plain @click="batchAdd"> 导入</el-button>
|
|
|
- <el-button type="primary" v-auth="['demo:videoStable:export']" icon="Download" plain @click="downloadFile"> 导出 </el-button>
|
|
|
+ <!-- <el-button type="primary" v-auth="['demo:videoStable:import']" icon="Upload" plain @click="batchAdd"> 导入</el-button>-->
|
|
|
+ <!-- <el-button type="primary" v-auth="['demo:videoStable:export']" icon="Download" plain @click="downloadFile"> 导出 </el-button>-->
|
|
|
<el-button
|
|
|
type="danger"
|
|
|
v-auth="['demo:videoStable:remove']"
|
|
@@ -32,14 +32,25 @@
|
|
|
</ProTable>
|
|
|
<FormDialog ref="formDialogRef" />
|
|
|
<ImportExcel ref="dialogRef" />
|
|
|
- <el-dialog v-model="dialogVisible" :title="'图片对比: ' + taskName + '第' + imageIdx + '张图片对比'" width="80%">
|
|
|
- <div class="image-dialog">
|
|
|
- <el-image :src="'data:image/png;base64,' + imageBase64List.origin" style="width: 45%"></el-image>
|
|
|
- <el-image :src="'data:image/png;base64,' + imageBase64List.stable" style="width: 45%"></el-image>
|
|
|
+ <el-dialog v-model="dialogVisible" :title="dialogTitle" width="80%">
|
|
|
+ <el-form>
|
|
|
+ <el-form-item label="帧率">
|
|
|
+ <el-select v-model="imageFps" placeholder="选择帧率" style="width: 200px" @change="changeFps">
|
|
|
+ <el-option label="0" value="0"></el-option>
|
|
|
+ <el-option label="5" value="5"></el-option>
|
|
|
+ <el-option label="15" value="15"></el-option>
|
|
|
+ <el-option label="30" value="30"></el-option>
|
|
|
+ <el-option label="60" value="60"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div class="image-dialog" v-if="imageIdx > 0">
|
|
|
+ <el-image :src="'data:image/png;base64,' + cacheImages[imageIdx].origin" style="width: 45%"></el-image>
|
|
|
+ <el-image :src="'data:image/png;base64,' + cacheImages[imageIdx].stable" style="width: 45%"></el-image>
|
|
|
</div>
|
|
|
- <div class="image-dialog-btn">
|
|
|
- <el-button type="primary" @click="pre_picture" :disabled="imageIdx === 1">上一个</el-button>
|
|
|
- <el-button type="primary" @click="next_picture">下一个</el-button>
|
|
|
+ <div class="image-dialog-btn" v-if="imageFps == 0">
|
|
|
+ <el-button type="primary" @click="pre_picture" :disabled="imageIdx <= 1">上一个</el-button>
|
|
|
+ <el-button type="primary" @click="next_picture" :disabled="imageIdx >= fileCount">下一个</el-button>
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
</div>
|
|
@@ -64,16 +75,40 @@ import {
|
|
|
exportVideoStableApi,
|
|
|
getVideoStableApi,
|
|
|
startVideoStableApi,
|
|
|
- getCompareImageApi
|
|
|
+ getCompareImageApi,
|
|
|
+ getCompareImageCountApi
|
|
|
} from '@/api/modules/demo/videoStable'
|
|
|
|
|
|
const dialogVisible = ref(false)
|
|
|
-const taskName = ref('')
|
|
|
-const imageIdx = ref(1)
|
|
|
+const taskId = ref('')
|
|
|
+const imageIdx = ref(0)
|
|
|
const imageBase64List = ref({
|
|
|
origin: '',
|
|
|
stable: ''
|
|
|
})
|
|
|
+const inFileCount = ref(0)
|
|
|
+const outFileCount = ref(0)
|
|
|
+// 直接缓存所有图片
|
|
|
+const cacheImages = ref({ 0: { origin: '', stable: '' } })
|
|
|
+const dialogTitle = ref('')
|
|
|
+const fileCount = ref(0)
|
|
|
+const imageFps = ref(0)
|
|
|
+const intervalChangeFps: any = ref()
|
|
|
+
|
|
|
+const changeFps = () => {
|
|
|
+ console.log('changeFps')
|
|
|
+ if (intervalChangeFps.value) {
|
|
|
+ clearInterval(intervalChangeFps.value)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (imageFps.value == 0) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ imageIdx.value = 1
|
|
|
+ intervalChangeFps.value = setInterval(() => {
|
|
|
+ next_picture()
|
|
|
+ }, 1000 / imageFps.value)
|
|
|
+}
|
|
|
|
|
|
const startVideoStable = async (params: any) => {
|
|
|
const res = await startVideoStableApi(params.id)
|
|
@@ -85,27 +120,57 @@ const startVideoStable = async (params: any) => {
|
|
|
proTable.value?.getTableList()
|
|
|
}
|
|
|
|
|
|
-const loadImageData = async (taskName: string, imageIdx: number) => {
|
|
|
- const res: any = await getCompareImageApi(taskName, imageIdx)
|
|
|
+const loadImageData = async (taskId: string, imageIdx: number) => {
|
|
|
+ const res: any = await getCompareImageApi(taskId, imageIdx)
|
|
|
imageBase64List.value.origin = res.origin
|
|
|
imageBase64List.value.stable = res.stable
|
|
|
}
|
|
|
const compareVideoStable = async (params: any) => {
|
|
|
- taskName.value = params.name
|
|
|
- imageIdx.value = 1
|
|
|
- await loadImageData(taskName.value, imageIdx.value)
|
|
|
+ taskId.value = params.id
|
|
|
+ imageIdx.value = 0
|
|
|
|
|
|
+ const resCount: any = await getCompareImageCountApi(params.id)
|
|
|
+ if (resCount.code === 200) {
|
|
|
+ inFileCount.value = resCount.data.inFileCount
|
|
|
+ outFileCount.value = resCount.data.outFileCount
|
|
|
+ } else {
|
|
|
+ ElMessage.error('获取图片对比数量失败')
|
|
|
+ return
|
|
|
+ }
|
|
|
dialogVisible.value = true
|
|
|
+
|
|
|
+ dialogTitle.value = '缓存图片中'
|
|
|
+ fileCount.value = Math.min(inFileCount.value, outFileCount.value)
|
|
|
+ for (let idx = 1; idx <= fileCount.value; idx++) {
|
|
|
+ dialogTitle.value = '缓存图片中: 第' + idx + '张图片 共' + fileCount.value + '张图片'
|
|
|
+ if (cacheImages.value[idx]) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ const res: any = await getCompareImageApi(taskId.value, idx)
|
|
|
+ cacheImages.value[idx] = {
|
|
|
+ origin: res.origin,
|
|
|
+ stable: res.stable
|
|
|
+ }
|
|
|
+ }
|
|
|
+ next_picture()
|
|
|
}
|
|
|
const next_picture = async () => {
|
|
|
- imageIdx.value = imageIdx.value + 1
|
|
|
- await loadImageData(taskName.value, imageIdx.value)
|
|
|
+ if (imageIdx.value < fileCount.value) {
|
|
|
+ if (!cacheImages.value[imageIdx.value + 1]) {
|
|
|
+ await loadImageData(taskId.value, imageIdx.value + 1)
|
|
|
+ }
|
|
|
+ imageIdx.value = imageIdx.value + 1
|
|
|
+ }
|
|
|
+ dialogTitle.value = '图片对比: 第' + imageIdx.value + '张图片 共' + fileCount.value + '张图片'
|
|
|
}
|
|
|
const pre_picture = async () => {
|
|
|
if (imageIdx.value > 1) {
|
|
|
+ if (!cacheImages.value[imageIdx.value - 1]) {
|
|
|
+ await loadImageData(taskId.value, imageIdx.value - 1)
|
|
|
+ }
|
|
|
imageIdx.value = imageIdx.value - 1
|
|
|
- await loadImageData(taskName.value, imageIdx.value)
|
|
|
}
|
|
|
+ dialogTitle.value = '图片对比: 第' + imageIdx.value + '张图片 共' + fileCount.value + '张图片'
|
|
|
}
|
|
|
|
|
|
// ProTable 实例
|
|
@@ -212,22 +277,6 @@ const columns = reactive<ColumnProps<any>[]>([
|
|
|
tag: true,
|
|
|
enum: statusEnums
|
|
|
},
|
|
|
- {
|
|
|
- prop: 'inPath',
|
|
|
- label: '输入图片集路径',
|
|
|
- search: {
|
|
|
- el: 'input'
|
|
|
- },
|
|
|
- width: 120
|
|
|
- },
|
|
|
- {
|
|
|
- prop: 'outPath',
|
|
|
- label: '去抖动的图片集路径',
|
|
|
- search: {
|
|
|
- el: 'input'
|
|
|
- },
|
|
|
- width: 120
|
|
|
- },
|
|
|
{
|
|
|
prop: 'startTime',
|
|
|
label: '开始时间',
|
|
@@ -268,6 +317,56 @@ const columns = reactive<ColumnProps<any>[]>([
|
|
|
},
|
|
|
width: 120
|
|
|
},
|
|
|
+
|
|
|
+ {
|
|
|
+ prop: 'block_size',
|
|
|
+ label: 'block_size',
|
|
|
+ search: {
|
|
|
+ el: 'input'
|
|
|
+ },
|
|
|
+ width: 120
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'radius',
|
|
|
+ label: 'radius',
|
|
|
+ search: {
|
|
|
+ el: 'input'
|
|
|
+ },
|
|
|
+ width: 120
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'cornerquality',
|
|
|
+ label: 'cornerquality',
|
|
|
+ search: {
|
|
|
+ el: 'input'
|
|
|
+ },
|
|
|
+ width: 130
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'cornerminDistance',
|
|
|
+ label: 'cornerminDistance',
|
|
|
+ search: {
|
|
|
+ el: 'input'
|
|
|
+ },
|
|
|
+ width: 180
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'lklevel',
|
|
|
+ label: 'lklevel',
|
|
|
+ search: {
|
|
|
+ el: 'input'
|
|
|
+ },
|
|
|
+ width: 120
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'lkwinSiz',
|
|
|
+ label: 'lkwinSiz',
|
|
|
+ search: {
|
|
|
+ el: 'input'
|
|
|
+ },
|
|
|
+ width: 120
|
|
|
+ },
|
|
|
+
|
|
|
{
|
|
|
prop: 'remarks',
|
|
|
label: '备注',
|
|
@@ -296,114 +395,98 @@ const setItemsOptions = () => {
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
- label: '输入路径',
|
|
|
- prop: 'inPath',
|
|
|
- rules: [{ required: true, message: '输入图片集路径不能为空', trigger: 'blur' }],
|
|
|
- compOptions: {
|
|
|
- type: 'block_size',
|
|
|
- clearable: true,
|
|
|
- placeholder: '请输入内容'
|
|
|
- }
|
|
|
- },
|
|
|
- {
|
|
|
- label: '输出路径',
|
|
|
- prop: 'outPath',
|
|
|
- rules: [{ required: true, message: '去抖动的图片集路径不能为空', trigger: 'blur' }],
|
|
|
- compOptions: {
|
|
|
- type: 'block_size',
|
|
|
- clearable: true,
|
|
|
- placeholder: '请输入内容'
|
|
|
- }
|
|
|
- },
|
|
|
- {
|
|
|
- label: '备注',
|
|
|
- prop: 'remarks',
|
|
|
- rules: [
|
|
|
- {
|
|
|
- required: false,
|
|
|
- message: '备注不能为空',
|
|
|
- trigger: 'blur'
|
|
|
- }
|
|
|
- ],
|
|
|
+ label: '图片集压缩包',
|
|
|
+ prop: 'inputOssId',
|
|
|
+ rules: [{ required: false, message: '图片集压缩包不能为空', trigger: 'blur' }],
|
|
|
compOptions: {
|
|
|
- placeholder: '请输入备注'
|
|
|
+ elTagName: 'file-upload',
|
|
|
+ fileSize: 4096,
|
|
|
+ fileType: ['zip'],
|
|
|
+ placeholder: '请上传图片集压缩包'
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
label: 'block_size',
|
|
|
prop: 'block_size',
|
|
|
- rules: [{ required: true, message: 'block_size不能为空', trigger: 'blur' }],
|
|
|
+ rules: [{ required: false, message: 'block_size不能为空', trigger: 'blur' }],
|
|
|
compOptions: {
|
|
|
type: 'input',
|
|
|
clearable: true,
|
|
|
- placeholder: '请输入内容',
|
|
|
- value: 50
|
|
|
+ placeholder: '默认50'
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
label: 'radius',
|
|
|
prop: 'radius',
|
|
|
- rules: [{ required: true, message: 'radius不能为空', trigger: 'blur' }],
|
|
|
+ rules: [{ required: false, message: 'radius不能为空', trigger: 'blur' }],
|
|
|
compOptions: {
|
|
|
- type: 'block_size',
|
|
|
+ type: 'input',
|
|
|
clearable: true,
|
|
|
- placeholder: '请输入内容',
|
|
|
- value: 500
|
|
|
+ placeholder: '默认500'
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
label: 'buffer_size',
|
|
|
prop: 'buffer_size',
|
|
|
- rules: [{ required: true, message: 'buffer_size不能为空', trigger: 'blur' }],
|
|
|
+ rules: [{ required: false, message: 'buffer_size不能为空', trigger: 'blur' }],
|
|
|
compOptions: {
|
|
|
- type: 'block_size',
|
|
|
+ type: 'input',
|
|
|
clearable: true,
|
|
|
- placeholder: '请输入内容',
|
|
|
- value: 200
|
|
|
+ placeholder: '默认200'
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
label: 'cornerquality',
|
|
|
prop: 'cornerquality',
|
|
|
- rules: [{ required: true, message: 'cornerquality不能为空', trigger: 'blur' }],
|
|
|
+ rules: [{ required: false, message: 'cornerquality不能为空', trigger: 'blur' }],
|
|
|
compOptions: {
|
|
|
- type: 'block_size',
|
|
|
+ type: 'input',
|
|
|
clearable: true,
|
|
|
- placeholder: '请输入内容',
|
|
|
- value: 0.2
|
|
|
+ placeholder: '默认0.2'
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
label: 'cornerminDistance',
|
|
|
prop: 'cornerminDistance',
|
|
|
- rules: [{ required: true, message: 'cornerminDistance不能为空', trigger: 'blur' }],
|
|
|
+ rules: [{ required: false, message: 'cornerminDistance不能为空', trigger: 'blur' }],
|
|
|
compOptions: {
|
|
|
- type: 'block_size',
|
|
|
+ type: 'input',
|
|
|
clearable: true,
|
|
|
- placeholder: '请输入内容',
|
|
|
- value: 5
|
|
|
+ placeholder: '默认5'
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
label: 'lklevel',
|
|
|
prop: 'lklevel',
|
|
|
- rules: [{ required: true, message: 'lklevel不能为空', trigger: 'blur' }],
|
|
|
+ rules: [{ required: false, message: 'lklevel不能为空', trigger: 'blur' }],
|
|
|
compOptions: {
|
|
|
- type: 'block_size',
|
|
|
+ type: 'input',
|
|
|
clearable: true,
|
|
|
- placeholder: '请输入内容',
|
|
|
- value: 3
|
|
|
+ placeholder: '默认3'
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
label: 'lkwinSiz',
|
|
|
prop: 'lkwinSiz',
|
|
|
- rules: [{ required: true, message: 'lkwinSiz不能为空', trigger: 'blur' }],
|
|
|
+ rules: [{ required: false, message: 'lkwinSiz不能为空', trigger: 'blur' }],
|
|
|
compOptions: {
|
|
|
- type: 'block_size',
|
|
|
+ type: 'input',
|
|
|
clearable: true,
|
|
|
- placeholder: '请输入内容',
|
|
|
- value: 15
|
|
|
+ placeholder: '默认15'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '备注',
|
|
|
+ prop: 'remarks',
|
|
|
+ rules: [
|
|
|
+ {
|
|
|
+ required: false,
|
|
|
+ message: '备注不能为空',
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ compOptions: {
|
|
|
+ placeholder: '请输入备注'
|
|
|
}
|
|
|
}
|
|
|
]
|