django和vue互传图片并进行处理和展示
作者:吕大娟
在项目中图片上传并附带几个参数的场景非常常见,如果技术栈是Vue+Django的小伙伴就一定会遇到这个需求,下面这篇文章主要给大家介绍了关于django和vue互传图片并进行处理和展示的相关资料,需要的朋友可以参考下
----------记录一下这两天做的一个小demo
功能是要实现一个从前端传给后端一张图片,在后端完成目标检测后,传给前端,前端接收后并展示。
一、前端上传图片到后端
1、这一部分要用到elelent ui
的upload
组件,代码如下:
view中
<el-upload :action="uploadURL" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :on-success="handlesuccess"> <i class="el-icon-plus"></i> </el-upload> <el-dialog :visible.sync="dialogVisible"> <img width="100%" :src="dialogImageUrl" alt=""> </el-dialog>
method中
handlePictureCardPreview(file) { // 这个“file”里默认包含了这张图片的所有信息:名字,url... console.log("打印下zi",file); this.dialogImageUrl = file.url; this.dialogVisible = true; },
data中
uploadURL:process.env.VUE_APP_BASE_API,
这里边on-preview
是点击文件列表中已上传的文件时的钩子,这个操作只是把本地图片上传到前端并展示到前端页面中了。
2、要把它传给后端的话,action这个钩子需要这么写:
uploadURL:process.env.VUE_APP_BASE_API+"/test_moudle/test/",
也就是说在后边加上路由。
二、后端接收图片并检测
1、首先接收图片
img = request.FILES.get('file')
因为前端传的时候并没有给名字,直接就传过来了,所以就按“file”
名处理。
2、然后要对图片进行检测,由于我的检测代码是写死的,它需要的是一个图片路径,如下所示,
parser.add_argument('--source', type=str, default='windmill/images/test', help='file/dir/URL/glob, 0 for webcam')
所以我没办法把前端传过来的图片直接处理并输入检测网络,最后只能把图片保存一下,然后把保存路径给检测网络:
img = request.FILES.get('file') print('打印名称和类型',type(img),img) base_dir = settings.BASE_DIR upload_dir = os.path.join(base_dir, 'upload') path = os.path.join(upload_dir, img.name) with open(path, 'wb+') as f: for chunk in img.chunks(): f.write(chunk) timestrap = str(time.time())
把路径给检测网络
parser.add_argument('--source', type=str, default=path, help='file/dir/URL/glob, 0 for webcam')
三、把检测完的图片传给前端
这一步需要把图片转为base64形式的才能传给前端
......这里省略了检测代码 res_path = os.path.join(base_dir, 'runs', 'detect', timestrap, img.name) if os.path.exists(res_path): print('有检测结果吧') with open(res_path, 'rb') as f: data = f.read() result['msg'] = bytes.decode(base64.b64encode(data)) else: result['msg'] = '有图片上传但是没有检测结果' else: result['msg'] = '没有图片上传' return JsonResponse(result)
四、前端接收base64图片并展示
<div class="myres"> <img width="20%" :src="'data:image/png;base64,'+detect_picture"> </div>
handlesuccess(response, file, fileList){ console.log("打印下",file,fileList); this.detect_picture = response.msg; },
在这里头接收后端的图片时并处理的钩子是upload
组件中的on-success
(on-success=“handlesuccess”)
然后需要注意的是展示图片时,需要在src(路径)前加'data:image/png;base64,'
:
<img width="20%" :src="'data:image/png;base64,'+detect_picture">
这样一个检测小demo就完成了-----------
完整代码
后端
def test(request): result = {} if request.method == 'POST': #你要关注的 1、从前端接收图片 img = request.FILES.get('file') print('打印名称和类型',type(img),img) base_dir = settings.BASE_DIR # 当前的最高级目录(dvadmin-backend) upload_dir = os.path.join(base_dir, 'upload') # 在主目录下新建文件夹 path = os.path.join(upload_dir, img.name) # 把前端传过来的图片保存在新建的upload文件夹中 with open(path, 'wb+') as f: for chunk in img.chunks(): f.write(chunk) timestrap = str(time.time()) # 从这里开始 parser = argparse.ArgumentParser() # 1、选模型 # parser.add_argument('--weights', nargs='+', type=str, default='runs/train/exp/weights/best.pt', help='model.pt path(s)') parser.add_argument('--weights', nargs='+', type=str, default=r'D:\Desktop\lfj\code\实验结果\expyolov5s原2\weights\best.pt', help='model.pt path(s)') # parser.add_argument('--source', type=str, default='windmill/images/test', help='file/dir/URL/glob, 0 for webcam') parser.add_argument('--source', type=str, default=path, help='file/dir/URL/glob, 0 for webcam') # parser.add_argument('--source', type=str, default=img, help='file/dir/URL/glob, 0 for webcam') # 输入图片的大小 默认640 parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='inference size (pixels)') # 置信度阈值 默认0.25 parser.add_argument('--conf-thres', type=float, default=0.25, help='confidence threshold') # 做Nms的iou阈值 parser.add_argument('--iou-thres', type=float, default=0.45, help='NMS IoU threshold') # 保留的最大检测框数量,每张图片中检测目标的个数最多为1000类 parser.add_argument('--max-det', type=int, default=1000, help='maximum detections per image') # 设置设备CPU/GPU,这个可以不用设置 parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu') # 是否展示预测之后的图片 parser.add_argument('--view-img', action='store_true', help='show results') # 是否将预测的框坐标以txt文件形式保存,默认False,使用save-txt在路径runs/detect/exp/labels/.txt下生成每张图片预测的txt文件 parser.add_argument('--save-txt', action='store_true', help='save results to *.txt') # 是否将置信度conf也保存到txt文件中 parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels') parser.add_argument('--save-crop', action='store_true', help='save cropped prediction boxes') parser.add_argument('--nosave', action='store_true', help='do not save images/videos') # 设置只保留某一部分类别,形如0或者0 2 3 parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 0 2 3') parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS') parser.add_argument('--augment', action='store_true', help='augmented inference') parser.add_argument('--visualize', action='store_true', help='visualize features') parser.add_argument('--update', action='store_true', help='update all models') # 保存测试日志的文件夹路径 parser.add_argument('--project', default='runs/detect', help='save results to project/name') # 用时间戳生成文件夹timestrap 保存测试日志文件夹的名字,所以最终保存在project/name中 parser.add_argument('--name', default=timestrap, help='save results to project/name') # parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment') # 画框的线条粗细--- parser.add_argument('--line-thickness', default=3, type=int, help='bounding box thickness (pixels)') parser.add_argument('--hide-label s', default=False, action='store_true', help='hide labels') parser.add_argument('--hide-conf', default=False, action='store_true', help='hide confidences') parser.add_argument('--half', action='store_true', help='use FP16 half-precision inference') opt = parser.parse_args(args=[]) main(opt) # 到这里结束,这些你都不用管 # 2、图片传给前端 # 找到刚刚检测的图片,并把它转为base64形式,传给前端 res_path = os.path.join(base_dir, 'runs', 'detect', timestrap, img.name) if os.path.exists(res_path): print('有检测结果吧') with open(res_path, 'rb') as f: data = f.read() result['msg'] = bytes.decode(base64.b64encode(data)) else: result['msg'] = '有图片上传但是没有检测结果' else: result['msg'] = '没有图片上传' return JsonResponse(result)
前端
<template> <div class="container"> <!-- <div class="mysel" style="margin-bottom: 20px;"> <el-select v-model="value" placeholder="请选择检测模型" > </el-select> </div> --> <el-upload :action="uploadURL" list-type="picture-card" multiple :limit="6" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :on-success="handlesuccess"> <i class="el-icon-plus"></i> </el-upload> <el-dialog :visible.sync="dialogVisible"> <img width="100%" :src="dialogImageUrl" alt=""> </el-dialog> <el-button icon="" type="text" @click="but_test"> 点击识别 </el-button> <div class="myres"> <img width="20%" :src="'data:image/png;base64,'+detect_picture"> </div> </div> </template> <script> import request from "@/utils/request"; import axios from "axios"; export default { components: { }, data() { return { // 图片要传到服务端的哪里(路由=process.env.VUE_APP_BASE_API+你要传图片的接口) uploadURL:process.env.VUE_APP_BASE_API+"/test_moudle/updateinfo/", // 前端上传的图片的地址 dialogImageUrl: '', dialogVisible: false, // 后端传过来的图片的base64形式 detect_picture: '', queryParams: { ipaddr: undefined, userName: undefined }, }; }, computed: { }, watch: { }, activeId: { }, mounted() { }, created(){ // this.visualize_data() }, methods: { // 测试前后端是否连通的函数 visualize_data() { return request({ url: "/test_moudle/test", //get请求最后没有'/' method: "get", }).then(response=>{ console.log('怎么可以这样',response) }); }, // 处理图片预览效果 handlePreview(){}, // 处理移除图片的操作 handleRemove(file, fileList) { console.log(file, fileList); }, // 点击文件列表中已上传的文件时的钩子 handlePictureCardPreview(file) { // 这个“file”里默认包含了这张图片的所有信息:名字,url... console.log("打印下zi",file); this.dialogImageUrl = file.url; this.dialogVisible = true; }, but_test(){ console.log("这个函数是否执行") this.uploadURL = process.env.VUE_APP_BASE_API+"/test_moudle/test/"; }, // 用这个函数去接收后端传过来的图片 handlesuccess(response, file, fileList){ console.log("打印下",file,fileList); this.detect_picture = response.msg; }, /** 重置按钮操作 */ resetQuery() { this.resetForm("queryForm"); this.handleQuery(); }, /** 搜索按钮操作 */ handleQuery() { this.pageNum = 1; // this.getList(); }, } }; </script>
写了3个demo,前端没变哈哈哈哈,变得只是后端怎么处理图片,怎么传给前端
总结
到此这篇关于django和vue互传图片并进行处理和展示的文章就介绍到这了,更多相关django vue互传图片展示内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!