html调用电脑/手机摄像头拍照上传+百度文字识别

1、需求

  利用电脑、手机摄像头对某零件拍照提取上面的文字(电脑我只用chrome测试过)

2、前端

Ps:id='data'的值就是base64,可通过post请求传到后端

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<html lang="en">
<head>
    <title>电脑摄像头拍照&文字识别</title>
</head>
<body>
<table border="1px">
    <tr>
        <td>
            <video id="video" width="320px" height="240px" autoplay="autoplay"></video>
        </td>
    </tr>
    <tr>
        <td>
            <canvas id="canvas" width="320px" height="240px"></canvas>
        </td>
    </tr>
    <tr>
        <td>
            <input type="text" value="" id="data" hidden>
            <input type="button" title="开启摄像头" value="开启摄像头" onclick="getMedia()"/>&nbsp;&nbsp;&nbsp;
            <button type="button" id="snap" onclick="takePhoto()">拍照</button>&nbsp;&nbsp;&nbsp;
            <input type="button" title="关闭摄像头" value="关闭摄像头" onclick="closeCamera()"/>
        </td>
    </tr>
</table>
<script>
    //获得video摄像头区域
    var buffer;
    var video = document.getElementById("video");

    function getMedia() {
        navigator.mediaDevices.enumerateDevices()
            .then(function (devices) {
                devices.forEach(function (device) {
                    //打印电脑上的设备类型、设备名称、设备ID
                    console.log(device.kind + ":" + device.label + "  id=" + device.deviceId);
                });
            }).catch(function (err) {
            console.log(err.name + ":" + err.message);
        });

        var constraints = {
            video: {facingMode: {exact: "environment"}},
            audio: false
        };
        /*
        这里介绍新的方法:H5新媒体接口 navigator.mediaDevices.getUserMedia()
        这个方法会提示用户是否允许媒体输入,(媒体输入主要包括相机,视频采集设备,屏幕共享服务,麦克风,A/D转换器等)
        返回的是一个Promise对象。
        如果用户同意使用权限,则会将 MediaStream对象作为resolve()的参数传给then()
        如果用户拒绝使用权限,或者请求的媒体资源不可用,则会将 PermissionDeniedError作为reject()的参数传给catch()
        */
        var promise = navigator.mediaDevices.getUserMedia(constraints);
        promise.then(function (MediaStream) {
            buffer = MediaStream;
            video.srcObject = MediaStream;
            video.play();
        }).catch(function (PermissionDeniedError) {
            console.log(PermissionDeniedError);
        })
    }

    function takePhoto() {
        //获得Canvas对象
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext('2d');
        ctx.drawImage(video, 0, 0, 320, 240);
        var str = canvas.toDataURL("image/jpeg");
        document.getElementById("data").value = (str.substr(str.indexOf(",") + 1));
    }

    function closeCamera() {
        buffer && buffer.getTracks()[1].stop();//关闭摄像头
    }
</script>
</body>
</html>

Ps:调用手机摄像头拍照上传,仅部分手机浏览器支持,比如QQ、UC;电脑浏览器可选择磁盘路径下的图片

<input type="file" style="text-align: center" onchange="showPic(event)" accept="image/*"  multiple>

<script>
        var formData;
        var xm;
        var cnt = 0;

        window.onload = function () {
            formData = new FormData();
            cnt = 0;
        };


        //图片压缩
        function photoCompress(file, callback){
            var reader=new FileReader();
            reader.readAsDataURL(file);
            reader.onload=function(){
                var path=this.result;
                canvasDataURL(path, callback)
            }
        }

        function canvasDataURL(path, callback){
            var img = new Image();
            img.src = path;
            img.onload = function(){
                var that = this;
                // 默认按比例压缩
                var w = that.width*0.5;
                var h = that.height*0.5;
                var quality = 0.5;  // 默认图片质量为0.7
                //生成canvas
                var canvas = document.createElement('canvas');
                var ctx = canvas.getContext('2d');
                // 创建属性节点
                var anw = document.createAttribute("width");
                anw.nodeValue = w;
                var anh = document.createAttribute("height");
                anh.nodeValue = h;
                canvas.setAttributeNode(anw);
                canvas.setAttributeNode(anh);
                ctx.drawImage(that, 0, 0, w, h);
                // quality值越小,所绘制出的图像越模糊
                var base64 = canvas.toDataURL('image/jpeg', quality);
                // 回调函数返回base64的值
                callback(base64);
            }
        }

        //图片压缩,并在页面上显示(预览)
        function showPic(e) {
            var files = e.target.files;
            for (var i = 0; i < files.length; i++) {
                photoCompress(files[i],function (base64) {
                    formData.append(xm+cnt, base64.substr(base64.indexOf(",")+1));
                    cnt++;
                });
            }
        }

        function Submit() {
            formData.append("xm", xm);
            formData.append("num", cnt);
            var url="***********";
            $.ajax({
                url : url,
                data :  formData,
                processData : false,
                contentType : false,
                dataType: 'json',
                type : "POST",
                success : function(data){
                    if(data.msg != "") {
                        alert(data.msg);
                    } else {
                        alert("上传成功");
                    }
                    location.reload(true);
                }
            });
        }
    </script>

3、后端(百度文字识别建议去百度智能云查看相关文档以及下载所需SDK)

String pic = request.getParameter("pic");
		String wlh = request.getParameter("wlh");
		Calendar cal = Calendar.getInstance();
		int day = cal.get(Calendar.DATE);
		int month = cal.get(Calendar.MONTH) + 1;
		int year = cal.get(Calendar.YEAR);
        net.sf.json.JSONObject jobj = new net.sf.json.JSONObject();

		String path = "";
		if(System.getProperties().getProperty("os.name").toLowerCase().indexOf("win") != -1) {
			path = "F:\\"+year+"\\"+month+"\\"+day;
		} else {
			path = DomGetServer.getDocBase("/zcjy")+"/"+year+"/"+month+"/"+day;
		}

		createDir(path);
		boolean b = generateImage(pic, path, wlh);
		if(b == false) {
			msg = "图片上传失败";
		} else {
			path = path+"/"+wlh+".jpg";
			OcrUtil ocrUtil = new OcrUtil();
			JSONObject json = ocrUtil.client.handwriting(path, new HashMap<String, String>());
			JSONArray res = json.getJSONArray("words_result");
			for (int i = 0; i < res.length(); i++) {
				JSONObject o = (JSONObject) res.get(i);
				msg += o.get("words");
				if(i != res.length()-1) {
					msg += "/";
				}
			}
		}
public static boolean generateImage(String imgStr,String path,String name) {
        //对字节数组字符串进行Base64解码并生成图片
        if (imgStr == null) {
            return false;
        }

        BASE64Decoder decoder = new BASE64Decoder();
        try {
            byte[] b = decoder.decodeBuffer(imgStr);
            for(int i=0;i<b.length;++i) {
                if(b[i]<0) {
                    b[i]+=256;
                }
            }
            String imgFilePath = path+"/"+name+".jpg";
            OutputStream out = new FileOutputStream(imgFilePath);
            out.write(b);
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            System.out.println("===========图片上传异常==========");
            e.printStackTrace();
            System.out.println("===========图片上传异常==========");
            return false;
        }
    }

    /**
     * 递归创建文件夹
     * @param destDirName
     * @return
     */
    public static boolean createDir(String destDirName) {
        File dir = new File(destDirName);
        if (dir.exists()) {
            return false;
        }
        if (dir.mkdirs()) {
            return true;
        } else {
            return false;
        }
    }
import com.baidu.aip.ocr.AipOcr;

/**
 * 百度文字识别
 * @author pxChen
 * @date 2020/8/24
 */
public class OcrUtil {
    //设置APPID/AK/SK
    public static final String APP_ID = "2220****";
    public static final String API_KEY = "XWoPNcxUgjDQTzzI3kq5****";
    public static final String SECRET_KEY = "mRZ0ThKrSAQM4ZGiUGtCYze*********";
    public AipOcr client;

    public OcrUtil() {
        // 初始化一个AipOcr
        client = new AipOcr(APP_ID, API_KEY, SECRET_KEY);

        // 可选:设置网络连接参数
        client.setConnectionTimeoutInMillis(2000);
        client.setSocketTimeoutInMillis(60000);

        // 可选:设置代理服务器地址, http和socket二选一,或者均不设置
        //client.setHttpProxy("proxy_host", proxy_port);  // 设置http代理
        //client.setSocketProxy("proxy_host", proxy_port);  // 设置socket代理

        // 可选:设置log4j日志输出格式,若不设置,则使用默认配置
        // 也可以直接通过jvm启动参数设置此环境变量
        //System.setProperty("aip.log4j.conf", "path/to/your/log4j.properties");
    }
}

4、调用电脑摄像头前提条件

通过 MediaDevices.getUserMedia() 获取用户多媒体权限,其只使用关于以下三种情况: localhost 域 开启了; HTTPS 的域 使用; file:/// 协议打开的本地文件

如果在一个 HTTP 站点上,navigator.mediaDevices 的值为 undefined。 想要 HTTP 环境下也能使用和调试 MediaDevices.getUserMedia(),可通过开启 Chrome 的相应参数。

* 在桌面浏览器快捷方式上右键->属性->快捷方式->目标里添加:--unsafely-treat-insecure-origin-as-secure="http://******.com"

与原本内容之间需间隔一个空格,如有多个网址,也以空格隔开


*打开浏览器地址栏,输入chrome://flags/#unsafely-treat-insecure-origin-as-secure,将该 flag 切换成 enable 状态,输入框中填写需要开启的域名,譬如 http://example.com",多个以逗号分隔,重启后生效。

 

 

<think>好的,用户想用树莓派和百度API实现摄像头文字识别。首先,我得回忆一下相关的步骤。首先可能需要配置树莓派的摄像头模块,比如CSI摄像头,确保它能正常拍照。然后安装必要的库,比如Python的requests库用来发送HTTP请求,还有picamera库用来控制摄像头。 接下来,用户需要注册百度智能云账号,创建一个OCR应用,获取API Key和Secret Key,这些是调用API的凭证。然后要获取访问令牌(access_token),这通常是通过发送POST请求到百度的认证地址,用API Key和Secret Key换取的。 然后,编写Python脚本,用picamera拍摄照片保存为图片文件,再读取图片的二进制数据,进行base64编码。之后构造请求参数,包括图像数据和其他可选参数,比如识别语言类型。发送POST请求到百度OCR的API地址,带上access_token和图像数据。 收到响应后,解析返回的JSON数据,提取识别出的文字结果。可能需要处理错误情况,比如网络问题或者API返回的错误码。 还要考虑树莓派的环境配置,比如安装依赖库,确保摄像头已经启用。可能需要参考引用中提到的树莓派CSI摄像头配置步骤。另外,百度OCR的准确率和速度可能受图像质量影响,所以可能需要调整摄像头的拍摄参数,比如分辨率、对比度,或者对图像进行预处理,比如二值化、降噪,以提高识别率。 用户可能遇到的问题包括摄像头无法启动,API认证失败,图像传输问题,或者识别结果不准确。需要检查摄像头连接,确认API密钥正确,检查网络连接,以及优化图像质量。 另外,引用里提到OCR的应用场景,比如票据、文档识别,用户可能需要根据具体应用调整参数,比如识别特定语言或格式。还有可能涉及到处理返回结果的结构,比如按行或段落组织文本。 最后,整理步骤,给出详细的代码示例,并提醒用户替换自己的API Key和Secret Key,确保代码可运行。同时,提供常见问题的解决方法,比如安装依赖库,处理图像大小限制等。</think>### 分步实现树莓派调用百度OCR API进行摄像头文字识别 #### 一、准备工作 1. **硬件配置** - 树莓派(建议4B及以上型号) - CSI摄像头模块或USB摄像头(需支持`picamera`库) - 网络连接(用于API调用) 2. **软件依赖安装** ```bash sudo apt-get update sudo apt-get install python3-pip pip3 install requests picamera pillow ``` 3. **百度API账号配置** - 登录[百度智能云](https://cloud.baidu.com/) - 创建文字识别应用,获取`API Key`和`Secret Key`[^1] --- #### 二、核心代码实现 ```python import requests import base64 import time from picamera import PiCamera # 百度API配置 API_KEY = "替换为你的API_KEY" SECRET_KEY = "替换为你的SECRET_KEY" TOKEN_URL = "https://aip.baidubce.com/oauth/2.0/token" OCR_URL = "https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic" def get_access_token(): params = { "grant_type": "client_credentials", "client_id": API_KEY, "client_secret": SECRET_KEY } response = requests.post(TOKEN_URL, params=params).json() return response["access_token"] def capture_image(): with PiCamera() as camera: camera.resolution = (1024, 768) camera.start_preview() time.sleep(2) # 摄像头预热 image_path = "/tmp/capture.jpg" camera.capture(image_path) return image_path def ocr_recognition(image_path, access_token): with open(image_path, "rb") as f: image_data = base64.b64encode(f.read()).decode("utf-8") headers = {"Content-Type": "application/x-www-form-urlencoded"} payload = { "access_token": access_token, "image": image_data, "language_type": "CHN_ENG" # 中英文混合识别 } response = requests.post(OCR_URL, headers=headers, data=payload) return response.json() if __name__ == "__main__": token = get_access_token() img_path = capture_image() result = ocr_recognition(img_path, token) if "words_result" in result: for item in result["words_result"]: print(item["words"]) else: print("识别失败:", result) ``` --- #### 三、关键步骤说明 1. **图像采集优化** - 分辨率建议:$1024 \times 768$(平衡清晰度与处理速度) - 使用`camera.start_preview()`可实时预览拍摄画面 - 通过调整`camera.contrast`参数改善文字对比度 2. **API参数说明** ```python { "detect_direction": "true", # 检测图像旋转角度 "probability": "true" # 返回置信度 } ``` 可在`payload`中添加增强参数[^1] 3. **识别结果处理** - 标准返回格式: $$ \text{JSON结构} = \begin{cases} \text{words_result: 识别结果列表} \\ \text{words_result_num: 识别结果数} \\ \text{log_id: 请求唯一标识} \end{cases} $$ --- #### 四、典型问题解决方案 1. **图像模糊导致识别率低** - 增加摄像头预热时间:`time.sleep(3)` - 使用数字图像增强技术: ```python camera.awb_mode = 'sunlight' # 设置白平衡模式 camera.exposure_mode = 'spotlight' # 曝光模式 ``` 2. **API调用频率限制** - 免费版QPS限制为2次/秒 - 建议添加错误重试机制: ```python import time def safe_ocr_call(): for _ in range(3): try: return requests.post(...) except Exception as e: time.sleep(1) return None ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值