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

2023/8/16 华为云OCR识别驾驶证、行驶证

目录

一、 注册华为云账号开通识别驾驶证、行驶证服务

二、编写配置文件

        2.1、配置秘钥

        2.2、 编写配置工具类

三、接口测试

        3.1、测试接口

        3.2、结果

 四、实际工作中遇到的问题

        4.1、前端传值问题

        4.2、后端获取数据问题

        4.3、使用openfeign调用接口报错

        4.3、前端显示问题


hello大家好,好久没写博客了,你们找到工作了吗?博主在去年11月成功找到工作,到现在上班大半年了,最近需求用到华为云OCR文字识别,这里就详细记录一下!

一、 注册华为云账号开通识别驾驶证、行驶证服务

华为云官网:特惠专区_云服务器_云主机_企业上云-华为云

 如上图所示,华为云还有很多文字识别服务,这个看个人需求了解即可。

 开放api接口地址体验:https://console.huaweicloud.com/apiexplorer/#/openapi/OCR/debug?api=RecognizeDriverLicense

二、编写配置文件

        2.1、配置秘钥

ocr:projectId: xxxxxxxxxxxxxx   // 项目id:华为云个人凭证获取area: cn-north-4        // 区域:北京4区,目前好像只有北京4区支持这两个证件的识别服务ak: xxxxxxxxxxxxx        //AK:华为云个人凭证获取sk: xxxxxxxxxxxxx        //SK:华为云个人凭证获取

        2.2、 编写配置工具类

@Component
public class OcrUtil {private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);@Value("${ocr.projectId}")private String projectId;@Value("${ocr.area}")private String area;@Value("${ocr.ak}")private String AK;@Value("${ocr.sk}")private String SK;private static CloseableHttpClient httpClient;static {PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();cm.setMaxTotal(100);cm.setDefaultMaxPerRoute(20);cm.setDefaultMaxPerRoute(50);httpClient = HttpClients.custom().setConnectionManager(cm).build();}public String getTokenByAKSK (){String url = "https://iam."+area+".myhuaweicloud.com/v3/auth/tokens";Map<String,String> p1 = new HashMap<>();Map<String,Object> p2 = new HashMap<>();Map<String,Object> p3 = new HashMap<>();Map<String,Object> p4 = new HashMap<>();Map<String,Object> p5 = new HashMap<>();Map<String,Object> p6 = new HashMap<>();Map<String,Object> p7 = new HashMap<>();Map<String,Object> p8 = new HashMap<>();p1.put("key",AK);p2.put("key",SK);p3.put("access",p1);p3.put("secret",p2);p4.put("hw_ak_sk",p3);String[] str = new String[1];str[0] = "hw_ak_sk";p4.put("methods",str);p5.put("identity",p4);p6.put("name",area);p7.put("project",p6);p5.put("scope",p7);p8.put("auth",p5);String result = postJson(url, JSON.toJSONString(p8));return result;}public static String postJson(String url, String jsonString) {CloseableHttpResponse response = null;String result = "";try {HttpPost httpPost = new HttpPost(url);RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();httpPost.setConfig(requestConfig);httpPost.setConfig(requestConfig);httpPost.addHeader("Content-type", "application/json; charset=utf-8");httpPost.setHeader("Accept", "application/json");httpPost.setEntity(new StringEntity(jsonString, StandardCharsets.UTF_8));response = httpClient.execute(httpPost);Header[] h = response.getAllHeaders();for(Header header : h){if(header.getName().equals("X-Subject-Token")){result = header.getValue();}}} catch (IOException e) {log.error("调用HttpUtils.Post IOException, url=" + url + ",param=" + jsonString, e);} finally {try {if (response != null) {response.close();}} catch (IOException e) {log.error("调用HttpUtils.Post IOException, url=" + url + ",param=" + jsonString, e);}}return result;}public static Result postJson(String url, String token, String jsonString) {CloseableHttpResponse response = null;BufferedReader in;String result = "";boolean err = false;try {HttpPost httpPost = new HttpPost(url);RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();httpPost.setConfig(requestConfig);httpPost.setConfig(requestConfig);httpPost.addHeader("Content-type", "application/json; charset=utf-8");httpPost.setHeader("Accept", "application/json");httpPost.setHeader("X-Auth-Token", token);httpPost.setEntity(new StringEntity(jsonString, StandardCharsets.UTF_8));response = httpClient.execute(httpPost);in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));StringBuilder sb = new StringBuilder();String line;String NL = System.getProperty("line.separator");while ((line = in.readLine()) != null) {sb.append(line).append(NL);}in.close();result = sb.toString();err = response.getStatusLine().getStatusCode() == 400;} catch (IOException e) {log.error("调用HttpUtils.Post IOException, url=" + url + ",param=" + jsonString, e);} finally {try {if (response != null) {response.close();}} catch (IOException e) {log.error("调用HttpUtils.Post IOException, url=" + url + ",param=" + jsonString, e);}}if (err) {return Result.error().data("data", result);} else {return Result.ok().data("data", result);}}/*** 功能描述:* 华为云驾驶证识别* @Param: [token, imageUrl]* @Return: com.ruoyi.phaseone.common.utils.R* @Author: Mr.Huang* @Date: 2023/8/10 10:21**/public Result driverLicense(String token, String imageUrl) {String url = "https://ocr."+area+".myhuaweicloud.com/v2/"+projectId+"/ocr/driver-license";Map<String, Object> p = new HashMap<>();// url:图片地址  image:图片的base64数据 两个参数二选一,详情见官网APIp.put("url", imageUrl);p.put("side", "front");log.info("ocr驾驶证识别请求路径:{},请求参数:{}",url,p);return postJson(url, token, JSON.toJSONString(p));}/*** 功能描述:* 华为云行驶证识别* @Param: [token, imageUrl]* @Return: com.sy.milkteasyservice.response.Result* @Author: Mr.Huang* @Date: 2023/8/14 10:52**/public Result vehicleLicense(String token, String imageUrl) {String url = "https://ocr."+area+".myhuaweicloud.com/v2/"+projectId+"/ocr/vehicle-license";Map<String, Object> p = new HashMap<>();// url:图片地址  image:图片的base64数据 两个参数二选一,详情见官网APIp.put("url", imageUrl);// front:行驶证主页  back:行驶证副页p.put("side", "front");log.info("ocr行驶证识别请求路径:{},请求参数:{}",url,p);return postJson(url, token, JSON.toJSONString(p));}
}

调用此接口的流程就是:获取token后设置请求头,发起请求获得结果

三、接口测试

        3.1、测试接口

@RestController
public class HuaWeiObsController {@Autowiredprivate ObsService ObsService;@Autowiredprivate OcrUtil ocrUtil;@ApiOperation(value = "上传图片文件",notes = "xxxxx")@PostMapping("/uploadImgFile")public Result upload(MultipartFile file){String url = ObsService.upload(file);// 行驶证识别/*        Result result = ocrUtil.vehicleLicense(ocrUtil.getTokenByAKSK(), url);System.out.println("调用华为云行驶证识别结果:"+result.toString());Map<String, Object> data = result.getData();Object data1 = data.get("data");JSONObject jsonObject = JSON.parseObject(data1.toString());String result1 = jsonObject.get("result").toString();System.out.println(result1);vehicleLicense vehicleLicense = JSON.parseObject(result1, vehicleLicense.class);System.out.println("orc识别结果是:"+vehicleLicense.toString());return Result.ok().data("result",vehicleLicense).data("url",url);*/// 驾驶证识别Result result = ocrUtil.driverLicense(ocrUtil.getTokenByAKSK(), url);System.out.println("调度接口获取的结果集:"+result);Map<String, Object> data = result.getData();Object data1 = data.get("data");JSONObject jsonObject = JSON.parseObject(data1.toString());String result1 = jsonObject.get("result").toString();System.out.println(result1);drivingLicence drivingLicence = JSON.parseObject(result1, drivingLicence.class);System.out.println("orc识别结果是:"+drivingLicence.toString());return Result.ok().data("result",drivingLicence).data("url",url);}
}

这里的文件上传用的是华为云的OBS服务,上传图片后拿到该图片对应的地址,注意:此图片地址必须要可以访问,如设置访问权限则会调用接口失败!

        3.2、结果

 

 

 四、实际工作中遇到的问题

        4.1、前端传值问题

问题描述:由于前端使用的是根据el-upload封装后的组件,我发现驾驶证和行驶证上传到的是同一个接口,那这样就分不清上传的驾驶证还是行驶证。

解决办法:在调用后端接口传入图片类型字段,判断是驾驶证还是行驶证

:action="this.$http.adornUrl(`/proxyKpiApi/${config.uploadUrl}?${config.id ? `id=${config.id}&` : ''}token=${$cookie.get('token')}&${config.type ? `type=${config.type}` : ''}`)"

 

        4.2、后端获取数据问题

问题描述:项目中使用的华为云obs文件上传服务,但是上传后获得的图片地址因为安全性考虑,不能直接访问,导致调用接口失败。

 

    // openfeign驾驶证服务@PostMapping(value = "/performance/driverLicense", params = "{url={url}}")R driverLicense(@RequestParam("url") String url);// openfeign行驶证服务@PostMapping(value = "/performance/vehicleLicense", params = "{url={url}}")R vehicleLicense(@RequestParam("url") String url);

解决办法:将上传的文件转换成base64格式,调用接口时改成使用image参数,图片的base64数据。

                if(StringUtils.isNotBlank(type)){byte[] fileBytes = file.getBytes();// 将上传的文件转换成base64格式String base64String = Base64.getEncoder().encodeToString(fileBytes);if(type.equals("driverLicense")){// 远程调用识别驾驶证服务com.ruoyi.phaseone.common.utils.R r = carrierPerformanceService.driverLicense(base64String);log.info("ocr驾驶证识别请求结果:{}",r);if(String.valueOf(r.get("code")).equals("0")){Object data = r.get("data");JSONObject jsonObject = JSON.parseObject(data.toString());String result1 = jsonObject.get("result").toString();DrivingLicenceEntity drivingLicenceEntity = JSON.parseObject(result1, DrivingLicenceEntity.class);map.put("ocrResult",drivingLicenceEntity);}}else if(type.equals("vehicleLicense")){// 远程调用识别行驶证服务com.ruoyi.phaseone.common.utils.R r = carrierPerformanceService.vehicleLicense(base64String);log.info("ocr行驶证识别请求结果:{}",r);if(String.valueOf(r.get("code")).equals("0")){Object data = r.get("data");JSONObject jsonObject = JSON.parseObject(data.toString());String result1 = jsonObject.get("result").toString();VehicleLicenseEntity vehicleLicenseEntity = JSON.parseObject(result1, VehicleLicenseEntity.class);map.put("ocrResult",vehicleLicenseEntity);}}}

        4.3、使用openfeign调用接口报错

问题描述:按照上面步骤修改后,由于项目是微服务架构,文件上传服务和前端调用的接口不在同一个服务上,所以要使用openfeign远程调用。但是调用的过程中报错了。报错信息:[<h1>Bad Message 414</h1><pre>reason: URI Too Long</pre>]

解决办法:此问题是因为图片数据转换成base64后,通过远程调用传的值URI太长了,因此我们将接口改造一下,将参数改成对象。

@Data
public class ImageEntity implements Serializable {private String imageUrl;private String imageBase64;
}
    // openfeign驾驶证服务@PostMapping( "/performance/driverLicense")R driverLicense(@RequestBody ImageEntity image);// openfeign行驶证服务@PostMapping("/performance/vehicleLicense")R vehicleLicense(@RequestBody ImageEntity image);
                if(StringUtils.isNotBlank(type)){byte[] fileBytes = file.getBytes();// 将上传的文件转换成base64格式String base64String = Base64.getEncoder().encodeToString(fileBytes);ImageEntity image =new ImageEntity();image.setImageBase64(base64String);if(type.equals("driverLicense")){// 远程调用识别驾驶证服务com.ruoyi.phaseone.common.utils.R r = carrierPerformanceService.driverLicense(image);log.info("ocr驾驶证识别请求结果:{}",r);if(String.valueOf(r.get("code")).equals("0")){Object data = r.get("data");JSONObject jsonObject = JSON.parseObject(data.toString());String result1 = jsonObject.get("result").toString();DrivingLicenceEntity drivingLicenceEntity = JSON.parseObject(result1, DrivingLicenceEntity.class);map.put("ocrResult",drivingLicenceEntity);}}else if(type.equals("vehicleLicense")){// 远程调用识别行驶证服务com.ruoyi.phaseone.common.utils.R r = carrierPerformanceService.vehicleLicense(image);log.info("ocr行驶证识别请求结果:{}",r);if(String.valueOf(r.get("code")).equals("0")){Object data = r.get("data");JSONObject jsonObject = JSON.parseObject(data.toString());String result1 = jsonObject.get("result").toString();VehicleLicenseEntity vehicleLicenseEntity = JSON.parseObject(result1, VehicleLicenseEntity.class);map.put("ocrResult",vehicleLicenseEntity);}}}

        4.3、前端显示问题

问题描述:调用接口成功后,由于前端使用的是el-upload封装后的组件,用的watch函数监听值的变化,每次打开该控件都会显示其结果。

    watch: {'dataForm.carLicence.attachments' (newVal, oldVal) {}

解决方案:判断newVal中的ocrResult是否为空,不为空在赋值,因为可以上传多个文件,所以每次更新选取集合中最后一个元素的数据

    watch: {'dataForm.carLicence.attachments' (newVal, oldVal) {if (newVal[newVal.length - 1] && newVal[newVal.length - 1].ocrResult !== undefined && newVal[newVal.length - 1].ocrResult !== null) {// 车牌号this.dataForm.carNumber = newVal[newVal.length - 1].ocrResult.number;// 发动机号this.dataForm.engineNumber = newVal[newVal.length - 1].ocrResult.engine_no;// 所有人this.dataForm.carLicence.person = newVal[newVal.length - 1].ocrResult.name;// 品牌型号this.dataForm.carLicence.brandModel = newVal[newVal.length - 1].ocrResult.model;// 注册日期this.dataForm.carLicence.registerTime = newVal[newVal.length - 1].ocrResult.register_date;// 发证日期this.dataForm.carLicence.certificationTime = newVal[newVal.length - 1].ocrResult.issue_date;}}},

相关文章:

2023/8/16 华为云OCR识别驾驶证、行驶证

目录 一、 注册华为云账号开通识别驾驶证、行驶证服务 二、编写配置文件 2.1、配置秘钥 2.2、 编写配置工具类 三、接口测试 3.1、测试接口 3.2、结果 四、实际工作中遇到的问题 4.1、前端传值问题 4.2、后端获取数据问题 4.3、使用openfeign调用接口报错 4.3、前端显示问题…...

【Java开发】 Mybatis-Plus 07:创建时间、更新时间自动添加

Mybatis-Plus 可以通过配置实体类的注解来自动添加创建时间和更新时间&#xff0c;这可以减轻一定的开发量。 1 在实体类中添加注解 public class User {TableId(type IdType.AUTO)private Long id;private String username;private String password;TableField(fill FieldF…...

解决vue2项目在IE11浏览器中无画面的兼容问题

解决vue2项目在IE11浏览器中无画面的兼容问题 背景介绍当前网上能找打的教程 背景介绍 当前项目面临其他浏览器都可以运行&#xff0c;但是在IE11浏览器中出现白屏的现象&#xff0c;F12后台也没有报错&#xff0c;项目月底也要交付了。当前项目的vue版本为2.6.11&#xff0c;…...

信号

信号也是IPC中的一种&#xff0c;是和管道&#xff0c;消息队列&#xff0c;共享内存并列的概念。 本文参考&#xff1a; Linux中的信号_linux中信号_wolf鬼刀的博客-CSDN博客 Linux系统编程&#xff08;信号处理 sigacation函数和sigqueue函数 )_花落已飘的博客-CSDN博客 Linu…...

产品经理的真实薪资有多少?今天带你看看

作为产品经理&#xff0c;除了需要拥有扎实的技术背景和出色的产品设计能力&#xff0c;还需具备出色的领导力和商业敏感度。因此&#xff0c;产品经理的薪资也越来越成为人们关注的话题。那么&#xff0c;一般来说&#xff0c;产品经理的薪资水平如何呢&#xff1f; 薪资多少…...

《一个操作系统的实现》windows用vm安装CentOS——从bochs环境搭建到第一个demo跑通

vm安装CentOS虚拟机带有桌面的版本。su输入密码123456。更新yum -y update 。一般已经安装好后面这2个工具&#xff1a;yum install -y net-tools wget。看下ip地址ifconfig&#xff0c;然后本地终端连接ssh root192.168.249.132输入密码即可&#xff0c;主要是为了复制网址方便…...

线程Thread

文章目录 一、概念1、进程2、线程3、CPU与线程的关系4、并行、并发5、线程的生命周期 二、创建1、继承Thread2、实现Runnable接口3、实现Callable接口 三、API1、获取运行使用的线程2、唯一标识3、线程名4、优先级5、是否处于活动状态6、守护线程7、join1、API2、有无join对比 …...

如何使用CSS实现一个渐变背景效果?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用CSS实现渐变背景效果⭐ 线性渐变&#xff08;Linear Gradient&#xff09;⭐ 径向渐变&#xff08;Radial Gradient&#xff09;⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订…...

初始C语言(7)——详细讲解有关初阶指针的内容

系列文章目录 第一章 “C“浒传——初识C语言&#xff08;1&#xff09;&#xff08;更适合初学者体质哦&#xff01;&#xff09; 第二章 初始C语言&#xff08;2&#xff09;——详细认识分支语句和循环语句以及他们的易错点 第三章 初阶C语言&#xff08;3&#xff09;——…...

ArcGIS Pro技术应用(暨基础入门、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合、案例应用)

GIS是利用电子计算机及其外部设备&#xff0c;采集、存储、分析和描述整个或部分地球表面与空间信息系统。简单地讲&#xff0c;它是在一定的地域内&#xff0c;将地理空间信息和 一些与该地域地理信息相关的属性信息结合起来&#xff0c;达到对地理和属性信息的综合管理。GIS的…...

RISC-V公测平台发布 · 数据库在RISC-V服务器上的适配评估

前言 上一期讲到YCSB在RISC-V服务器上对MySQL进行性能测试&#xff08;RISC-V公测平台发布 使用YCSB测试SG2042上的MySQL性能&#xff09;&#xff0c;在这一期文章中&#xff0c;我们继续深入讨论RISC-V数据库的应用。本期就继续利用HS-2平台来测试数据库软件在RISC-V服务器…...

UE5.2 LyraDemo源码阅读笔记(五)输入系统

Lyra里使用了增强输入系统&#xff0c;首先知道增强输入系统里的三个类型配置。 一、Input Actions (IA)&#xff1a; 输入操作带来的变量&#xff0c;与玩家的输入组件绑定&#xff0c;回调里驱动玩家行为。 二、InputMappingContext&#xff08;IMC&#xff09;&#xff1a…...

线段树详解——影子宽度

OK&#xff0c;今天来讲一讲线段树~~ 线段树是什么线段树的实现线段树的时间复杂度线段树的应用线段树的节点结构其他操作和优化例题——影子宽度输入输出格式输入格式输出格式 输入输出样例输入样例输出样例 例题讲解 线段树是什么 线段树&#xff08; S e g m e n t Segmen…...

使用R语言绘制折线图

写在前面 昨天我们分享了使用Python绘制折线图的教程,跟着NC学作图 | 使用python绘制折线图,考虑到很多同学基本不使用Python绘图。那么,我们也使用R语言复现此图形。 此外,在前期的教程中,我们基本没有分享过折线图的教程。因此,我们在这里也制作一期关于折线图的教程。…...

无涯教程-Perl - wantarray函数

描述 如果当前正在执行的函数的context正在寻找列表值,则此函数返回true。在标量context中返回false。 语法 以下是此函数的简单语法- wantarray返回值 如果没有context,则此函数返回undef&#xff1b;如果lvalue需要标量,则该函数返回0。 例 以下是显示其基本用法的示例…...

【gitkraken】gitkraken自动更新问题

GitKraken 会自动升级&#xff01;一旦自动升级&#xff0c;你的 GitKraken 自然就不再是最后一个免费版 6.5.1 了。 在安装 GitKraken 之后&#xff0c;在你的安装目录&#xff08;C:\Users\<用户名>\AppData\Local\gitkraken&#xff09;下会有一个名为 Update.exe 的…...

《Java Web程序设计》试卷03

《Java Web程序设计》试卷03 课程编码&#xff1a; 301209 适用专业&#xff1a; 计算机应用(包括JAVA方向) 注 意 事 项 1、首先按要求在试卷标封处填写你所在的系&#xff08;部&#xff09;、专业、班级及学号和姓名&#xff1b; 2、仔细阅读各类题目的回答要求&#xff0c;…...

怎么查看小程序中的会员信息

商家通过查看会员信息&#xff0c;可以更好地了解用户&#xff0c;并为他们提供更个性化的服务和推荐。接下来&#xff0c;就将介绍如何查看会员信息。 商家在管理员后台->会员管理处&#xff0c;可以查看到会员列表。支持搜索会员的卡号、手机号和等级。还支持批量删除会员…...

网络安全—黑客—自学笔记

想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全…...

深度解读波卡 2.0:多核、更有韧性、以应用为中心

本文基于 Polkadot 生态研究院整理&#xff0c;有所删节 随着波卡 1.0 的正式实现&#xff0c;波卡于 6 月 28 日至 29 日在哥本哈根举办了年度最重要的会议 Polkadot Decoded 2023&#xff0c;吸引了来自全球的行业专家、开发者和爱好者&#xff0c;共同探讨和分享波卡生态的…...

钉钉H5应用环境检测:精准识别JSAPI运行容器的实战指南

1. 为什么需要检测钉钉容器环境 开发钉钉H5应用时&#xff0c;很多同学都遇到过这样的尴尬场景&#xff1a;在浏览器调试时突然蹦出"notInDingTalk"的错误提示&#xff0c;打断调试流程不说&#xff0c;还会污染日志记录。我去年接手的一个企业审批项目就因为这个坑…...

别再为SBUS负逻辑头疼了!硬件反相器电路设计与STM32软件避坑全指南

SBUS负逻辑难题终结手册&#xff1a;从硬件反相到STM32配置的工程实践 当你第一次将航模遥控器的SBUS输出端直接连接到自制的STM32飞控板时&#xff0c;那个令人沮丧的时刻——串口调试器里只有乱码或者干脆一片寂静——可能已经成为许多嵌入式开发者的"成人礼"。这…...

FPGA与MCP2518FD的SPI通信调试实战:从时序纠错到CAN FD数据收发

1. SPI通信调试&#xff1a;从时序分析到实战纠错 第一次用FPGA通过SPI控制MCP2518FD时&#xff0c;我对着逻辑分析仪抓到的波形反复比对手册&#xff0c;发现数据死活写不进寄存器。这种经历相信很多工程师都遇到过——明明代码逻辑没问题&#xff0c;硬件连接也正确&#xff…...

从光场相机到手机摄影:聊聊那些让你‘先拍照后对焦’的黑科技是怎么实现的

从光场相机到手机摄影&#xff1a;揭秘“先拍照后对焦”背后的技术革命 你是否曾在拍完照片后&#xff0c;发现焦点没有对准想要的主体&#xff1f;或是拍完人像照片后&#xff0c;想要调整背景虚化程度&#xff1f;这些看似神奇的功能&#xff0c;其实都源自于一项被称为“光场…...

宏基AS6530笔记本时序解析:从G3到S0的硬件启动密码

1. 宏基AS6530笔记本的硬件启动密码&#xff1a;从G3到S0的时序解析 当你按下笔记本电源键的那一刻&#xff0c;主板就像在解一道精密的数学题——每个电压和信号必须按照特定顺序出现&#xff0c;错一步就会导致启动失败。宏基AS6530采用的广达ZK3代工板&#xff0c;其启动时序…...

Android SVG 实战:从零构建交互式中国地图组件

1. SVG基础与Android开发准备 SVG&#xff08;Scalable Vector Graphics&#xff09;作为矢量图形标准&#xff0c;在Android开发中具有独特优势。与传统的位图格式不同&#xff0c;SVG通过XML描述图形&#xff0c;这意味着无论放大多少倍都不会出现像素化。在Android项目中&a…...

10分钟学会用C语言构建Android应用:rawdrawandroid零基础入门指南

10分钟学会用C语言构建Android应用&#xff1a;rawdrawandroid零基础入门指南 【免费下载链接】rawdrawandroid Build android apps without any java, entirely in C and Make 项目地址: https://gitcode.com/gh_mirrors/ra/rawdrawandroid rawdrawandroid是一个革命性…...

Quartus RS232 UART IP核 配置与Verilog数据流控制实战

1. Quartus RS232 UART IP核基础配置 第一次接触FPGA串口通信时&#xff0c;我也被各种协议和配置参数搞得晕头转向。后来发现Quartus自带的RS232 UART IP核简直就是救命稻草&#xff0c;它把复杂的底层协议封装成简单易用的模块。下面我就用最直白的语言&#xff0c;带你一步步…...

告别嗡嗡声!用SWM120 MCU驱动24V单相BLDC风扇,实现静音正弦波控制保姆级教程

静音革命&#xff1a;基于SWM120 MCU的24V单相BLDC风扇正弦波控制实战指南 清晨的书房里&#xff0c;传统风扇的嗡嗡声总是打断思绪&#xff1b;卧室中&#xff0c;电机的高频啸叫让人辗转难眠——这些场景正是无数家电开发者和硬件爱好者试图攻克的难题。当市面大多数BLDC风扇…...

Java的Switch表达式中的箭头语法与传统case语句在代码风格上的演进

Java语言在长期演进中不断优化语法结构&#xff0c;其中Switch表达式的箭头语法与传统case语句的对比尤为典型。从JDK 12引入预览特性到JDK 14正式落地&#xff0c;箭头语法通过更简洁的形式改变了开发者处理多分支逻辑的方式。这种演进不仅提升了代码可读性&#xff0c;还反映…...