当前位置: 首页 > news >正文

腾讯云OCR车牌识别实践:从图片上传到车牌识别

在当今智能化和自动化的浪潮中,车牌识别(LPR)技术已经广泛应用于交通管理、智能停车、自动收费等多个场景。腾讯云OCR车牌识别服务凭借其高效、精准的识别能力,为开发者提供了强大的技术支持。本文将介绍如何利用腾讯云OCR车牌识别服务,结合Spring Boot框架实现一个车牌识别的完整实践,包括图片上传、车牌识别、结果返回及前端展示。

零元试用OCR

本文提要

  • 什么是腾讯云OCR车牌识别服务
  • 项目需求分析
  • 环境准备
  • 后端实现
    • 使用Spring Boot实现图片上传
    • 调用腾讯云OCR车牌识别API
    • 处理车牌识别结果
  • 前端实现
    • 图片上传与预览
    • 显示车牌识别结果
  • 总结与优化建议

1. 什么是腾讯云OCR车牌识别服务

车牌识别(License Plate Recognition, LPR)是一种基于图像处理和人工智能算法的技术,主要用于通过图片识别车牌信息。腾讯云OCR车牌识别API提供了便捷的接口,能够自动识别图片中的车牌信息,返回车牌号、车牌类型等相关数据,广泛应用于智能交通、自动停车系统、无人驾驶等领域。

腾讯云OCR车牌识别服务的主要特点:

  • 高准确率:能够精准识别车牌号,即便在不同光照、角度下也能够提供较高的识别率。
  • 支持多种车牌:支持国内车牌和部分国际车牌类型。
  • 云端计算:通过腾讯云强大的计算能力,提供高效的处理速度。

我们可以通过调用腾讯云提供的API,将车牌图片传送至云端进行识别,返回车牌信息,便于开发者在自己的项目中集成。


2. 项目需求分析

本项目的目标是创建一个基于Spring Boot的车牌识别应用,实现以下功能:

  • 用户通过Web界面上传车辆照片。
  • 系统调用腾讯云OCR车牌识别API,识别车牌信息。
  • 返回车牌号,并在页面上显示识别结果。

技术栈:

  • 前端:HTML、CSS、JavaScript、Bootstrap
  • 后端:Spring Boot(用于处理图片上传和API调用)
  • 腾讯云API:腾讯云OCR车牌识别API
  • 数据库:暂时不使用数据库,但可以扩展以存储识别的车牌号(例如,存入MySQL)

3. 环境准备

在开始编写代码之前,我们需要完成一些环境准备工作:

a. 注册腾讯云账号并开通OCR服务

  1. 访问腾讯云官网并注册账户:腾讯云官网.
  2. 登录后进入控制台,搜索“OCR车牌识别”,并开通API。
  3. 获取API密钥(SecretId和SecretKey),这将用于后端调用腾讯云OCR API。

b. 创建Spring Boot项目

我们可以使用Spring Boot快速创建一个Web应用来实现这个车牌识别功能。可以使用Spring Initializr(https://start.spring.io/)来创建项目。

  • 选择依赖:Spring Web、Spring Boot DevTools、Spring Boot Actuator(可选)。

c. 安装并配置腾讯云SDK

  • 安装腾讯云SDK:使用Maven管理依赖,编辑pom.xml文件:
		<!--# 版本在maven生效需要时间,如获取不到对应的版本,可以调低版本号--><dependency><groupId>com.tencentcloudapi</groupId><artifactId>tencentcloud-sdk-java-ocr</artifactId><version>3.1.1137</version></dependency>
  • 配置腾讯云API密钥:在application.properties文件中配置腾讯云API的密钥:
tencentcloud.secretId=your_secret_id
tencentcloud.secretKey=your_secret_key

4. 后端实现

a. 使用Spring Boot实现图片上传

我们将使用Spring Boot的MultipartFile来处理图片上传。创建一个ImageController类,负责接收前端上传的图片并保存。并调用腾讯云的车牌识别API。接收图片的Base64编码,将其发送到腾讯云OCR API进行车牌识别,并返回识别结果。

package com.example.demo.controller;import com.tencentcloudapi.common.AbstractModel;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.ocr.v20181119.OcrClient;
import com.tencentcloudapi.ocr.v20181119.models.LicensePlateOCRRequest;
import com.tencentcloudapi.ocr.v20181119.models.LicensePlateOCRResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.util.Base64Utils;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;@Controller
public class ImageOCRController {// 图片存储路径private static final String UPLOAD_DIR = "src/main/resources/static/uploads/";@GetMapping("/")public String ocrPage() {return "ocr"; // 返回上传页面视图}// 图片上传接口@PostMapping("/api/image/upload")public String uploadImage(@RequestParam("file") MultipartFile file, HttpSession session) {try {// 确保上传目录存在Path uploadPath = Paths.get(UPLOAD_DIR);if (!Files.exists(uploadPath)) {Files.createDirectories(uploadPath);}// 获取文件输入流并存储文件Path filePath = uploadPath.resolve(file.getOriginalFilename());try (InputStream inputStream = file.getInputStream()) {Files.copy(inputStream, filePath, StandardCopyOption.REPLACE_EXISTING);}// 将上传的图片文件转换为Base64byte[] fileBytes = Files.readAllBytes(filePath);String base64Encoded = Base64Utils.encodeToString(fileBytes);// 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密// 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取Credential cred = new Credential("SecretId", "SecretKey");// 实例化一个http选项,可选的,没有特殊需求可以跳过HttpProfile httpProfile = new HttpProfile();httpProfile.setEndpoint("ocr.tencentcloudapi.com");// 实例化一个client选项,可选的,没有特殊需求可以跳过ClientProfile clientProfile = new ClientProfile();clientProfile.setHttpProfile(httpProfile);// 实例化要请求产品的client对象,clientProfile是可选的OcrClient client = new OcrClient(cred, "ap-beijing", clientProfile);// 实例化一个请求对象,每个接口都会对应一个request对象LicensePlateOCRRequest req = new LicensePlateOCRRequest();req.setImageBase64(base64Encoded);// 返回的resp是一个LicensePlateOCRResponse的实例,与请求对象对应LicensePlateOCRResponse resp = client.LicensePlateOCR(req);// 输出json格式的字符串回包System.out.println(AbstractModel.toJsonString(resp));session.setAttribute("color", resp.getColor());session.setAttribute("number", resp.getNumber());// 上传成功后,返回当前页面return "redirect:/";} catch (Exception e) {e.printStackTrace();return "Error uploading file";}}// 图片预览接口@GetMapping("/api/image/preview")public String previewImage(@RequestParam("fileName") String fileName) {try {Path filePath = Paths.get(UPLOAD_DIR, fileName);byte[] fileBytes = Files.readAllBytes(filePath);return "data:image/png;base64," + Base64Utils.encodeToString(fileBytes);} catch (IOException e) {e.printStackTrace();return "Error previewing file";}}
}

调试一下,看下接口返回值:

请在此添加图片描述


5. 前端实现

前端的任务是让用户上传图片,并显示车牌号。

a. 图片上传与预览

我们使用HTML和Bootstrap来创建一个简洁的上传界面。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>车牌识别</title><!-- 引入Bootstrap CSS --><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body><div class="container mt-5"><h2 class="text-center mb-4">上传车牌</h2><!-- 图片上传表单 --><form method="post" enctype="multipart/form-data" action="/api/image/upload" id="uploadForm"><div class="mb-3"><label for="file" class="form-label">Choose an Image</label><input type="file" class="form-control" name="file" id="file" required></div><button type="submit" class="btn btn-primary w-100">Upload Image</button></form><!-- 图片预览 --><div id="previewContainer" class="text-center"><p th:text="${color}" class="text-center"></p><p th:text="${number}" class="text-center"></p></div><!-- 展示图片名称 --><div th:if="${session.color != null}"><h3 class="mt-4">识别结果</h3><p>车牌颜色: <span th:text="${session.color}"></span></p><p>车牌号码: <span th:text="${session.number}"></span></p></div>
</div><!-- 引入Bootstrap JS和Popper.js -->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.min.js"></script></body>
</html>

b. 显示车牌识别结果

当用户上传图片并完成车牌识别后,页面将自动显示车牌号。

    <div th:if="${session.color != null}"><h3 class="mt-4">识别结果</h3><p>车牌颜色: <span th:text="${session.color}"></span></p><p>车牌号码: <span th:text="${session.number}"></span></p></div>

6. 效果展示

请在此添加图片描述

请在此添加图片描述

7. 部署轻量云服务器

功能完成以后,我们可以将腾讯云OCR车牌识别功能打包部署到轻量云服务器(Lighthouse),可以实现车牌识别的服务化,并便于集成到其他应用中。

# 使用官方 OpenJDK 作为基础镜像
FROM openjdk:11-jre-slim
# 设置环境变量,避免容器内部日志缓冲
ENV SPRING_PROFILES_ACTIVE=prod
# 设置工作目录
WORKDIR /app
# 复制本地项目中的 JAR 文件到容器中
COPY target/ocr-demo-1.0.0.jar /app/ocr-demo.jar
# 容器启动时运行的命令,启动 Spring Boot 应用
CMD ["java", "-jar", "ocr-demo.jar"]
# 暴露应用运行的端口
EXPOSE 8080

请在此添加图片描述

8. 总结与优化建议

我们完成了一个基于腾讯云OCR车牌识别的应用,涵盖了图片上传、车牌识别、识别结果返回和前端展示等关键步骤。当然我们还有很多可以优化的功能点,例如:

  • 错误处理:当前实现中,上传图片或调用API时,错误信息只是简单地打印。可以进一步优化错误处理,提供更加友好的用户反馈。
  • 性能优化:车牌识别服务调用可能会引起一定的延迟,可以考虑在上传和识别过程中加入加载动画,提高用户体验。
  • 安全性:目前代码中的腾讯云API密钥是硬编码的,建议将其存储在更安全的位置,例如环境变量或配置文件中。

相关文章:

腾讯云OCR车牌识别实践:从图片上传到车牌识别

在当今智能化和自动化的浪潮中&#xff0c;车牌识别&#xff08;LPR&#xff09;技术已经广泛应用于交通管理、智能停车、自动收费等多个场景。腾讯云OCR车牌识别服务凭借其高效、精准的识别能力&#xff0c;为开发者提供了强大的技术支持。本文将介绍如何利用腾讯云OCR车牌识别…...

TailwindCss 总结

目录 一、简介 二、盒子模型相关 三、将样式类写到一个类里面apply 四、一款TailWind CSS的UI库 一、简介 官方文档&#xff1a;Width - TailwindCSS中文文档 | TailwindCSS中文网 Tailwind CSS 的工作原理是扫描所有 HTML 文件、JavaScript 组件以及任何 模板中的 CSS 类…...

Java与C#

Java和C#&#xff08;C Sharp&#xff09;是两种流行的面向对象编程语言&#xff0c;它们在很多方面非常相似&#xff0c;因为它们都受到了类似的编程范式和语言设计理念的影响。然而&#xff0c;它们之间也存在一些重要的区别。 平台依赖性&#xff1a; Java&#xff1a;Java是…...

leetcode:222完全二叉树的节点个数

给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面一层的节点都集中在该层最左边的若干位置。若最…...

[STM32]从零开始的STM32 FreeRTOS移植教程

一、前言 如果能看到这个教程的话&#xff0c;说明大家已经学习嵌入式有一段时间了。还记得嵌入式在大多数时候指的是什么吗&#xff1f;是的&#xff0c;我们所说的学习嵌入式大部分时候都是在学习嵌入式操作系统。从简单的一些任务状态机再到复杂一些的RTOS&#xff0c;再到最…...

java——Tomcat连接池配置NIO、BIO、APR

Tomcat连接池的配置涉及不同的IO模型&#xff0c;包括NIO&#xff08;Non-blocking IO&#xff0c;非阻塞IO&#xff09;、APR&#xff08;Apache Portable Runtime&#xff0c;Apache可移植运行库&#xff09;和BIO&#xff08;Blocking IO&#xff0c;阻塞IO&#xff09;。以…...

跨域相关的一些问题 ✅

当网页从一个源&#xff08;https://baidu.com&#xff09;请求另一个源&#xff08;如 https://taobao/api&#xff09;的资源时&#xff0c;就发生了跨域。由于安全原因&#xff08;防止恶意网站通过脚本访问用户在其他网站上的数据&#xff09;&#xff0c;浏览器对跨域请求…...

RPC学习

一、什么是 RPC RPC&#xff08;Remote Procedure Call&#xff09;&#xff0c;即远程过程调用&#xff0c;是一种计算机通信协议&#xff0c;它允许运行在一台计算机上的程序调用另一台计算机上的子程序或函数&#xff0c;就好像调用本地程序中的函数一样&#xff0c;无需程序…...

coe文件转mif(c语言)

1 mif文件格式 DEPTH=1024; --The size of data in bits WIDTH=16; --The size of memory in words ADDRESS_RADIX = DEC; --The radix for address values DATA_RADIX = UNS...

【leetcode】动态规划

31. 873. 最长的斐波那契子序列的长度 题目&#xff1a; 如果序列 X_1, X_2, ..., X_n 满足下列条件&#xff0c;就说它是 斐波那契式 的&#xff1a; n > 3对于所有 i 2 < n&#xff0c;都有 X_i X_{i1} X_{i2} 给定一个严格递增的正整数数组形成序列 arr &#xff0…...

介绍一下atoi(arr);(c基础)

hi , I am 36 适合对象c语言初学者 atoi(arr)&#xff1b;是返回整数(int型)&#xff0c;整数是arr数组中字符中数字 格式 #include<stdio.h> atoi(arr); 返回值arr数组中的数字 未改变arr数组 #include<stdlib.h>//atoi(arr); 返 <stdlib> int main(…...

docker入门学习笔记

docker的定义 docker是一个用于构建、运行、传送 应用程序的平台。 为什么要使用docker &#xff1f; 在开发测试库环境中测试成功后&#xff0c;打包成集装箱&#xff0c;到生产环境也是能够成功的。而传统的安装方式不仅繁琐&#xff0c;并且在测试环境安装后&#xff0c;到…...

使用Python和Pybind11调用C++程序(CMake编译)

目录 一、前言二、安装 pybind11三、编写C示例代码四、结合Pybind11和CMake编译C工程五、Python调用动态库六、参考 一、前言 跨语言调用能对不同计算机语言进行互补&#xff0c;本博客主要介绍如何实现Python调用C语言编写的函数。 实验环境&#xff1a; Linux gnuPython3.10…...

tableau-制作30个图表

制作条形图 步骤: 1、横轴是数值,对应了某一个度量值,纵轴是一个标签 战区的成交额,条形图横轴是战区,纵轴是成交额 下钻条形图 1、增加业务架构-战区右键点击,分层结构,增加分层结构 调整业务架构,将战区,城市,小组移动到业务架构下方 此时的条形图上方有➕号展开后…...

2024APMCM亚太杯数学建模C题【宠物行业】原创论文分享

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了2024 年APMCM亚太地区大学生数学建模竞赛C题的成品论文。 给大家看一下目录吧&#xff1a; 目录 摘 要&#xff1a; 10 一、问题重述 14 二&#xff0e;问题分析 15 2.1问题一 15 2.2问题二 15 2.3问题三…...

C语言解析命令行参数

原文地址&#xff1a;C语言解析命令行参数 – 无敌牛 欢迎参观我的个人博客&#xff1a;无敌牛 – 技术/著作/典籍/分享等 C语言有一个 getopt 函数&#xff0c;可以对命令行进行解析&#xff0c;下面给出一个示例&#xff0c;用的时候可以直接copy过去修改&#xff0c;很方便…...

推荐一款龙迅HDMI2.0转LVDS芯片 LT6211UX LT6211UXC

龙迅的HDMI2.0转LVDS芯片LT6211UX和LT6211UXC是两款高性能的转换器芯片&#xff0c;它们在功能和应用上有所差异&#xff0c;同时也存在一些共同点。以下是对这两款芯片的详细比较和分析&#xff1a; 一、LT6211UX 主要特性&#xff1a; HDMI2.0至LVDS和MIPI转换器。HDMI2.0输…...

libmodbus 源码学习笔记

1.核心函数_框架_数据结构 整个通信的过程 就是上面这个框架 下面就是具体过程 <1> 主设备 我们首先要初始化 我们要使用的串口 然后 设置我们要访问的哪一个设备 最后打开串口 <2>从机设备 也是我们要初始化我们的串口 然后随后立即设置我们的串口设备地址 最后…...

通用网络安全设备之【防火墙】

概念&#xff1a; 防火墙&#xff08;Firewall&#xff09;&#xff0c;也称防护墙&#xff0c;它是一种位于内部网络与外部网络之间的网络安全防护系统&#xff0c;是一种隔离技术&#xff0c;允许或是限制传输的数据通过。 基于 TCP/IP 协议&#xff0c;主要分为主机型防火…...

Vue.js基础——贼简单易懂!!(响应式 ref 和 reactive、v-on、v-show 和 v-if、v-for、v-bind)

Vue.js是一个渐进式JavaScript框架&#xff0c;用于构建用户界面。它专门设计用于Web应用程序&#xff0c;并专注于视图层。Vue允许开发人员创建可重用的组件&#xff0c;并轻松管理状态和数据绑定。它还提供了一个虚拟DOM系统&#xff0c;用于高效地渲染和重新渲染组件。Vue以…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

数据库正常,但后端收不到数据原因及解决

从代码和日志来看&#xff0c;后端SQL查询确实返回了数据&#xff0c;但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离&#xff0c;并且ai辅助开发的时候&#xff0c;很容易出现前后端变量名不一致情况&#xff0c;还不报错&#xff0c;只是单…...

Redis上篇--知识点总结

Redis上篇–解析 本文大部分知识整理自网上&#xff0c;在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库&#xff0c;Redis 的键值对中的 key 就是字符串对象&#xff0c;而 val…...

GeoServer发布PostgreSQL图层后WFS查询无主键字段

在使用 GeoServer&#xff08;版本 2.22.2&#xff09; 发布 PostgreSQL&#xff08;PostGIS&#xff09;中的表为地图服务时&#xff0c;常常会遇到一个小问题&#xff1a; WFS 查询中&#xff0c;主键字段&#xff08;如 id&#xff09;莫名其妙地消失了&#xff01; 即使你在…...