You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

382 lines
9.2 KiB

(function initAxios(){
axios.defaults.baseURL = 'http://127.0.0.1:5000';
axios.interceptors.response.use(
function(response) {
return Promise.resolve(response.data);
},
function(error) {
return Promise.reject(error);
}
);
})();
const app = new Vue({
el: '#app',
data: {
currentImage: null,
secondImage: null,
resultImage: [],
disableReplace: false,
images: [],
inCrop: false,
loading: false,
command: '',
// cropper
cropper:{
width: 200,
height: 200
},
displayCropperWidth: 200,
displayCropperHeight: 200,
// ui
asideMenu: [
'图像调整',
'基本计算',
'边缘检测',
'图像增强',
'形态学操作',
'噪声滤波',
'风格迁移',
'其他'
],
currentCollapseName: '',
selectedAsideMenu: 0,
// popup
dialogVisible: false,
// aside menu中具体项目
logicOp: [
['and', '与运算'],
['or', '或运算'],
['not', '非运算']
],
arthimaticOp: [
['add', '加运算'],
['subtract', '减运算'],
['multiply', '乘运算'],
['divide', '除运算']
],
geometricOp: [
['scale', '缩放'],
['translate', '平移'],
['rotate', '旋转'],
],
geometricOpArgs: {
x: 0,
y: 0,
xArg: 0,
yArg: 0,
deg: 0
},
flipOp: [
['flipHor', '水平翻转'],
['flipVer', '垂直翻转']
],
affineOp: [
['affine', '仿射变换']
],
affineArgs: {
post1: [[0,0],[0,0],[0,0]],
post2: [[0,0],[0,0],[0,0]],
},
// 边缘检测
edgeOp: [
['roberts', 'Roberts'],
['sobel', 'Sobel'],
['laplacian', 'Laplacian'],
['LoG', 'LoG'],
['canny', 'Canny']
],
edgeArgs: {
blurSize: 3,
ksize: 3,
threshold1: 50,
threshold2: 150
},
houghOp: [
['hough', '霍夫变换'],
['houghP', '概率霍夫变换']
],
houghArgs: {
blurSize: 3,
cannyThreshold1: 50,
cannyThreshold2: 150,
houghThreshold: 120,
minLineLength: 120,
maxLineGap: 15
},
// 噪声
noiseOp: [
['spNoise', '椒盐噪声'],
['gaussianNoise', '高斯噪声'],
],
noiseArgs: {
svp: 0.5,
amount: 0.04,
mean: 0,
sigma: 25
},
// 滤波01
blurOp: [
['maxBlur', '最大值滤波'],
['avgBlur', '均值滤波'],
['minBlur', '最小值滤波'],
['medBlur', '中值滤波'],
['gaussianBlur', '高斯滤波'],
['geometricBlur', '几何均值滤波'],
['harmonicBlur', '谐波均值滤波']
],
blurArgs: {
x: 3,
y: 3,
ksize: 3
},
// 滤波02
selectiveOp: [
['lowPass', '低通滤波'],
['highPass', '高通滤波'],
['bandPass', '带通滤波'],
['bandStop', '带阻滤波'],
],
selectiveArgs: {
threshold1: 0,
threshold2: 255
},
// 形态学操作
morphOp: [
['morphOpen', '开操作'],
['morphClose', '闭操作'],
['morphErode', '腐蚀'],
['morphDilate', '膨胀'],
],
morphArgs: {
kernelX: 5,
kernelY: 5,
kernelType: 0
},
// 频域的平滑/频域的锐化
filterOp1: [
['lpFilter', '理想低通滤波'],
['hpFilter', '理想高通滤波'],
['blpFilter', '巴特沃兹低通滤波'],
['bhpFilter', '巴特沃兹高通滤波'],
['glpFilter', '高斯低通滤波'],
['ghpFilter', '高斯高通滤波'],
],
filterArgs1: {
d0: 50,
n: 2
},
// 空域的平滑
filterOp2: [
['robertsGrad', 'Roberts算子'],
['sobelGrad', 'Sobel算子'],
['prewittGrad', 'Prewitt算子'],
['laplacianGrad', 'Laplacian算子'],
],
// 其他
otherOp: [
['hist', '直方图统计'],
['getRGB', 'RGB'],
['getHSV', 'HSV']
],
// 风格迁移
transferOp: [
['transfer', '风格迁移']
],
transferModels: [
'candy', 'composition_vii', 'feather', 'la_muse', 'la_muse_eccv16',
'mosaic', 'starry_night', 'the_scream', 'the_wave', 'udnie'
],
transferArgs: {
model: ''
},
// 任意风格任意内容
myTransferOp: [
['myTransfer', '风格迁移']
]
},
methods: {
selectAsideCollapse(index){
this.selectedAsideMenu = index;
this.command = ''; // clear command
},
switchImage(index){
this.inCrop = false;
this.currentImage = index;
},
setCommand(command){
this.command = command;
},
replaceResultImage(){
this.getImageInfo(this.resultImage[0]).then(info => {
this.images[this.currentImage] = info
})
this.dialogVisible = false;
},
addResultImage(){
this.resultImage.forEach(e => {
this.addImage(e)
})
this.dialogVisible = false;
},
//---crop---
startCrop(){
if(this.currentImage !== null){
this.inCrop = true;
}
},
cancelCrop(){
this.inCrop = false;
},
endCrop(){
const cropper = this.$refs.cropper;
this.$refs.cropper.getCropData(data => {
this.images[this.currentImage].data = data;
this.images[this.currentImage].width = cropper.cropW
this.images[this.currentImage].height = cropper.cropH
this.inCrop = false;
})
},
onCropperMove(preview){
const cropper = this.$refs.cropper;
this.displayCropperHeight = Math.round(cropper.cropH)
this.displayCropperWidth = Math.round(cropper.cropW)
},
setCropperSize(){
this.cropper.width = this.displayCropperWidth;
this.cropper.height = this.displayCropperHeight;
},
//---command---
cancelAction(){
if(this.inCrop){
this.cancelCrop();
return;
}
// cancel request
this.controller.abort();
},
confirmAction(args){
if(this.loading){
this.$message.warning('正在进行其他处理操作')
return;
}
if(this.inCrop){
this.endCrop();
return;
}
if(!this.command){
this.$message.warning('未选择操作');
return;
}
if(this.currentImage === null){
this.$message.warning('未选择图片');
return;
}
const files = [this.images[this.currentImage].data];
if(this.multiInput){
if(!this.secondImage){
this.$message.warning('未选择第二张图片')
return;
}
files.push(this.secondImage)
}
this.process(files, this.command, args);
},
//---collapse---
onCollapseChange(newCollapse){
if(newCollapse !== '' && newCollapse !== 'adjust-01'){
this.cancelCrop();
}
},
//---api---
process(base64Images, command, args={}){
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime
});
}
this.loading = true;
this.controller = new AbortController();
const param = new FormData();
base64Images.forEach((img,i) => {
param.append('files', dataURLtoBlob(img),new Date().getTime() + '' + i);
})
param.append('command', command);
param.append('args', JSON.stringify(args));
return axios.post('/process', param, {
'Content-Type': 'multipart/form-data',
signal: this.controller.signal
}).then(data => {
this.resultImage = data.data.map(e => 'data:image/jpeg;base64,' + e);
this.dialogVisible = true;
}).catch(e => {
console.error(e);
if(e.response){
const msg = e.response.data.message;
this.$message.error(msg);
}
}).finally(() => {
this.loading = false;
});
},
uploadImage(file, onload){
const reader = new FileReader();
reader.onload = onload || (e => {
this.addImage(e.target.result);
});
reader.readAsDataURL(file);
return false;
},
uploadSecondImage(file){
this.uploadImage(file, e => {
this.secondImage = e.target.result;
})
return false;
},
getImageInfo(data){
return new Promise((resolve, reject) => {
const img = new Image();
img.src = data;
img.onload = () => {
resolve({
width: img.width,
height: img.height,
data: data,
tag: ''
})
}
})
},
addImage(data, tag=''){
this.getImageInfo(data).then(info => {
info.tag = tag;
this.images.push(info);
if(this.currentImage === null){
this.currentImage = 0;
}
})
},
deleteImage(index){
this.images.splice(index, 1);
if(this.currentImage >= index){
this.currentImage = this.images.length === 0 ? null : Math.max(this.currentImage-1, 0);
}
}
},
computed: {
multiInput(){
return this.currentCollapseName.indexOf('[mul]') >= 0 && this.command !== 'not';
},
}
});