场景说明
在做图像处理的实验
前端发送两张图片,后端返回 图片的和
下边给大家介绍两种方法
一种不落磁盘法,一种保存再请求
主要就是不落磁盘方法的使用,可以加快请求时间,减少磁盘垃圾产生
存储磁盘再返回url数据的话,也可以直接采用django 自带的方法来实现
不落磁盘法
前端请求代码
#根据imgurl 生成 file function getImageFileFromUrl(url, imageName) { // imageName一定要带上后缀 let p = new Promise((resolve, reject) => { var blob = null; var xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.setRequestHeader('Accept', 'image/jpeg'); xhr.responseType = "blob"; xhr.onload = () => { blob = xhr.response; let imgFile = new File([blob], imageName, {type: 'image/jpeg'}); resolve(imgFile); }; xhr.send(); }); return p; } #插入图片函数 function beforedivimg(div1,name1,img1url){ var box1=div1; var tempdiv1=document.createElement("div") tempdiv1.style="display:flex;justify-content: space-around;align-content: space-around;padding: 15px;width:90%;color:red;font-size:40px;"; var tempimg1=document.createElement("img"); tempimg1.id="img"+imgindex; tempimg1.style="width:100%;" tempimg1.src=img1url; var inf01=name1; tempdiv1.append(inf01,tempimg1); box1.prepend(tempdiv1) } #执行函数 $('#fuc1').click(function () { var formdata= new FormData(); var blobimg1='' var blobimg2='' var p1=getImageFileFromUrl($('#img1')[0].src,"img1.jpg") p1.then((file1) => { var p2=getImageFileFromUrl($('#img2')[0].src,"img2.jpg") p2.then((file2) => { blobimg1=file1 blobimg2=file2 formdata.append('img1',blobimg1) formdata.append('img2',blobimg2) $.ajax({ cache: false, type: 'POST', // 根据表单id 生成数据 data: formdata, url: "/dealimg/addtwoimg/", traditional:true, //为必须内容 //dataType:'json', //data为json时必须 processData: false, //为必须内容 contentType: false, //为必须内容 success: function(data) { var imgsrc = "data:image/jpeg;base64," + data; beforedivimg($('#dropBox'),"处理结果",imgsrc) }, beforeSend: function(xhr, settings) { xhr.setRequestHeader("X-CSRFToken", '{{ csrf_token }}'); } }); }).then(() => {}) }).then(() => {}) });
后端代码
def addtwoimg(request): if request.method== "POST": # <class 'django.core.files.uploadedfile.InMemoryUploadedFile'> fileinmemory1,fileinmemory2=request.FILES.get('img1'),request.FILES.get('img2') # 将上传的 二进制 图片数据,转化为 cv2 格式 cv2img1,cv2img2=getNdarraybyInMemoryUploadedFile(fileinmemory1),getNdarraybyInMemoryUploadedFile(fileinmemory2) print(cv2img1.shape) img1height,img1width,_=cv2img1.shape cv2img2=cv2.resize(cv2img2, ( img1width, img1height)) img_add = cv2.addWeighted(cv2img1, 0.5, cv2img2, 0.5, 0) return HttpResponse(getbase64byndarray(img_add),content_type='image/jpeg')
落磁盘法
很简单,后端保存图片,前台根据 返回的url 再去自己请求加载
前台改动 ajax 返回函数即可
success: function(data) { data=JSON.parse(data); console.log(typeof(data)) beforedivimg($('#dropBox'),"处理结果",data.resultimgurl) },
后台直接返回url链接即可
def addtwoimg(request): if request.method== "POST": # <class 'django.core.files.uploadedfile.InMemoryUploadedFile'> fileinmemory1,fileinmemory2=request.FILES.get('img1'),request.FILES.get('img2') # 将上传的 二进制 图片数据,转化为 cv2 格式 cv2img1,cv2img2=getNdarraybyInMemoryUploadedFile(fileinmemory1),getNdarraybyInMemoryUploadedFile(fileinmemory2) print(cv2img1.shape) img1height,img1width,_=cv2img1.shape cv2img2=cv2.resize(cv2img2, ( img1width, img1height)) img_add = cv2.addWeighted(cv2img1, 0.5, cv2img2, 0.5, 0) cv2.imwrite('static/img/addtwoimg.jpg',img_add) return HttpResponse(json.dumps({"info":"成功","resultimgurl":"/static/img/addtwoimg.jpg"},ensure_ascii=False))
关于从前台获取图片二进制后,后台的处理
我们从 request.FILES 中取出的数据类型是InMemoryUploadedFile
# <class '_io.BytesIO'> fileinbytes=fileinmemory.file img_np_arr = np.frombuffer(fileinbytes.read(), np.uint8) # <class 'numpy.ndarray'> return cv2.imdecode(img_np_arr, cv2.IMREAD_COLOR)
InMemoryUploadedFile --》 io.BytesIO -》 numpy.ndarray
numpy.ndarray 就是 opencv 直接处理的数据类型
import base64 import numpy as np import cv2 def getNdarraybyInMemoryUploadedFile(fileinmemory): # <class '_io.BytesIO'> fileinbytes=fileinmemory.file img_np_arr = np.frombuffer(fileinbytes.read(), np.uint8) # <class 'numpy.ndarray'> return cv2.imdecode(img_np_arr, cv2.IMREAD_COLOR) def getbase64byndarray(pic_img): retval, buffer = cv2.imencode('.jpg', pic_img) pic_str = base64.b64encode(buffer) return pic_str.decode()
js中 promise 对象使用
js promise 可以保证 程序的顺序执行,只有 promise 执行完成之后,
才会去执行, promise.then 函数
#创建对象 let p = new Promise((resolve, reject) => { } #使用回调函数,先成功回调,再失败回调 p1.then((value) => { }).then(() => {})
query 绑定函数时的注意事项
正确的绑定方法
$('#fuc2').click(function(){ oneimgchange("Mirror",$('#img1'))});
错误的绑定方法
这种绑定方法会直接执行函数,爆出来乱七八糟的错误
$('#fuc2').click( oneimgchange("Mirror",$('#img1')));