場景說明
在做圖像處理的實驗
前端發送兩張圖片,後端返回 圖片的和
下邊給大家介紹兩種方法
一種不落磁盤法,一種保存再請求
主要就是不落磁盤方法的使用,可以加快請求時間,減少磁盤垃圾產生
存儲磁盤再返回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(() => {})
jquery 綁定函數時的注意事項
正確的綁定方法
$('#fuc2').click(function(){ oneimgchange("Mirror",$('#img1'))});
錯誤的綁定方法
這種綁定方法會直接執行函數,爆出來亂七八糟的錯誤
$('#fuc2').click( oneimgchange("Mirror",$('#img1')));