因为项目的原因了解到有一个python的flask框架,查了一下: 关于前端图片上传的canvas: 如下元素
< canvas id = " canvas" width = " 5" height = " 5" > </ canvas>
可以用这样的方式获取一个 data-URL
var canvas
= document
. getElementById ( "canvas" ) ;
var dataURL
= canvas
. toDataURL ( ) ;
console
. log ( dataURL
) ;
// “data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby // blAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC” 设置jpegs图片的质量
var fullQuality
= canvas
. toDataURL ( "image/jpeg" , 1.0 ) ;
var mediumQuality
= canvas
. toDataURL ( "image/jpeg" , 0.5 ) ;
var lowQuality
= canvas
. toDataURL ( "image/jpeg" , 0.1 ) ;
getContext() 方法返回一个用于在画布上绘图的环境。
语法 Canvas.getContext(contextID) 参数 参数 contextID 指定了您想要在画布上绘制的类型。当前唯一的合法值是 “2d”,它指定了二维绘图,并且导致这个方法返回一个环境对象,该对象导出一个二维绘图 API。
提示:在未来,如果 < canvas> 标签扩展到支持 3D 绘图,getContext() 方法可能允许传递一个 “3d” 字符串参数。
返回值 一个 CanvasRenderingContext2D 对象,使用它可以绘制到 Canvas 元素中。 后端: 首先pip install Flask 然后新建文件:
from flask
import Flask
, make_response
, jsonify
from multiprocessing
import Process
app
= Flask
( __name__
)
def run_index ( ) : app
. run
( host
= '0.0.0.0' , port
= 5000 , threaded
= True ) def make_new_response ( data
) : res
= make_response
( jsonify
( { 'code' : 0 , 'data' : data
} ) ) res
. headers
[ 'Access-Control-Allow-Origin' ] = '*' res
. headers
[ 'Access-Control-Allow-Method' ] = '*' res
. headers
[ 'Access-Control-Allow-Headers' ] = '*' return res@app
. route
( '/' )
def hello_world ( ) : return { 'hello' : 'world!' } @app
. route
( "/test" )
def test ( ) : res
= "{'no':'dddd'}" return make_new_response
( res
) if __name__
== "__main__" : app
. run
( debug
= True )
打开浏览器:
向flask后端发请求接收图片:(点击按钮触发事件) flask:
from flask
import Flask
, make_response
, jsonify
from flask_cors
import CORS
import socket
import threading
import json
import os
from io
import BytesIO
from multiprocessing
import Process
import io
from PIL
import Image
app
= Flask
( __name__
)
def main ( ) : serversocket
= socket
. socket
( socket
. AF_INET
, socket
. SOCK_STREAM
) host
= socket
. gethostname
( ) port
= 5000 serversocket
. bind
( ( host
, port
) ) serversocket
. listen
( 5 ) myaddr
= serversocket
. getsockname
( ) print ( "服务器地址:%s" % str ( myaddr
) ) while True : clientsocket
, addr
= serversocket
. accept
( ) print ( "连接地址:%s" % str ( addr
) ) try : t
= ServerThreading
( clientsocket
) t
. start
( ) pass except Exception
as identifier
: print ( identifier
) pass pass serversocket
. close
( ) pass def run_index ( ) : app
. run
( host
= '0.0.0.0' , port
= 5000 , threaded
= True ) CORS
( app
, resources
= r
'/*' , supports_credentials
= True ) basedir
= os
. path
. abspath
( os
. path
. dirname
( __file__
) ) @app
. route
( '/getPic' , methods
= [ 'GET' , 'POST' ] )
def findpic ( ) : img_url
= basedir
+ '/data/tt/b/b_1.png' print ( img_url
) with open ( img_url
, 'rb' ) as f
: a
= f
. read
( ) '''对读取的图片进行处理''' img_stream
= io
. BytesIO
( a
) img
= Image
. open ( img_stream
) imgByteArr
= io
. BytesIO
( ) img
. save
( imgByteArr
, format = 'PNG' ) imgByteArr
= imgByteArr
. getvalue
( ) print ( imgByteArr
) return imgByteArr
if __name__
== "__main__" : app
. run
( debug
= True )
注意:Python在内存中读写数据,用到的模块是StringIO和BytesIO,当为StringIO时getvalue()方法用于获得写入后的str。StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO。可以用一个bytes初始化BytesIO,然后,像读文件一样读取:
>> > from io
import BytesIO
>> > f
= BytesIO
( b
'\xe4\xb8\xad\xe6\x96\x87' )
>> > f
. read
( )
b
'\xe4\xb8\xad\xe6\x96\x87'
BytesIO实现了在内存中读写bytes。
vue代码:
< button @click = " getPic" > 获取图片
</ button> < img :src = " picurl" alt = " beachball" />
data ( ) { return { picurl
: "" , } } , methods
: { getPic ( ) { var that
= this ; this . $axios
. get ( 'http://127.0.0.1:5000/getPic' , { responseType
: "arraybuffer" , } ) . then ( function ( response
) { that
. picurl
= "data:image/jpeg;base64," + that
. arrayBufferToBase64 ( response
. data
) ; } ) ; } , arrayBufferToBase64 ( buffer
) { var binary
= "" ; var bytes
= new Uint8Array ( buffer
) ; var len
= bytes
. byteLength
; for ( var i
= 0 ; i
< len
; i
++ ) { binary
+= String
. fromCharCode ( bytes
[ i
] ) ; } return window
. btoa ( binary
) ; } ,
}
点击按钮后: 后端的显示:
图片传给后端
捣鼓了半天终于把图片传给后端了,不过暂时用的java测试。中途遇到无数次cannot read property xxx xxx is not defined,怀疑是自己哪些代码莫名出了问题,因为canvas是getelementbyid,所以如果写的是ref的话是获取不到的,然后注释掉了一堆代码,结果:
后端的响应:
flask获取图片数据:
flask获取参数方式:
request.form.get(“key”, type=str, default=None) 获取表单数据
request.args.get(“key”) 获取get请求参数
request.values.get(“key”) 获取所有参数
import base64
img1
= 'E:/nsfw_tensorflow/corpus/weibocore_WBC_IMAGE_DATA_SOURCE_6521.jpg' pimg
= open ( img1
, 'rb' ) . read ( ) print ( pimg
) # base64图片加密
result
= base64
. b64encode ( pimg
) print ( result
) # 再把加密后的结果解码
temp
= base64
. b64decode ( result
) print ( temp
)
现在出现一个问题,从前端发送图片之后后端接收到的data一直是str类型,不知道怎么取出来:
@app
. route ( '/getpic' , methods
= [ 'POST' ] )
def
getpic ( ) : data
= flask
. request
. get_data ( ) . decode ( 'utf-8' ) data
= json
. loads ( data
) data_b64
= data
[ "data" ] print ( type ( data_b64
) )
修改:
def
getpic ( ) : data
= json
. loads ( flask
. request
. get_data ( "data" ) ) data_64
= str
. encode ( data
[ 'data' ] ) print ( type ( data_64
) ) print ( data_64
)
得到类型为bytes. 前端去掉base64前面的前缀:
var image
= this . thisCancas
. toDataURL ( "image/png" ) . split ( 'base64,' ) [ 1 ] ;
搞了好久试了好多方法终于把前端的图片base码解出来了!!!!!!激动 后端的代码:
def decode_base64 ( data
) : """Decode base64, padding being optional.:param data: Base64 data as an ASCII byte string:returns: The decoded byte string.""" missing_padding
= len ( data
) % 4 if missing_padding
!= 0 : data
+= b
'=' * ( 4 - missing_padding
) return base64
. b64decode
( data
)
@app
. route
( '/getpic' , methods
= [ 'POST' ] )
def getpic ( ) : data
= json
. loads
( flask
. request
. get_data
( "data" ) ) data_64
= str . encode
( data
[ 'data' ] ) print ( type ( data_64
) ) print ( '------------------------' ) print ( str ( data_64
, 'utf8' ) ) imgdata
= decode_base64
( data_64
) file = open ( '1.jpg' , 'wb' ) file . write
( imgdata
) file . close
( )
其中注意前端发送的数据也经过了处理,使得去掉了img/jpeg前缀
现在载入模型进行拍照预测: 附上关键的代码:
import torch
from torchvision
import transforms
def run_index ( ) : app
. run
( host
= '0.0.0.0' , port
= 5000 , threaded
= True )
def decode_base64 ( data
) : """Decode base64, padding being optional.:param data: Base64 data as an ASCII byte string:returns: The decoded byte string.""" missing_padding
= len ( data
) % 4 if missing_padding
!= 0 : data
+= b
'=' * ( 4 - missing_padding
) return base64
. b64decode
( data
)
transform
= transforms
. Compose
( [ transforms
. Resize
( 224 ) , transforms
. CenterCrop
( 224 ) , transforms
. ToTensor
( ) , transforms
. Normalize
( mean
= [ 0.485 , 0.456 , 0.406 ] , std
= [ 0.229 , 0.224 , 0.225 ] ) ] ) CORS
( app
, resources
= r
'/*' , supports_credentials
= True )
@app
. route
( '/getpic' , methods
= [ 'POST' ] )
def getpic ( ) : data
= json
. loads
( flask
. request
. get_data
( "data" ) ) data_64
= str . encode
( data
[ 'data' ] ) print ( type ( data_64
) ) print ( '------------------------' ) print ( str ( data_64
, 'utf8' ) ) imgdata
= decode_base64
( data_64
) file = open ( '1.jpg' , 'wb' ) file . write
( imgdata
) file . close
( ) image
= Image
. open ( r
"1.jpg" ) . convert
( 'RGB' ) image
= transform
( image
) . unsqueeze
( 0 ) modelme
= torch
. load
( 'modefresnet.pkl' ) modelme
. eval ( ) outputs
= modelme
( image
) _
, predict
= torch
. max ( outputs
. data
, 1 ) for j
in range ( image
. size
( ) [ 0 ] ) : print ( 'predicted: {}' . format ( class_names
[ predict
[ j
] ] ) ) return class_names
[ predict
[ j
] ]
if __name__
== "__main__" : app
. run
( debug
= True )
试了好多次,几乎都与预测结果相符。 哈哈哈哈哈花了两天弄这个,之前关于图片解码编码一直没弄出来,现在成功了还是挺开心的。
总结
以上是生活随笔 为你收集整理的【后端过程记录】用flask搭建服务器作后端接收数据 将base64字符串码解码为可读取文件 载入训练好的模型进行预测 的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得生活随笔 网站内容还不错,欢迎将生活随笔 推荐给好友。