概述一下处理逻辑:
点击某个按钮,执行某个函数,该函数打开文件选择器->
将选择的文件转成base64字符串,并通过axios传给后端->
后端接收base64字符串,并将其转换成opencv格式的图片->
opencv格式的图片经过处理得到一个新的opencv格式图片,该图片转成base64字符串->
该base64字符串返回给前端,前端进行渲染
实操:
1. 前端安装必要的库
前端库:axios@1.6.7 qs@6.11.0
2. 页面元素
<img :src="store.img1" style="width:100%" alt="">
<img :src="store.img2" style="width:100%" alt="">
这是两个img标签,src中的img1表示处理前的图片(base64字符串),img2表示处理后的图片(base64字符串)
3. 浏览器选择图片并转化为base64字符串
这里以点击一个按钮为例(这个按钮用一个img标签代替,当然你也可以直接用一个div代替,给这个img或者div一个click事件即可)
<img @click="store.upload" src="./assets/up.png" alt="" height="49px">
点击img,触发upload函数,upload函数:
upload(){
var input = document.createElement('input');input.type = 'file';
input.addEventListener('change',e => {
var file = e.target.files[0];//console.log(file.name,file.type,);
let reader=new FileReader();
reader.readAsDataURL(file)
reader.onload=e=>{
let base64string=e.target.result
this.img1=base64string
console.log(base64string);
axios.post('http://127.0.0.1:8000/test1/upload',qs.stringify({name:base64string}))
.then(response=>{console.log(response.data);this.img2=response.data.msg;})
}
})
input.click();
},
解释一下这个函数的大概逻辑,先创建一个input标签类型为file(那么为什么不直接再页面中创建一个input标签嘞,问就是自带的input标签太丑了。。。,反正只是为了弹出一个文件选择框方便选择文件而已,就用这种方式好了)
接着为这个input标签添加change事件,该事件的回调函数中将选择的文件的第一个存储到变量file中,接着file通过reader.readAsDataURL(file)将file变量转成base64格式的字符串(也就是文件转字符串),转换完成后还有个回调函数onload,里面将这个base64字符串用base64string这个变量进行赋值,并且将base64字符串直接赋值给img1,好让之前的第一个img标签显示原始图片。然后通过axios将base64string传入后端。
这里需要注意一件事,传入给后端的base64数据:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASkAAAEpAQAAAADn4ukvAAA***klEQVR4nO3aQW6jQBSE4b+ACO9gN0t8EzInyVEMNzM3sW8Ai5GMZKhZgOxJVpG***Zg0K9R8clcj6wleI/OJo44+oyCwwAILLLBPs07TsadPLOmVbjfMY7uFs22BpbbtI90O4FDvswuybbeLZ9sCGyRVAENsKJscQNJ+Bdk2xFKPAMV5942TbpglHw***mebtdBn+46Q/h823NzbQQC+grlD6Bwx0C2bbDOslSa+QXmX5WLRgSVK+eLanZvj9cQWg+DBarXkJT8CGCGpJSkd***ZaS8O/9KtbtsGSfMvcRQGH3Ea5ujxCrX8JKWQKQXQaNquui7W8PZPEYaeFsW2GdEst2kxOPyMfpmqvylF0WzrYBNt/DZt9l/fTWJmn6gS4Uh8fZ9LJWTh0GS2ULwOG4gmzPzzopNrX2WZeOTM2H2IZmv3i2DbDMHiS7ydOrxcFNzhChqjwtnu25WQLQ5fHV0Lxm/U6G5q3N8T8PDqtewupZNr2slT7v4kFQnkgdisNXsftuBYAqzjlDBITi8CDDttt5t6JoU4/MJzaUpyz0HB5hc0NySODwm+wyvFhAzlR5i3bBbNtkrihaYptDvf+uSX8E65RY95JbH5qwU/wQe197fdsgnmtv6Pc+xqba28+VlvSaaPrqbHgZAbpfl8WybYBND***7d3zxdJpdGDG3bs+alxBYYIEF9nTsL3d0Co4PuPsxAAAAAElFTkSuQm***
这里是一大段的,需要注意前面有data:image/png;base64,开头,这一大段可以直接赋值给img1,让img标签显示图片。并且需要注意的是“data:image/png;base64,”表示之前选择的图片格式是png,不能是其他格式,那么如果之前选择的是jpg格式的图片,这里应该显示为“data:image/jpg;base64,”
4. django接收base64格式图片
def upload(request):
base64string=request.POST.get("name")
print(base64string)
img = base64.b64decode(base64string.split(',')[1])
img_np = numpy.fromstring(img, dtype='uint8')
new_img_np = cv2.imdecode(img_np, 1)
barcodes=pyzbar.decode(new_img_np)
print("检测到二维码个数:"+str(len(barcodes)))
if len(barcodes):
barcode = barcodes[0]
(x, y, w, h) = barcode.rect
cv2.rectangle(new_img_np, (x, y), (x + w, y + h), (0, 0, 225), 2)
img_str = cv2.imencode('.png', new_img_np)[1].tostring()
b64_code = base64.b64encode(img_str)
print(b64_code)
return JsonResponse({'state':0,"msg":"data:image/png;base64,"+str(b64_code).split("'")[1]})
# cv2.imwrite("./test1/res_imgs/ddd2.png",new_img_np)
return JsonResponse({'state':0,"msg":base64string})
解释一个这个函数,首先获取前端传给我们的base64字符串,并将数据赋值给变量base64string,由于此时这个变量里头是有data:image/png;base64前缀的,转格式之前需要通过base64string.split(',')[1]来去掉前缀,去掉之后再进行转格式,最终将转格式得到的opencv格式的图片用new_img_np来接收。然后就可以对这个new_img_np进行处理了。
由于作者这里是需要实现一个二维码检测,之后将检测图片里面的二维码进行框选,因此执行cv2.rectangle(new_img_np, (x, y), (x + w, y + h), (0, 0, 225), 2)将框框放在new_img_np上面(读者可以进行别的处理),之后对new_img_np进行转格式,得到b64_code这个base64格式的字符串,但是这个字符串如果直接打印是这个样子:
......
前面有b’,后面有个尾巴‘,这两个东东都是不需要的,因此去除,并且加上前缀data:image/png;base64,给返回给前端
5.前端接收base64字符串
这里实际上就涉及第三点的函数了,其中axios发送消息之后还有个回调函数:
直接给img2赋值后端传回来的base64字符串,然后第二个img标签就也可以显示图片了