如何将HTML页面加载的图片传递到Flask应用进行处理
实现方案
核心逻辑是前端把页面已加载的图片转成可传输格式,通过HTTP请求发给Flask接口,后端解码后直接传给PIL/OpenCV处理即可,不需要让用户重复选择文件。
前端实现逻辑
页面中已经加载展示的<img>标签内容,可以通过Canvas导出为可传输格式,有两种常用传输方式:
- 方式1:转Base64字符串通过JSON格式POST发送
假设你页面上预览图片的标签id为previewImg,绑定处理按钮的点击事件即可触发传输:document.getElementById('processBtn').addEventListener('click', async () => { const img = document.getElementById('previewImg'); // 创建和原图尺寸一致的画布 const canvas = document.createElement('canvas'); canvas.width = img.naturalWidth; canvas.height = img.naturalHeight; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); // 导出为base64格式,可按需切换image/jpeg、image/webp等格式 const base64Data = canvas.toDataURL('image/png'); // 发送请求到Flask接口 const resp = await fetch('/process-image', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({image: base64Data}) }); // 接收处理结果,比如返回的处理后图片base64可直接赋值给img标签展示 const result = await resp.json(); document.getElementById('resultImg').src = result.processed_image; }) - 方式2:转Blob文件流通过FormData发送
这种方式后端接收逻辑和普通文件上传完全一致,不需要额外解析Base64,传输大图片时体积更小:canvas.toBlob(async (blob) => { const formData = new FormData(); // 字段名和普通文件上传保持一致即可 formData.append('uploaded_img', blob, 'process.png'); const resp = await fetch('/process-image', { method: 'POST', body: formData }); // 响应处理逻辑和上述方式一致 }, 'image/png');
注意:如果页面展示的图片是跨域资源,Canvas导出时会触发跨域污染报错,这种情况要么给图片源配置CORS规则,要么在用户首次上传图片时就把原始File对象存在全局变量里,直接传原始File对象,不需要从img标签转。
Flask后端实现
先安装依赖:pip install flask pillow opencv-python numpy
- 对应接收Base64参数的接口写法,包含PIL、OpenCV格式转换逻辑:
from flask import Flask, request, jsonify import base64 import numpy as np from PIL import Image import cv2 import io app = Flask(__name__) @app.route('/process-image', methods=['POST']) def process_image(): data = request.get_json() # 去掉base64开头的格式前缀 img_base64 = data['image'].split(',')[1] # 解码为字节流 img_bytes = base64.b64decode(img_base64) # 转PIL可直接处理的格式 pil_img = Image.open(io.BytesIO(img_bytes)) # 转OpenCV可直接处理的格式(注意通道转换:PIL是RGB,OpenCV默认用BGR) cv_img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR) # 在此处编写你的图像处理逻辑即可,以下为灰度化示例 processed_cv = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY) # 处理完成后转回base64返回给前端 _, buffer = cv2.imencode('.png', processed_cv) processed_base64 = 'data:image/png;base64,' + base64.b64encode(buffer).decode('utf-8') return jsonify({'processed_image': processed_base64}) if __name__ == '__main__': app.run(debug=True) - 对应接收FormData文件流的接口写法,和普通文件上传逻辑完全一致:
@app.route('/process-image', methods=['POST']) def process_image_file(): file = request.files['uploaded_img'] img_bytes = file.read() # 后续转PIL、OpenCV格式以及处理逻辑和上述代码完全一致 pil_img = Image.open(io.BytesIO(img_bytes)) cv_img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR) # 自定义处理逻辑... # 返回结果逻辑同上
常见注意点
- 传输高清大图优先选择Blob+FormData的方式,Base64编码会比原文件体积大30%左右
- Canvas导出图片默认会有压缩,如果需要无损画质,直接存用户首次上传时的原始File对象传输即可,不需要走Canvas转换
- 转OpenCV格式时必须做RGB到BGR的通道转换,否则处理后的图片会出现蓝红色调错位
内容的提问来源于stack exchange,提问作者K___V
相关产品推荐
相关产品推荐

