Commit 459094c9 authored by 柳 佳乐's avatar 柳 佳乐
Browse files

first

parents
Pipeline #35 canceled with stages
//图标颜色和大小
$iconfont:30px;
$iconblue:#409EFF;
$iconred:#F56C6C;
$icongreen:#67C23A;
\ No newline at end of file
<template>
<div class="setting">
<el-row>
<el-col :xs="24" :sm="12" :lg="4">
<div class="setting_select">
<i class="iconfont icon-moxing setting_select_icon"></i>
<el-button class="setting_select_btn" @click="selectModel">模型权重选择</el-button>
</div>
</el-col>
<el-col :xs="24" :sm="12" :lg="4">
<div class="setting_initialize">
<i class="iconfont icon-shujuji setting_initialize_icon"></i>
<el-button class="setting_initialize_btn" @click="gotoDataSetVue">数据集</el-button>
</div>
</el-col>
<el-col :xs="24" :sm="12" :lg="8">
<div class="setting_confidence">
<p class="setting_confidence_text">Confidence:</p>
<el-input-number class="setting_confidence_number" v-model="confidenceValue" size="small" :precision="2"
:step="0.01" :max="1" :min="0" @change="updataSetting"></el-input-number>
<el-slider class="setting_confidence_slider" v-model="confidenceValue" :precision="2" :step="0.01" :max="1"
:min="0" @change="updataSetting"></el-slider>
</div>
</el-col>
<el-col :xs="24" :sm="12" :lg="8">
<div class="setting_IOU">
<p class="setting_IOU_text">IOU:</p>
<el-input-number class="setting_IOU_number" v-model="IOUValue" size="small" :precision="2" :step="0.01" :max="1"
:min="0" @change="updataSetting"></el-input-number>
<el-slider class="setting_IOU_slider" v-model="IOUValue" :precision="2" :step="0.01" :max="1"
:min="0" @change="updataSetting"></el-slider>
</div>
</el-col>
</el-row>
<el-dialog title="模型权重选择" :visible.sync="dialogVisible" width="30%">
<el-upload
class="upload-demo"
ref="upload"
:action="baseUrl + '/model/load'"
accept=".pt"
:multiple="false"
:file-list="modelList"
:http-request="selectModelUpload"
:on-change="selectModelUploadOnChange"
:on-remove="selectModelUploadOnChange"
:auto-upload="false"
:limit="1"
>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<el-button style="margin-left: 10px;" :disabled="isUpload" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
<div slot="tip" class="el-upload__tip">只能上传pt文件</div>
</el-upload>
</el-dialog>
</div>
</template>
<script>
import {FileData} from "@/api/index"
import { Loading } from 'element-ui';
export default {
name: "HomeHeader",
data() {
return {
confidenceValue:0.7,
IOUValue:0.45,
dialogVisible: false,
modelList:[],
isUpload:true,
}
},
created() {
},
methods: {
//模型权重选择
selectModel(){
this.dialogVisible = true;
this.isUpload = true;
},
selectModelUploadOnChange(file, fileList){
this.modelList = fileList
if(fileList.length>0){
this.isUpload = false;
}else{
this.isUpload = true;
}
},
submitUpload(){
this.$refs.upload.submit();
},
selectModelUpload(obj){
let loadingInstance = Loading.service();
const formData = new FormData();
formData.append("model", obj.file);//file 和 后端字段要保持一致
FileData(obj,formData).then(res=>{
loadingInstance.close();
this.$message.success(res)
this.dialogVisible = false;
this.$refs.upload.clearFiles()
}).catch(error=>{
loadingInstance.close();
this.$refs.upload.clearFiles()
console.log(error)
this.$message.error("系统错误")
})
},
updataSetting(){
this.$emit("updataSetting",this.confidenceValue,this.IOUValue)
},
gotoDataSetVue(){
this.$router.push("/dataset")
}
},
}
</script>
<style scoped lang="scss">
.setting {
width: 100%;
margin-bottom: 20px;
text-align: center;
.setting_select_icon {
font-size: $iconfont;
margin: 0px 5px;
vertical-align: middle;
color: $iconblue;
}
.setting_initialize_icon {
font-size: $iconfont;
margin: 0px 5px;
vertical-align: middle;
color: $iconblue;
}
.setting_confidence {
.setting_confidence_text {
display: inline-block;
margin: 0px 10px;
}
.setting_confidence_number {
display: inline-block;
margin: 0px 5px;
}
.setting_confidence_slider {
display: inline-block;
margin: 0px 5px;
width: 100px;
vertical-align: bottom;
}
}
.setting_IOU {
.setting_IOU_text {
display: inline-block;
margin: 0px 10px;
}
.setting_IOU_number {
display: inline-block;
margin: 0px 5px;
}
.setting_IOU_slider {
display: inline-block;
margin: 0px 5px;
width: 100px;
vertical-align: bottom;
}
}
}
</style>
\ No newline at end of file
<template>
<div class="content_operate_img">
<div class="content_operate_img_select">
<i class="iconfont icon-tupian content_operate_img_select_icon"></i>
<el-button @click="selectImage">选择图像</el-button>
</div>
<div class="content_operate_img_detect">
<i class="iconfont icon-5tuxiangjiance content_operate_img_detect_icon"></i>
<el-button @click="imageDetect">图像检测</el-button>
</div>
<div class="content_operate_img_export">
<i class="iconfont icon-daochu content_operate_img_export_icon"></i>
<el-button @click="imageDownload">图像检测结果导出</el-button>
</div>
<div class="content_operate_img_end">
<i class="iconfont icon-wutupian1 content_operate_img_end_icon"></i>
<el-button @click="endImage">结束图像检测</el-button>
</div>
<el-dialog title="图片选择" :visible.sync="dialogVisible" width="30%">
<el-upload
class="upload-demo"
ref="upload"
:action="baseUrl + '/image/open'"
accept=".JPG,.TIF"
:multiple="false"
:file-list="imagelList"
:http-request="selectImageUpload"
:on-change="selectImageUploadOnChange"
:on-remove="selectImageUploadOnChange"
:auto-upload="false"
:limit="1"
>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<el-button style="margin-left: 10px;" :disabled="isUpload" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
<div slot="tip" class="el-upload__tip">只能上传.jpg和.TIF图片</div>
</el-upload>
</el-dialog>
</div>
</template>
<script>
import { Loading } from 'element-ui';
import {FileData,GetData} from "@/api/index"
import 'tiff.js'
import Tiff from 'tiff.js'
import axios from 'axios'
export default {
name: "ImageVue",
data() {
return {
dialogVisible: false,
imageUrl:null,
imagelList:[],
isUpload:true,
TiforJPG:false,
imageDownloadURL:null,
fileNmae:null,
}
},
props:['confidenceValue','IOUValue'],
created() {
},
methods: {
//选择图片
selectImage(){
this.dialogVisible = true;
this.isUpload = true;
},
selectImageUploadOnChange(file, fileList){
this.imagelList = fileList
if(fileList.length>0){
this.isUpload = false;
this.imageUrl = URL.createObjectURL(file.raw);
this.fileNmae = file.name;
if(this.fileNmae.slice(-3) == "TIF"){
this.fileNmae = this.fileNmae.slice(0,this.fileNmae.length-3)+"JPG"
console.log(this.fileNmae)
this.TiforJPG = true;
}else{
this.TiforJPG = false;
}
}else{
this.isUpload = true;
this.imageUrl = null;
}
},
submitUpload(){
this.$refs.upload.submit();
},
selectImageUpload(obj){
let loadingInstance = Loading.service();
const formData = new FormData();
formData.append("image", obj.file);//file 和 后端字段要保持一致
FileData(obj,formData).then(res=>{
loadingInstance.close();
this.$message.success(res);
this.$refs.upload.clearFiles();
this.imageShow();
this.dialogVisible = false;
}).catch(error=>{
loadingInstance.close();
this.$refs.upload.clearFiles();
console.log(error)
this.$message.error("系统错误")
})
},
async imageShow(){
if(this.TiforJPG){
await axios.get(this.imageUrl, { responseType: 'blob' }).then((res) => {
res.data.arrayBuffer().then((arrayBuffer) => {
const tiff = new Tiff({
buffer: arrayBuffer,
});
this.imageUrl = tiff.toDataURL("image/jpg")
this.$emit("openImage",this.imageUrl);
})
})
}else{
this.$emit("openImage",this.imageUrl);
}
},
//图像检测
imageDetect(){
let loadingInstance = Loading.service();
let data={
numcon:this.confidenceValue,
numiou:this.IOUValue
}
GetData("/image/detect",data).then(res=>{
this.imageDownloadURL = this.baseUrl +"/" + res.url
this.$emit("imageFrame",res,loadingInstance)
}).catch(error=>{
loadingInstance.close();
console.log(error)
this.$message.error("系统错误")
})
},
//图像导出
imageDownload(){
// if(this.imageDownloadURL){
// window.open(this.baseUrl+"/image/export")
// }
this.$emit("uploadeImage",this.fileNmae)
},
endImage(){
this.imageDownloadURL=null
this.dialogVisible=false
this.imageUrl=null
this.imagelList=[]
this.isUpload=true
this.$emit("endImage")
}
},
}
</script>
<style scoped lang="scss">
.content_operate_img{
display: flex;
flex-wrap:wrap;
justify-content: space-between;
margin:5px;
.content_operate_img_select{
margin: 5px;
.content_operate_img_select_icon{
font-size: $iconfont;
margin: 0px 5px;
vertical-align: middle;
color: $iconblue;
}
}
.content_operate_img_detect{
margin: 5px;
.content_operate_img_detect_icon{
font-size: $iconfont;
margin: 0px 5px;
vertical-align: middle;
color: $icongreen;
}
}
.content_operate_img_show{
margin: 5px;
.content_operate_img_show_icon{
font-size: $iconfont;
margin: 0px 5px;
vertical-align: middle;
color: $iconblue;
}
}
.content_operate_img_export{
margin: 5px;
.content_operate_img_export_icon{
font-size: $iconfont;
margin: 0px 5px;
vertical-align: middle;
color: $iconblue;
}
}
.content_operate_img_end{
margin: 5px;
.content_operate_img_end_icon{
font-size: $iconfont;
margin: 0px 5px;
vertical-align: middle;
color: $iconred;
}
}
}
</style>
\ No newline at end of file
//图形检测
let rectList = res.results
let labelList = res.labels
let myCanvas = this.$refs.myCanvas
var ctx = myCanvas.getContext('2d')
var w = myCanvas.width;
var h = myCanvas.height;
ctx.clearRect(0, 0, w, h);
let img = new Image()
img.src = this.imageUrl
img.onload = function(){
let w = img.width*800/img.width;
let h = img.height*600/img.height;
myCanvas.width = w
myCanvas.height = h
ctx.drawImage(img, 0, 0,w,h)
//位置框框
ctx.beginPath();
ctx.strokeStyle = 'red';
ctx.lineWidth = 1;
ctx.font = "20px serif";
for(let i=0;i<rectList.length;i++){
console.log("画框框")
let x = (800/1600)*rectList[i][0]
let y = (600/1300)*rectList[i][1]
let width = (800/1600)*rectList[i][2] - x;
let height = (600/1300)*rectList[i][3] - y;
ctx.strokeRect(x, y, width, height);
ctx.strokeText(labelList[i],x,y-5);
}
//标签
}
// ctx.clearRect(0, 0, w, h);
// 在Canvas画布 添加图片
// let img = new Image()
// img.src = this.baseUrl +"/" + res.url
// img.onload = function(){
// let w = img.width*800/img.width;
// let h = img.height*600/img.height;
// myCanvas.width = w
// myCanvas.height = h
// ctx.drawImage(img, 0, 0,w,h)
// loadingInstance.close();
// }
\ No newline at end of file
<template>
<div class="content_operate_video">
<div class="content_operate_video_select">
<i class="iconfont icon-shipin2 content_operate_video_icon"></i>
<el-button @click="selectVideo">选择视频</el-button>
</div>
<div class="content_operate_video_detect">
<i class="iconfont icon-shipinjiance_mianxing content_operate_video_detect_icon"></i>
<el-button @click="videoFrame">视频检测</el-button>
</div>
<!-- <div class="content_operate_video_paused">
<i class="iconfont icon-zanting content_operate_video_paused_icon"></i>
<el-button>暂停检测</el-button>
</div> -->
<div class="content_operate_video_export">
<i class="iconfont icon-daochu content_operate_video_export_icon"></i>
<el-button @click="videoDownload">视频检测结果导出</el-button>
</div>
<div class="content_operate_video_end">
<i class="iconfont icon-jieshushipin content_operate_video_end_icon"></i>
<el-button @click="endVideo">结束视频检测</el-button>
</div>
<el-dialog title="视频选择" :visible.sync="dialogVisible" width="30%" >
<el-upload
class="upload-demo"
ref="upload"
:action="baseUrl + '/video/open'"
accept=".mp4"
:multiple="false"
:file-list="videolList"
:http-request="selectVideoUpload"
:on-change="selectVideoUploadOnChange"
:on-remove="selectVideoUploadOnChange"
:auto-upload="false"
:limit="1"
>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<el-button style="margin-left: 10px;" :disabled="isUpload" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
<div slot="tip" class="el-upload__tip">只能上传.mp4文件</div>
</el-upload>
</el-dialog>
</div>
</template>
<script>
import { Loading } from 'element-ui';
import {FileData,GetData} from "@/api/index"
export default {
name: "VideoVue",
data() {
return {
dialogVisible:false,
isUpload:true,
videolList:[],
videoUrl:null,
videoDownloadURL:null,
}
},
props:['confidenceValue','IOUValue'],
created() {
},
methods: {
selectVideo(){
this.dialogVisible = true;
this.isUpload = true;
},
selectVideoUploadOnChange(file,fileList){
this.videolList = fileList
if(fileList.length>0){
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file.raw);
reader.onload = () => {
this.videoUrl = reader.result;
resolve(true); // 允许上传
}
reader.onerror = error => reject(error);
}).then(res=>{
this.isUpload = false;
}).catch(error=>{
console.log(error)
this.$message.error("该视频暂无法观看")
this.isUpload = false;
})
}else{
this.isUpload = true;
this.videoUrl = null;
}
},
submitUpload(){
this.$refs.upload.submit();
},
selectVideoUpload(obj){
let loadingInstance = Loading.service();
const formData = new FormData();
formData.append("video", obj.file);//file 和 后端字段要保持一致
FileData(obj,formData).then(res=>{
loadingInstance.close();
this.$message.success(res);
this.$refs.upload.clearFiles();
this.$emit("oepnVideo",this.videoUrl);
this.dialogVisible = false;
}).catch(error=>{
loadingInstance.close();
this.$refs.upload.clearFiles();
console.log(error)
this.$message.error("系统错误")
})
},
//视频检测
videoFrame(){
let loadingInstance = Loading.service();
let data={
numcon:this.confidenceValue,
numiou:this.IOUValue
}
GetData("/video/detect",data).then(res=>{
console.log(res)
this.videoDownloadURL = this.baseUrl +"/" + res.url
this.$emit("videoFrame",res,loadingInstance)
}).catch(error=>{
loadingInstance.close();
console.log(error)
this.$message.error("系统错误")
})
},
videoDownload(){
if(this.videoDownloadURL){
const a = document.createElement("a");
a.href = this.videoDownloadURL;
a.download = "123";
a.click();
a.remove();
}
},
endVideo(){
this.dialogVisible=false
this.isUpload=true
this.videolList=[]
this.videoDownloadURL = null
this.videoUrl=null
this.$emit("endVideo")
}
},
}
</script>
<style scoped lang="scss">
.content_operate_video {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: 5px;
.content_operate_video_select {
margin: 5px;
.content_operate_video_icon {
font-size: $iconfont;
margin: 0px 5px;
vertical-align: middle;
color: $iconblue;
}
}
.content_operate_video_detect {
margin: 5px;
.content_operate_video_detect_icon {
font-size: $iconfont;
margin: 0px 5px;
vertical-align: middle;
color: $icongreen;
}
}
.content_operate_video_paused {
margin: 5px;
.content_operate_video_paused_icon {
font-size: $iconfont;
margin: 0px 5px;
vertical-align: middle;
color: $iconred;
}
}
.content_operate_video_export {
margin: 5px;
.content_operate_video_export_icon {
font-size: $iconfont;
margin: 0px 5px;
vertical-align: middle;
color: $iconblue;
}
}
.content_operate_video_end {
margin: 5px;
.content_operate_video_end_icon {
font-size: $iconfont;
margin: 0px 5px;
vertical-align: middle;
color: $iconred;
}
}
}</style>
\ No newline at end of file
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import './assets/icon/iconfont.css';
Vue.prototype.baseUrl = window.ipConfig.baseUrl
Vue.config.productionTip = false
Vue.use(ElementUI);
new Vue({
router,
render: h => h(App),
}).$mount('#app')
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export const constantRoutes=[
{
path:"/login",
component:()=>import("@/views/login"),
name:"登录",
},
{
path:"/home",
component:()=>import("@/views/home"),
name:"主页面"
},
{
path:"/register",
component:()=>import("@/views/register"),
name:"注册",
},
{
path:"/",
redirect:"/login",
},
{
path:"/dataset",
component:()=>import("@/views/dataset"),
name:"数据集",
}
]
const createRouter = () => new Router({
routes: constantRoutes
})
const router = createRouter()
export default router
\ No newline at end of file
export function setCookie(name, value) {
let date = new Date()
date.setDate(date.getDate() + 1)
document.cookie = name + '=' + value + ';expires=' + date
}
export function getCookie(name) {
let reg = RegExp(name + '=([^;]+)')
let arr = document.cookie.match(reg)
if (arr) {
return arr[1]
} else {
return ''
}
}
export function delCookie(name) {
setCookie(name, null, -1)
}
import {Client} from 'basic-ftp';
export const ftpServe=new Client();
ftpServe.access({
host: "192.168.3.6",
port: 2121, // defaults to 21
user: "admin", // defaults to "anonymous"
pass: "123456" // defaults to "@anonymous"
});
ftp://admin:123456@192.168.3.6/train/images/DJI_001_0001_NIR.TIF
import axios from 'axios'
import { Message } from 'element-ui'
import Vue from 'vue'
const service = axios.create({
})
axios.defaults.withCredentials = true;
service.interceptors.request.use(
config => {
// config.headers['X-CSRFToken'] = "CTfoWmXPYGyEbN9Dm2sUcHe7cMafl33rOZx8jGvzKGRrxALz9if7o3qWoOmRKtgy"
config.headers['X-CSRFToken'] = sessionStorage.getItem("X-CSRFToken")
// axios.defaults.headers['X-CSRFToken'] = sessionStorage.getItem("X-CSRFToken")
return config
},
err => {
return Promise.reject(err)
}
)
service.interceptors.response.use(
response => {
const res = response
if (res.status !== 200) {
Message({
message: res.response.data || 'Error',
type: 'error',
duration: 5 * 1000
})
} else {
return res.data
}
},
error => {
Message({
message: error.response.data,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
export default service
<template>
<div class="data_set">
<!-- 头 -->
<div class="header">
<el-row>
<el-col :span="6">
<div>
<el-button @click="getList('train')">训练集</el-button>
</div>
</el-col>
<el-col :span="6">
<div>
<el-button @click="getList('val')">验证集</el-button>
</div>
</el-col>
<el-col :span="6">
<div>
<el-button @click="getList('test')">测试集</el-button>
</div>
</el-col>
<el-col :span="6">
<div>
<el-button @click="gotoHome">返回检测页面</el-button>
</div>
</el-col>
</el-row>
</div>
<!-- 内容 -->
<div class="content">
<!-- 列表 -->
<div class="table">
<div class="table_view">
<el-table :data="tableData" border style="width: 100%;height:100%"
:header-cell-style="{ 'text-align': 'center' }" highlight-current-row
@row-click="tableChange">
<el-table-column prop="img_name" label="名称">
</el-table-column>
<el-table-column label="操作" align="center" width="120">
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-download" @click.stop="uploadFile(scope.row)">下载</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div style="text-align: right;margin: 5px;">
<el-button :disabled="isUploadAllFiles" type="primary" icon="el-icon-download" @click="uploadAllFiles" >全部下载</el-button>
</div>
<div class="pagination">
<el-pagination background layout="prev, pager, next"
:total="total"
:page-size="queryData.page_size"
:current-page ="queryData.page_num"
@current-change="handleCurrentChange"
>
</el-pagination>
</div>
</div>
<!-- 图片展示 -->
<div class="image">
<el-image style="width: 100%; height: 100%" :src="imageUrl" fit="fit">
</el-image>
</div>
</div>
</div>
</template>
<script>
import { PostData,FTPData } from '@/api';
import qs from "qs";
import Tiff from 'tiff.js'
import axios from 'axios'
export default {
name: "DataSet",
data() {
return {
queryData:{
page_num:1,
page_size:10,
dataset_type:null,
},
tableData: [],
imageUrl: "",
total:0,
backAPi:null,
isUploadAllFiles:true
}
},
created() {
},
mounted(){
let backAPi = localStorage.getItem("backapi")
console.log(backAPi)
if(backAPi){
this.backAPi = backAPi
}else{
this.backAPi = "http://127.0.0.1:8080"
localStorage.setItem("backapi",this.backAPi);
}
},
methods: {
handleCurrentChange(val){
this.queryData.page_num = val
this.getList(this.queryData.dataset_type)
},
gotoHome(){
this.$router.push("/home")
},
getList(datasetType){
this.queryData.dataset_type = datasetType
PostData("/dataset/get_info",qs.stringify(this.queryData) ).then(res=>{
console.log(res)
this.tableData = res.dataset_info;
this.total = res.count
this.isUploadAllFiles = false;
}).catch(error=>{
console.log(error)
this.$message.error("系统错误")
})
},
uploadFile(row){
try{
const a = document.createElement('a')
a.download = row.img_name
a.href = this.baseUrl+"/"+row.img_url
a.click()
a.href = this.baseUrl+"/"+row.label_url
a.click()
a.remove()
}catch(error){
this.$message.error("系统错误")
console.log(error)
}
},
async tableChange(row,column,event){
if(row.img_name.slice(-3) == "TIF"){
await axios.get(this.baseUrl+row.img_url, { responseType: 'blob' }).then((res) => {
res.data.arrayBuffer().then((arrayBuffer) => {
const tiff = new Tiff({
buffer: arrayBuffer,
});
this.imageUrl = tiff.toDataURL("image/jpg")
})
})
}else{
this.imageUrl = this.baseUrl +"/"+ row.img_url
}
},
uploadAllFiles(){
PostData("/dataset/download_dataset",qs.stringify({dataset_type:this.queryData.dataset_type})).then(res=>{
console.log(res)
// //创建a标签
let a = document.createElement('a')
a.href = this.baseUrl+"/"+res.dataset_download_url
a.click()
a.remove()
// let url = this.backAPi+"/"+res.dataset_download_url
// window.open(url)
}).catch(error=>{
console.log(error)
this.$message.error("系统错误")
})
}
},
}
</script>
<style scoped lang="scss">
.data_set {
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 5px;
display: flex;
flex-direction: column;
.header {
width: 100%;
margin: 20px 0px;
text-align: center;
}
.content {
width: 100%;
flex: 1;
.table {
width: 500px;
float: left;
height: 100%;
.table_view{
width: 100%;
height: calc(100% - 85px);
}
.pagination{
text-align: right;
}
}
.image {
margin-left: 510px;
height: 100%;
}
}
.content:after {
content: "";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
}
</style>
\ No newline at end of file
<template>
<div class="home">
<HomeHeader @updataSetting="updataSetting"></HomeHeader>
<div class="content">
<div class="content_show">
<div class="content_show_canvas">
<canvas ref="myCanvas" id="canvas" width="800" height="600"></canvas>
</div>
</div>
<div class="content_operate">
<ImageVue
:confidenceValue="confidenceValue"
:IOUValue="IOUValue"
@openImage="openImage"
@imageFrame="imageFrame"
@uploadeImage="uploadeImage"
@endImage="endImage"
>
</ImageVue>
<hr/>
<VideoVue
:confidenceValue="confidenceValue"
:IOUValue="IOUValue"
@oepnVideo="oepnVideo"
@videoFrame="videoFrame"
@endVideo="endVideo"
></VideoVue>
</div>
</div>
<div style="display: none;">
<image width="800" height="600" ref="img" :src="imageUrl"></image>
</div>
<div style="display: none;">
<video width="800" height="600" ref="vdo" controls :src="videoUrl"></video>
</div>
</div>
</template>
<script>
import HomeHeader from '@/components/header.vue'
import ImageVue from '@/components/image.vue'
import VideoVue from '@/components/video.vue'
export default {
name: "HomeVue",
components:{
HomeHeader,
ImageVue,
VideoVue
},
data() {
return {
confidenceValue:0.7,
IOUValue:0.45,
imageUrl:null,
imageInfo:{
width:0,
height:0,
name:null,
},
videoUrl:null,
videoInfo:{
width:0,
height:0,
name:null,
},
ctxBackground:null,
ctxImage:null,
ctxImageLabel:null,
ctxVideo:null,
labelsColor:{
car:"#0CFF00",//车
pedestrian:"#00D2FF",//人
freighter:"#FFEA00",//货船
houses:"#FF5FF6",//房子
bridge:"#A200FF",//桥
boat:"#00FFE4",//船
}
}
},
created() {
},
mounted() {
this.canvasInit()
},
methods: {
updataSetting(confidenceValue,IOUValue){
this.confidenceValue = confidenceValue
this.IOUValue = IOUValue
},
canvasInit(){
let myCanvas = this.$refs.myCanvas
let ctx = myCanvas.getContext('2d')
ctx.clearRect(0, 0, w, h);
var w = myCanvas.width;
var h = myCanvas.height;
let img = new Image();
img.src = require("@/assets/image/showView.png");
img.onload=()=>{
ctx.fillStyle = ctx.createPattern(img, 'repeat') // 性质相当于css中的background-image
ctx.fillRect(0, 0, w, h) // 最终渲染的位置
}
},
canvasImg() {
// 获取Canvas 画图
let myCanvas = this.$refs.myCanvas
var ctx = myCanvas.getContext('2d')
var w = myCanvas.width;
var h = myCanvas.height;
ctx.clearRect(0, 0, w, h);
// 在Canvas画布 添加图片
let img = new Image()
img.src = this.imageUrl
img.onload =()=>{
this.imageInfo.width = img.width
this.imageInfo.height = img.height
let w = img.width*800/img.width;
let h = img.height*600/img.height;
myCanvas.width = w
myCanvas.height = h
ctx.drawImage(img, 0, 0,w,h)
}
},
openImage(url){
new Promise((resolve, reject) => {
this.imageUrl = url
resolve()
}).then(res=>{
this.canvasImg()
})
},
//图像检测画框
imageFrame(res,loadingInstance){
let myCanvas = this.$refs.myCanvas
var ctx = myCanvas.getContext('2d')
var w = myCanvas.width;
var h = myCanvas.height;
ctx.clearRect(0, 0, w, h);
// 在Canvas画布 添加图片
let img = new Image()
img.src = this.imageUrl
img.onload =()=>{
let rectList = res.results
let labelList = res.labels
this.imageInfo.width = img.width
this.imageInfo.height = img.height
let w = img.width*800/img.width;
let h = img.height*600/img.height;
myCanvas.width = w
myCanvas.height = h
ctx.drawImage(img, 0, 0,w,h);
//位置框框
ctx.beginPath();
ctx.lineWidth = 1;
ctx.font = "20px serif";
for(let i=0;i<rectList.length;i++){
switch(labelList[i]){
case "car":
ctx.strokeStyle = this.labelsColor.car
break
case "pedestrian":
ctx.strokeStyle = this.labelsColor.pedestrian
break
case "freighter":
ctx.strokeStyle = this.labelsColor.freighter
break
case "houses":
ctx.strokeStyle = this.labelsColor.houses
break
case "bridge":
ctx.strokeStyle = this.labelsColor.bridge
break
case "boat":
ctx.strokeStyle = this.labelsColor.boat
break
default:
ctx.strokeStyle = 'red';
}
let x = (800/this.imageInfo.width)*rectList[i][0]
let y = (600/this.imageInfo.height)*rectList[i][1]
let width = (800/this.imageInfo.width)*rectList[i][2] - x;
let height = (600/this.imageInfo.height)*rectList[i][3] - y;
ctx.strokeRect(x, y, width, height);
ctx.strokeText(labelList[i],x,y);
}
}
loadingInstance.close();
},
uploadeImage(name){
console.log(name)
var link = document.createElement("a");
var imgData =canvas.toDataURL({format: 'jpg',});
// var strDataURI = imgData.substr(22, imgData.length);
var blob = this.dataURLtoBlob(imgData);
var objurl = URL.createObjectURL(blob);
link.download = name;
link.href = objurl;
link.click();
},
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});
},
endImage(){
this.canvasInit();
this.imageUrl = null;
},
canvasVideo(){
let myCanvas = this.$refs.myCanvas
var ctx = myCanvas.getContext('2d')
var w = myCanvas.width;
var h = myCanvas.height;
ctx.clearRect(0, 0, w, h);
const videoEl = document.createElement("video");
videoEl.src = this.videoUrl;
videoEl.muted = "muted";
videoEl.autoplay = "autoplay";
videoEl.loop = "loop";
videoEl.play();
// videoEl.addEventListener("loadedmetadata", (event) => {
// console.log(
// "Yay! readyState just increased to " +
// "HAVE_CURRENT_DATA or greater for first time.",
// );
// });
console.log(videoEl.width,videoEl.height)
const videoRender = () => {
window.requestAnimationFrame(videoRender);
ctx.clearRect(0, 0, w, h);
ctx.drawImage(videoEl, 0, 0, w, h);
};
videoRender();
},
oepnVideo(url){
new Promise((resolve, reject) => {
this.videoUrl = url
resolve()
}).then(res=>{
this.canvasVideo()
})
},
videoFrame(res,loadingInstance){
let myCanvas = this.$refs.myCanvas
var ctx = myCanvas.getContext('2d')
var w = myCanvas.width;
var h = myCanvas.height;
ctx.clearRect(0, 0, w, h);
const videoEl = document.createElement("video");
videoEl.src = this.baseUrl +"/" + res.url;
this.videoUrl = this.baseUrl +"/" + res.url;
videoEl.muted = "muted";
videoEl.autoplay = "autoplay";
videoEl.loop = "loop";
videoEl.play();
videoEl.addEventListener("loadeddata", (event) => {
console.log(
"Yay! readyState just increased to " +
"HAVE_CURRENT_DATA or greater for first time.",
);
});
const videoRender = () => {
window.requestAnimationFrame(videoRender);
ctx.clearRect(0, 0, w, h);
ctx.drawImage(videoEl, 0, 0, w, h);
loadingInstance.close();
};
videoRender();
},
endVideo(){
this.canvasInit();
this.videoUrl = null;
}
},
}
</script>
<style scoped lang="scss">
.home {
width: 100%;
height: 100%;
padding: 5px;
box-sizing: border-box;
}
.content {
width: 100%;
.content_show{
width:100%;
height: 600px;
margin-bottom: 20px;
.content_show_canvas{
width: 800px;
height: 600px;
margin: auto;
}
}
.content_operate{
width: 100%;
}
}
</style>
\ No newline at end of file
<template>
<div class="login">
<div class="loginav">
<div class="video">
<video src="../assets/video/video.mp4" muted autoplay loop></video>
</div>
<div class=""></div>
<div class="loginbox boxall">
<div class="logo">
<h1>小型无人机目标检测系统</h1>
<h2>Small UAV target detection system</h2>
</div>
<div class="logintit">用户登录</div>
<ul class="logininput">
<li>
<i><img src="../assets/image/user.png"></i>
<input class="forminput" v-model.trim="userInfo.username" type="text" placeholder="用户名">
</li>
<li>
<i><img src="../assets/image/password.png"></i>
<input class="forminput" type="password" v-model.trim="userInfo.password" placeholder="密码">
</li>
<div class=" flex1" style="padding: 15px 0;">
<label> <input type="checkbox" v-model="rememberPassword" class="aui-checkbox" >&nbsp;记住密码</label>
<a href="#" class="text-primary" @click="register"> 注册新账号</a>
<a href="#" class="text-primary" @click="setBackApiView">后端接口</a>
</div>
<li>
<a href="#" class="btn btnblock btn-lg btn-block btn-primary" @click="login">登录</a>
</li>
</ul>
<div class="boxfoot"></div>
</div>
</div>
<el-dialog
title="后端API设置"
:visible.sync="dialogVisible"
width="30%"
:close-on-click-modal="false"
>
<el-input v-model="backAPi" placeholder="请输入后端网址"></el-input>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="setBackApi()">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { PostData } from '@/api';
import {setCookie } from "@/utils/cookie"
import qs from 'qs';
export default {
data() {
return {
userInfo:{
username:null,
password:null
},
rememberPassword:true,
backAPi:null,
dialogVisible:false,
}
},
created() {
},
mounted(){
let userInfoString = localStorage.getItem('userInfo')
if(userInfoString){
this.userInfo = qs.parse(userInfoString)
}
let backAPi = localStorage.getItem("backapi")
if(backAPi){
this.backAPi = backAPi
}else{
this.backAPi = "http://127.0.0.1:8080"
localStorage.setItem("backapi",this.backAPi);
}
},
methods: {
login(){
if(this.userInfo.username == " " ||this.userInfo.username == null){
this.$message.warning("请输出用户名")
return
}
if(this.userInfo.password == " " ||this.userInfo.password == null){
this.$message.warning("请输入密码")
return
}
PostData("/user/login",qs.stringify(this.userInfo)).then(res=>{
console.log(res)
if(this.rememberPassword){
localStorage.setItem('userInfo',qs.stringify(this.userInfo))
sessionStorage.setItem("X-CSRFToken",res["X-CSRFToken"])
setCookie("csrftoken",res["X-CSRFToken"])
this.$router.push("/home")
}else{
sessionStorage.setItem("crsf_token","")
localStorage.setItem('userInfo',"")
}
}).catch(error=>{
console.log(error)
this.$message.error("登录失败")
})
},
register(){
this.$router.push("/register")
},
setBackApiView(){
this.dialogVisible = true
},
setBackApi(){
localStorage.setItem("backapi",this.backAPi);
this.dialogVisible = false
}
},
}
</script>
<style scoped lang="scss">
li {
list-style-type: none;
}
a {
text-decoration: none;
color: #fff;
}
.login {
background: #000;
max-width: 1920px;
margin: 0 auto;
height: 100%;
position: relative;
font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", "微软雅黑", STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;
}
.login::before {
position: absolute;
width: 100%;
height: 100%;
background: url(../assets/image/bg.png) no-repeat left center;
content: "";
left: 0;
top: 0;
z-index: 100;
pointer-events: none;
}
.loginbg {
background-image: linear-gradient(300deg, #004491, #1e88e5);
position: absolute;
width: 100%;
height: 50%;
left: 0;
top: 0;
z-index: 0
}
.loginav {
max-width: 1300px;
width: 100%;
height: 100%;
margin: 0 auto;
z-index: 10;
box-shadow: 0 0 30px rgba(0, 0, 0, .1);
display: flex;
align-items: center;
justify-content: space-between;
}
.video {
position: absolute;
width: 1200px;
left: 0px;
padding-bottom: 40px;
pointer-events: none;
}
.video video {
width: 100%;
}
.video::before {
position: absolute;
content: "";
width: 200px;
height: 100%;
background: #000;
right: 0;
top: 0;
}
.logotit {
text-align: center;
padding: 40px 0;
font-size: 30px
}
.loginbox {
padding: 30px 0 50px 0;
width: 600px;
padding: 30px 50px;
flex-shrink: 0;
position: relative;
z-index: 100;
}
.logininput .forminput {
border: 2px solid rgba(32, 163, 245, .4);
font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", "微软雅黑", STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;
display: block;
padding-left: 50px;
font-size: 18px;
color: #fff;
width: 100%;
line-height: 48px;
outline: 0;
text-indent: 1px;
background: rgba(32, 163, 245, .1);
}
input::input-placeholder {
color: #fff;
}
::-webkit-input-placeholder {
color: #fff;
}
.flex1 {
display: flex;
justify-content: space-between;
align-items: center;
}
.flex1 label {
color: #fff;
display: flex;
align-items: center;
}
.logininput>li {
display: block;
padding: 15px 0;
position: relative;
}
.logininput li>i {
position: absolute;
height: 100%;
left: 15px;
top: 0;
display: flex;
align-items: center;
}
.logintit {
color: #00bff4;
text-align: center;
position: relative;
padding: 25px 0;
font-size: 24px
}
.btn-primary {
background: #20a3f5;
display: block;
text-align: center;
color: #fff;
line-height: 48PX;
font-size: 24px;
}
.btn-primary:hover {
background: #137bd6
}
.copyright {
position: fixed;
width: 100%;
left: 0;
bottom: 10px;
text-align: center;
color: #006b95;
font-size: 12px
}
.logo {
position: absolute;
top: -120px;
width: 100%;
left: 0;
text-align: center;
color: #fff;
}
.logo h1,
.logo h2 {
background: linear-gradient(90deg, #009ef3, #00e9d0);
background-size: cover;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
text-fill-color: transparent;
}
.logo h1 {
font-weight: bolder;
font-size: 48px;
font-family: "Microsoft YaHei", "HanHei SC";
letter-spacing: 2px;
}
.logo h2 {
font-size: 30px;
text-transform: uppercase;
font-weight: lighter;
letter-spacing: 2px;
}
.boxall {
border: 2px solid #186baf;
background: rgba(32, 163, 245, .1);
position: relative;
transform: scale(.7);
opacity: 0;
animation: shows 1s forwards;
}
@keyframes shows {
to {
transform: scale(1);
opacity: 1;
}
}
.boxall:before,
.boxall:after {
position: absolute;
width: 30px;
height: 30px;
content: "";
border-top: 3px solid #20a3f5;
top: -2px;
}
.boxall:before,
.boxfoot:before {
border-left: 3px solid #20a3f5;
left: -2px;
}
.boxall:after,
.boxfoot:after {
border-right: 3px solid #20a3f5;
right: -2px;
}
.boxfoot {
position: absolute;
bottom: 0;
width: 100%;
left: 0;
}
.boxfoot:before,
.boxfoot:after {
position: absolute;
width: 30px;
height: 30px;
content: "";
border-bottom: 3px solid #20a3f5;
bottom: -2px;
}
.aui-checkbox,
input[type=radio] {
width: 24px;
height: 24px;
background: rgba(32, 163, 245, .1);
border: solid 2px rgba(32, 163, 245, .5);
margin: 0;
padding: 0;
position: relative;
cursor: default;
-webkit-appearance: none;
-webkit-user-select: none;
user-select: none;
-webkit-transition: background-color ease .1s;
transition: background-color ease .1s;
flex-shrink: 0;
border-radius: 0;
}
.aui-checkbox,
input[type=radio] {
margin: 0 3px 0 0 !important;
position: relative;
}
.aui-checkbox:checked,
input[type=radio]:checked {
text-align: center;
background-clip: padding-box;
}
.aui-checkbox:checked:after,
.aui-checkbox:checked:before,
input[type=radio]:checked:after,
input[type=radio]:checked:before {
content: '';
width: 10px;
height: 5px;
position: absolute;
top: 50%;
left: 50%;
margin-left: -6px;
margin-top: -5px;
background: 0 0;
border: 2px solid #439aff;
border-top: none;
border-right: none;
z-index: 2;
-webkit-border-radius: 0;
border-radius: 0;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg)
}
.aui-checkbox:disabled,
input[type=radio]:disabled {
background-color: #f5f5f5;
border: solid 1px #ddd
}
.aui-checkbox:disabled:after,
.aui-checkbox:disabled:before,
input[type=radio]:disabled:after,
input[type=radio]:disabled:before {
content: '';
width: .5rem;
height: .3rem;
position: absolute;
top: 50%;
left: 50%;
margin-left: -.25rem;
margin-top: -.4rem;
background: 0 0;
border: 1px solid #fff;
border-top: none;
border-right: none;
z-index: 2;
-webkit-border-radius: 0;
border-radius: 0;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg)
}
input[type="radio"] {
border-radius: 20px;
}
input {
outline: none !important;
}
@media (max-width: 1200px) {
.loginav {
justify-content: center;
}
.video {
display: none;
}
.loginbox {
width: 96%;
}
.logo h1 {
font-size: 30px;
}
.logo h2 {
font-size: 20px;
}
.loginbox {
padding: 30px;
}
}
</style>
\ No newline at end of file
<template>
<div class="login">
<div class="loginav">
<div class="video">
<video src="../assets/video/video.mp4" muted autoplay loop></video>
</div>
<div class=""></div>
<div class="loginbox boxall">
<div class="logo">
<h1>无人机AI识别系统</h1>
<h2>Drone AI identification system</h2>
</div>
<div class="logintit">用户注册</div>
<ul class="logininput">
<li>
<i><img src="../assets/image/user.png"></i>
<input class="forminput" v-model.trim="userInfo.username" type="text" placeholder="用户名">
</li>
<li>
<i><img src="../assets/image/password.png"></i>
<input class="forminput" type="password" v-model.trim="userInfo.password" placeholder="密码">
</li>
<li>
<a href="#" class="btn btnblock btn-lg btn-block btn-primary" @click="registerAccount">注册</a>
</li>
</ul>
<div class="boxfoot"></div>
</div>
</div>
</div>
</template>
<script>
import { PostData } from '@/api';
import qs from 'qs';
export default {
data() {
return {
userInfo:{
username:"",
password:""
},
}
},
created() {
},
methods: {
registerAccount(){
if(this.userInfo.username == " " ||this.userInfo.username == null){
this.$message.warning("请输出用户名")
return
}
if(this.userInfo.password == " " ||this.userInfo.password == null){
this.$message.warning("请输入密码")
return
}
PostData("/user/register",qs.stringify(this.userInfo)).then(res=>{
this.$message.success("注册成功")
setTimeout(()=>{
this.$router.push("/login")
},2000)
}).catch(error=>{
this.$message.error("注册失败")
})
}
},
}
</script>
<style scoped lang="scss">
li {
list-style-type: none;
}
a {
text-decoration: none;
color: #fff;
}
.login {
background: #000;
max-width: 1920px;
margin: 0 auto;
height: 100%;
position: relative;
font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", "微软雅黑", STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;
}
.login::before {
position: absolute;
width: 100%;
height: 100%;
background: url(../assets/image/bg.png) no-repeat left center;
content: "";
left: 0;
top: 0;
z-index: 100;
pointer-events: none;
}
.loginbg {
background-image: linear-gradient(300deg, #004491, #1e88e5);
position: absolute;
width: 100%;
height: 50%;
left: 0;
top: 0;
z-index: 0
}
.loginav {
max-width: 1300px;
width: 100%;
height: 100%;
margin: 0 auto;
z-index: 10;
box-shadow: 0 0 30px rgba(0, 0, 0, .1);
display: flex;
align-items: center;
justify-content: space-between;
}
.video {
position: absolute;
width: 1200px;
left: 0px;
padding-bottom: 40px;
pointer-events: none;
}
.video video {
width: 100%;
}
.video::before {
position: absolute;
content: "";
width: 200px;
height: 100%;
background: #000;
right: 0;
top: 0;
}
.logotit {
text-align: center;
padding: 40px 0;
font-size: 30px
}
.loginbox {
padding: 30px 0 50px 0;
width: 600px;
padding: 30px 50px;
flex-shrink: 0;
position: relative;
z-index: 100;
}
.logininput .forminput {
border: 2px solid rgba(32, 163, 245, .4);
font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", "微软雅黑", STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;
display: block;
padding-left: 50px;
font-size: 18px;
color: #fff;
width: 100%;
line-height: 48px;
outline: 0;
text-indent: 1px;
background: rgba(32, 163, 245, .1);
}
input::input-placeholder {
color: #fff;
}
::-webkit-input-placeholder {
color: #fff;
}
.logininput>li {
display: block;
padding: 15px 0;
position: relative;
}
.logininput li>i {
position: absolute;
height: 100%;
left: 15px;
top: 0;
display: flex;
align-items: center;
}
.logintit {
color: #00bff4;
text-align: center;
position: relative;
padding: 25px 0;
font-size: 24px
}
.btn-primary {
background: #20a3f5;
display: block;
text-align: center;
color: #fff;
line-height: 48PX;
font-size: 24px;
}
.btn-primary:hover {
background: #137bd6
}
.copyright {
position: fixed;
width: 100%;
left: 0;
bottom: 10px;
text-align: center;
color: #006b95;
font-size: 12px
}
.logo {
position: absolute;
top: -120px;
width: 100%;
left: 0;
text-align: center;
color: #fff;
}
.logo h1,
.logo h2 {
background: linear-gradient(90deg, #009ef3, #00e9d0);
background-size: cover;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
text-fill-color: transparent;
}
.logo h1 {
font-weight: bolder;
font-size: 48px;
font-family: "Microsoft YaHei", "HanHei SC";
letter-spacing: 2px;
}
.logo h2 {
font-size: 30px;
text-transform: uppercase;
font-weight: lighter;
letter-spacing: 2px;
}
.boxall {
border: 2px solid #186baf;
background: rgba(32, 163, 245, .1);
position: relative;
transform: scale(.7);
opacity: 0;
animation: shows 1s forwards;
}
@keyframes shows {
to {
transform: scale(1);
opacity: 1;
}
}
.boxall:before,
.boxall:after {
position: absolute;
width: 30px;
height: 30px;
content: "";
border-top: 3px solid #20a3f5;
top: -2px;
}
.boxall:before,
.boxfoot:before {
border-left: 3px solid #20a3f5;
left: -2px;
}
.boxall:after,
.boxfoot:after {
border-right: 3px solid #20a3f5;
right: -2px;
}
.boxfoot {
position: absolute;
bottom: 0;
width: 100%;
left: 0;
}
.boxfoot:before,
.boxfoot:after {
position: absolute;
width: 30px;
height: 30px;
content: "";
border-bottom: 3px solid #20a3f5;
bottom: -2px;
}
input[type="radio"] {
border-radius: 20px;
}
input {
outline: none !important;
}
@media (max-width: 1200px) {
.loginav {
justify-content: center;
}
.video {
display: none;
}
.loginbox {
width: 96%;
}
.logo h1 {
font-size: 30px;
}
.logo h2 {
font-size: 20px;
}
.loginbox {
padding: 30px;
}
}
</style>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment