c/c++的opencv车牌识别
- OpenCV 安装: 你需要正确安装 OpenCV 库。
- Tesseract OCR 安装:
- 你需要安装 Tesseract OCR 引擎。在 Ubuntu/Debian 上,可以使用:
sudo apt-get install tesseract-ocr sudo apt-get install libtesseract-dev sudo apt-get install libleptonica-dev
- 你还需要下载 Tesseract 的语言数据文件(例如,用于英文识别的
eng.traineddata
)。通常这些文件需要放在一个名为tessdata
的目录下,并且 Tesseract 需要知道这个目录的位置 (可以通过设置环境变量TESSDATA_PREFIX
或在代码中指定)。
- 你需要安装 Tesseract OCR 引擎。在 Ubuntu/Debian 上,可以使用:
- 编译器: 你需要一个 C++ 编译器 (如 G++)。
代码结构:
- 包含头文件和命名空间。
- 主函数
main
:- 加载图像。
- 预处理图像(灰度化、模糊、边缘检测)。
- 查找轮廓。
- 过滤轮廓以找到可能的车牌区域。
- 提取车牌 ROI (Region of Interest)。
- 对提取的 ROI 进行 OCR。
- 显示结果。
#include <opencv2/opencv.hpp>
#include <tesseract/baseapi.h> // Tesseract API
#include <leptonica/allheaders.h> // Leptonica (Tesseract 使用的图像库)
#include <iostream>
#include <vector>
#include <string>// 使用标准命名空间
using namespace std;
using namespace cv;// 函数:对车牌ROI进行OCR识别
string recognize_text_from_roi(Mat roi_image) {if (roi_image.empty()) {return "Error: ROI image is empty.";}// 将OpenCV Mat转换为Tesseract可以处理的Pix对象// 首先确保图像是灰度图,如果不是,则转换Mat gray_roi;if (roi_image.channels() == 3) {cvtColor(roi_image, gray_roi, COLOR_BGR2GRAY);} else {gray_roi = roi_image.clone();}// 可以选择进行二值化处理,有时能提高识别率// threshold(gray_roi, gray_roi, 0, 255, THRESH_BINARY | THRESH_OTSU);tesseract::TessBaseAPI *ocr = new tesseract::TessBaseAPI();// 初始化Tesseract// 参数1: tessdata路径,如果TESSDATA_PREFIX环境变量已设置,可以为NULL// 参数2: 语言,例如 "eng" 代表英文,"chi_sim" 代表简体中文 (需要相应的traineddata文件)// PSM_SINGLE_BLOCK: 假定图像是一个统一的文本块if (ocr->Init(NULL, "eng", tesseract::OEM_LSTM_ONLY)) {cerr << "Could not initialize tesseract." << endl;delete ocr;return "Error: Tesseract initialization failed.";}ocr->SetPageSegMode(tesseract::PSM_SINGLE_BLOCK); // 或 PSM_SINGLE_LINE, PSM_AUTO 等// 设置图像ocr->SetImage(gray_roi.data, gray_roi.cols, gray_roi.rows, gray_roi.channels(), gray_roi.step);// 获取识别结果char *outText = ocr->GetUTF8Text();string recognized_text(outText);// 清理ocr->End();delete ocr;delete[] outText;// 移除识别文本中的换行符和多余空格(简单处理)recognized_text.erase(remove(recognized_text.begin(), recognized_text.end(), '\n'), recognized_text.end());recognized_text.erase(remove(recognized_text.begin(), recognized_text.end(), '\r'), recognized_text.end());// 也可以进一步去除空格等return recognized_text;
}int main(int argc, char** argv) {// --- 1. 加载图像 ---string image_path = "plate_image.png"; // 修改为你的车牌图片路径if (argc > 1) {image_path = argv[1];}Mat original_image = imread(image_path);if (original_image.empty()) {cout << "无法加载图像: " << image_path << endl;return -1;}cout << "图像加载成功: " << image_path << endl;Mat processed_image;// --- 2. 预处理 ---// 转换为灰度图cvtColor(original_image, processed_image, COLOR_BGR2GRAY);// 高斯模糊以减少噪声GaussianBlur(processed_image, processed_image, Size(5, 5), 0);// Canny边缘检测Mat edges;Canny(processed_image, edges, 50, 150); // 调整阈值以获得更好的边缘// --- 3. 查找轮廓 ---vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(edges, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); // RETR_TREE 可能会找到更多嵌套轮廓Mat contours_display = original_image.clone(); // 用于显示轮廓和检测结果cout << "找到 " << contours.size() << " 个轮廓。" << endl;// --- 4. 过滤轮廓以找到可能的车牌区域 ---vector<Rect> potential_plates_roi;for (size_t i = 0; i < contours.size(); i++) {// 计算轮廓的边界框Rect bounding_rect = boundingRect(contours[i]);// 过滤条件 (非常基础,需要根据实际情况调整)// a. 宽高比 (例如,中国车牌标准宽高比约为 440/140 = 3.14)float aspect_ratio = (float)bounding_rect.width / bounding_rect.height;// b. 面积 (避免太小或太大的区域)double area = contourArea(contours[i]);double min_area = 800; // 最小面积阈值 (像素)double max_area = 50000; // 最大面积阈值 (像素)// c. 近似多边形顶点数 (车牌通常是矩形,4个顶点)vector<Point> approx_poly;approxPolyDP(contours[i], approx_poly, arcLength(contours[i], true) * 0.02, true);// 简单的过滤逻辑if (approx_poly.size() == 4 && // 近似为四边形aspect_ratio > 2.0 && aspect_ratio < 5.5 && // 合理的宽高比area > min_area && area < max_area) { // 合理的面积// 绘制绿色矩形标记潜在车牌rectangle(contours_display, bounding_rect, Scalar(0, 255, 0), 2);potential_plates_roi.push_back(bounding_rect);cout << "潜在车牌区域: x=" << bounding_rect.x << ", y=" << bounding_rect.y<< ", w=" << bounding_rect.width << ", h=" << bounding_rect.height<< ", AR=" << aspect_ratio << ", Area=" << area << endl;}}if (potential_plates_roi.empty()) {cout << "未找到潜在的车牌区域。" << endl;} else {cout << "找到 " << potential_plates_roi.size() << " 个潜在车牌区域。" << endl;// 为了简单,我们只处理第一个找到的潜在车牌// 在实际应用中,可能需要更复杂的逻辑来选择最佳车牌或处理多个车牌// --- 5. 提取车牌 ROI 并进行 OCR ---for (const auto& plate_rect : potential_plates_roi) {Mat plate_roi_raw = original_image(plate_rect); // 从原始彩色图像中提取ROIif (plate_roi_raw.empty()) {cerr << "无法提取车牌ROI。" << endl;continue;}// (可选) 对ROI进行一些额外的预处理,如调整大小,进一步去噪等// Mat plate_roi_for_ocr = plate_roi_raw.clone();// cvtColor(plate_roi_for_ocr, plate_roi_for_ocr, COLOR_BGR2GRAY);// threshold(plate_roi_for_ocr, plate_roi_for_ocr, 0, 255, THRESH_BINARY_INV | THRESH_OTSU); // 反二值化+OTSUcout << "\n对ROI进行OCR..." << endl;string recognized_plate = recognize_text_from_roi(plate_roi_raw); // 直接传入彩色ROI,函数内部会转灰度if (recognized_plate.rfind("Error:", 0) == 0) { // 检查是否以 "Error:" 开头cerr << "OCR失败: " << recognized_plate << endl;} else {cout << "识别结果: " << recognized_plate << endl;// 在图像上显示识别结果putText(contours_display, recognized_plate, Point(plate_rect.x, plate_rect.y - 10),FONT_HERSHEY_SIMPLEX, 0.9, Scalar(0, 0, 255), 2);}}}// --- 6. 显示结果 ---imshow("原始图像", original_image);imshow("边缘检测", edges);imshow("检测到的车牌", contours_display);waitKey(0); // 等待按键destroyAllWindows();return 0;
}
编译和运行
-
保存代码: 将上述代码保存为
lpr_simple.cpp
。 -
准备图片: 准备一张名为
plate_image.png
(或你在代码中指定的其他名称) 的车牌图片,并将其放在与lpr_simple.cpp
相同的目录下。或者,你可以在运行时通过命令行参数传递图片路径。 -
编译:
打开终端,使用以下命令编译 (假设你使用的是 g++,并且 OpenCV 和 Tesseract 已正确安装):g++ lpr_simple.cpp -o lpr_simple $(pkg-config --cflags --libs opencv4 tesseract leptonica)
- 注意:
opencv4
可能需要根据你的 OpenCV 版本调整 (例如opencv
或opencv3
)。你可以通过运行pkg-config --libs opencv4
来检查正确的链接标志。 - 如果
pkg-config
找不到 tesseract 或 leptonica,你可能需要手动指定头文件和库路径。
- 注意:
-
运行:
./lpr_simple
或者,如果你想指定图片:
./lpr_simple /path/to/your/image.jpg
代码解释
1. 包含头文件
#include <opencv2/opencv.hpp> // OpenCV 主要头文件
#include <tesseract/baseapi.h> // Tesseract C++ API
#include <leptonica/allheaders.h> // Leptonica (Tesseract 依赖的图像处理库)
#include <iostream> // 标准输入输出
#include <vector> // STL vector
#include <string> // STL string
2. recognize_text_from_roi
函数
这个函数负责对提取到的车牌候选区域 (ROI) 进行光学字符识别。
string recognize_text_from_roi(Mat roi_image) {// ... (错误检查) ...Mat gray_roi;if (roi_image.channels() == 3) { // 如果是彩色图,转为灰度cvtColor(roi_image, gray_roi, COLOR_BGR2GRAY);} else {gray_roi = roi_image.clone();}// 初始化 Tesseract APItesseract::TessBaseAPI *ocr = new tesseract::TessBaseAPI();// "eng" 表示英文,OEM_LSTM_ONLY 表示使用 LSTM OCR 引擎 (通常效果更好)if (ocr->Init(NULL, "eng", tesseract::OEM_LSTM_ONLY)) {// ... (错误处理) ...}// 设置页面分割模式,PSM_SINGLE_BLOCK 假设图像是一个统一的文本块ocr->SetPageSegMode(tesseract::PSM_SINGLE_BLOCK);// 将 OpenCV Mat 数据传递给 Tesseractocr->SetImage(gray_roi.data, gray_roi.cols, gray_roi.rows, gray_roi.channels(), gray_roi.step);// 获取识别文本char *outText = ocr->GetUTF8Text();string recognized_text(outText);// 清理资源ocr->End();delete ocr;delete[] outText;// 简单地移除换行符recognized_text.erase(remove(recognized_text.begin(), recognized_text.end(), '\n'), recognized_text.end());// ...return recognized_text;
}
- Tesseract 初始化 (
ocr->Init
):- 第一个参数是
tessdata
目录的路径。如果设置为NULL
或空字符串,Tesseract 会尝试从环境变量TESSDATA_PREFIX
或默认安装路径查找。 - 第二个参数是语言代码 (例如, “eng” 表示英语, “chi_sim” 表示简体中文)。你需要确保相应的
.traineddata
文件存在于tessdata
目录中。 - 第三个参数是 OCR 引擎模式。
OEM_LSTM_ONLY
通常提供较好的结果。
- 第一个参数是
- 页面分割模式 (
ocr->SetPageSegMode
): 这告诉 Tesseract 如何解释图像中的文本布局。PSM_SINGLE_BLOCK
适合单个文本块,对于裁剪出的车牌图像通常是合适的。其他模式如PSM_SINGLE_LINE
(单行文本)也可能有用。
3. main
函数
-
加载图像 (
imread
):Mat original_image = imread(image_path); if (original_image.empty()) { /* ... 错误处理 ... */ }
-
图像预处理:
cvtColor(original_image, processed_image, COLOR_BGR2GRAY); // 转灰度 GaussianBlur(processed_image, processed_image, Size(5, 5), 0); // 高斯模糊 Canny(processed_image, edges, 50, 150); // Canny 边缘检测
这些步骤有助于减少噪声,并突出图像中的边缘,为轮廓检测做准备。Canny 算法的两个阈值(50 和 150)可能需要根据输入图像的特性进行调整。
-
查找轮廓 (
findContours
):vector<vector<Point>> contours; vector<Vec4i> hierarchy; findContours(edges, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
RETR_EXTERNAL
: 只检测最外层的轮廓。CHAIN_APPROX_SIMPLE
: 压缩水平、垂直和对角线段,只保留其端点。
-
过滤轮廓:
这是车牌定位的核心步骤。循环遍历所有找到的轮廓,并根据一些基本几何特征进行过滤:for (size_t i = 0; i < contours.size(); i++) {Rect bounding_rect = boundingRect(contours[i]); // 获取边界框float aspect_ratio = (float)bounding_rect.width / bounding_rect.height; // 计算宽高比double area = contourArea(contours[i]); // 计算面积vector<Point> approx_poly;// 对轮廓进行多边形逼近approxPolyDP(contours[i], approx_poly, arcLength(contours[i], true) * 0.02, true);// 过滤条件if (approx_poly.size() == 4 && // 顶点数接近4 (矩形)aspect_ratio > 2.0 && aspect_ratio < 5.5 && // 典型的车牌宽高比area > min_area && area < max_area) { // 合理的面积范围// ... 标记为潜在车牌 ...potential_plates_roi.push_back(bounding_rect);} }
这些过滤条件(顶点数、宽高比、面积)是非常基础的,实际应用中可能需要更鲁棒的算法,例如结合颜色信息、字符的排布特征等。
-
提取 ROI 和 OCR:
如果找到了潜在的车牌区域,就从原始图像中提取该区域,并调用recognize_text_from_roi
函数。for (const auto& plate_rect : potential_plates_roi) {Mat plate_roi_raw = original_image(plate_rect); // 从原图提取ROI// ... (错误检查) ...string recognized_plate = recognize_text_from_roi(plate_roi_raw);// ... (显示结果) ... }
-
显示结果 (
imshow
,waitKey
):
显示原始图像、边缘图像以及带有标记和识别文本的图像。
局限性与改进方向
这个示例非常基础,其鲁棒性有限:
- 简单的轮廓过滤: 对于复杂背景、光照变化、车牌倾斜或部分遮挡的情况,效果可能不佳。
- 固定的阈值: Canny 边缘检测的阈值、面积和宽高比的过滤阈值是硬编码的,可能不适用于所有图像。
- OCR 准确性: Tesseract 的准确性受图像质量、字体、字符间距等多种因素影响。对 ROI 进行更精细的预处理(如二值化、去噪、倾斜校正、字符分割)可以提高识别率。
- 单车牌假设: 代码目前简单地处理找到的第一个(或所有)符合条件的区域。如果图像中有多个车牌或多个类似车牌的物体,可能需要更复杂的逻辑来选择。
- 语言和字符集: Tesseract 需要为特定语言和字符集进行配置。
可能的改进方向:
- 更高级的定位算法:
- 使用形态学操作(如开运算、闭运算、顶帽、黑帽)来增强车牌特征。
- 颜色分割:利用车牌颜色(如蓝色、黄色、绿色底板)进行初步筛选。
- 滑动窗口或基于 MSER (Maximally Stable Extremal Regions) 的方法。
- 训练一个目标检测模型 (如基于 Haar Cascades, HOG+SVM, 或深度学习的 Faster R-CNN, YOLO, SSD) 来专门检测车牌。
- 车牌倾斜校正: 检测车牌的四个角点,并进行透视变换将其校正为标准矩形。
- 字符分割: 在识别之前,将车牌上的字符分割成单个字符图像,然后对每个字符进行识别。这通常能提高复杂车牌的识别率。
- Tesseract 参数调优: 尝试不同的页面分割模式 (
SetPageSegMode
) 和 OCR 引擎模式 (Init
中的oem
参数)。 - 训练自定义 Tesseract 模型: 对于特定字体或低质量图像,训练针对性的 Tesseract 模型可能会有显著提升。
- 后处理: 对 OCR 结果进行校验,例如根据车牌号码的语法规则(如特定位置是字母还是数字)进行修正。
这个简单的例子可以作为你学习和探索车牌识别的一个起点。祝你编码愉快!
相关文章:
c/c++的opencv车牌识别
OpenCV 安装: 你需要正确安装 OpenCV 库。Tesseract OCR 安装: 你需要安装 Tesseract OCR 引擎。在 Ubuntu/Debian 上,可以使用:sudo apt-get install tesseract-ocr sudo apt-get install libtesseract-dev sudo apt-get install…...

4.2.3 Spark SQL 手动指定数据源
在本节实战中,我们学习了如何在Spark SQL中手动指定数据源以及如何使用format()和option()方法。通过案例演示,我们读取了不同格式的数据文件,包括CSV、JSON,并从JDBC数据源读取数据,展示了如何将这些数据转换为DataFr…...

【论文解读】CVPR2023 PoseFormerV2:3D人体姿态估计(附论文地址)
论文链接:https://arxiv.org/pdf/2303.17472 源码链接:https://github.com/QitaoZhao/PoseFormerV2 Abstract 本文提出了 PoseFormerV2,通过探索频率域来提高 3D 人体姿态估计的效率和鲁棒性。PoseFormerV2 利用离散余弦变换(DC…...
WPF的交互核心:命令系统(ICommand)
命令系统(ICommand) 1 RelayCommand实现2 CanExecute控制按钮可用性3 参数传递(CommandParameter)3.1 静态参数绑定:3.2 动态参数绑定:3.3 复杂对象参数: 4 异步命令实现5 常见问题排查 WPF的命…...

Maven工程演示
软件:idea 一、项目创建 操作截图file -> New -> Projectnextnext -> Name:工程名称;Location:项目路径;项目创建完成;文件夹基本样例:(如果不完整自己创建即可)MANIFEST.MF内容 二、导入依赖 …...

uniapp分包配置,uniapp设置subPackages
在使用uniapp开发过程中,由于项目比较大,无法直接上传,需要分包后才可以上传。 步骤: 1、在pages同级目录下创建分包的目录(pages_second),把要分包的文件放到该目录下; 2、在pag…...
计算机网络 HTTP篇常见面试题总结
HTTP各版本区别 HTTP 1.0 无状态、无连接:每次请求都需要建立新的 TCP,处理完后立即关闭,导致开销较大。队头阻塞:每个请求必须按照顺序依次处理,前面的请求未完成,后面的请求只能等待,减低了…...

C++八股 —— 手撕线程池
文章目录 一、背景二、线程池实现1. 任务队列和工作线程2. 构造和析构函数3. 添加任务函数4. 完整代码 三、阻塞队列实现1. 基础队列2. 升级版队列 四、测试代码五、相关问题六、其他实现方式 来自:华为C一面:手撕线程池_哔哩哔哩_bilibili 华为海思&am…...

RPA如何支持跨平台和跨浏览器的自动化
RPA,即机器人流程自动化(Robotic Process Automation),正日益成为企业实现业务流程高效自动化的关键技术。在复杂的数字化环境中,跨平台和跨浏览器的自动化需求极为迫切,RPA 通过多种技术手段和策略来满足这…...

【笔记】Windows 成功部署 Suna 开源的通用人工智能代理项目部署日志
#工作记录 本地部署运行截图 kortix-ai/suna: Suna - 开源通用 AI 代理 项目概述 Suna 是一个完全开源的 AI 助手,通过自然对话帮助用户轻松完成研究、数据分析等日常任务。它结合了强大的功能和直观的界面,能够理解用户需求并提供结果。其强…...
关于ffplay在macos上运行奔溃的问题
这个问题大概是由于 MacOS 的问题引起的,奔溃的地方在 SDL2 的代码中,如果直接使用 brew 安装 SDL2就会遇到这个问题,所以需要修改 SDL2源码然后再编译安装。 我这里采用的是 origin/release-2.28.x 分支,修改部分如下࿱…...

Linux531rsync定时同步 再回忆
rsync定时同步 环境配置 关闭防火墙,selinux systemctl stop firewalld systemctl disable firewall setenforce 0 cat /etc/selinux/configpei SELINUXdisable设置主机名 systemctl set-hostname code systemctl set-hostname backup设置静态IP rsync由于要设…...
Elasticsearch 分析器介绍
在 Elasticsearch 的世界里,构建高效搜索引擎的关键一环,便是透彻理解分析器(Analyzer)的工作机制。一个优秀的搜索引擎,能够精准地返回与用户查询紧密相关的文档,而这背后,正是分析器在默默发挥着核心作用。它不仅负责处理待索引的文档,还在用户发起查询时,智能评估哪…...

【KWDB 创作者计划】_探秘浪潮KWDB数据库:从时间索引到前沿技术
探秘浪潮KWDB数据库:从时间索引到前沿技术 文章目录 探秘浪潮KWDB数据库:从时间索引到前沿技术引言1.浪潮KWDB数据库时间索引深度解析1.1时间索引工作原理1.2时间索引创建与管理实践 2.浪潮KWDB数据库前沿产品技术纵览2.1多模融合存储引擎2.2就地计算技术…...

安卓逆向篇LSP 模块HOOK 添加技术绕过检测算法解密逻辑验证
前置解释: 0 、 Magisk : 是当前 Android 社区用来获取 root 权限的主流方式开源工具 1 、 LSP 框架: XPosed 框架因只支持安卓 8 及以下,故高版本应使用 MagiskLSPosed 2 、 HOOK 技术: 钩子技术&…...
【SQL】关键字
ORDER BY ORDER BY(排序) 语句可以按照一个或多个列的值进行升序(ASC)或降序(DESC)排序。 MAX / MIN MAX() 函数返回一组值中的最大值。这个函数常用于数字字段,但也可以用于文本字段来找出按字典顺序最后的元素。 …...

第一节 51单片机概述
目录 一、单片机系统组成 (一)、单片机硬件系统 (二)单片机的软件系统 二、STC89C52单片机 (1)、基本信息 (2)、命名规则 (3)、单片机内部结构图 &am…...

Google car key:安全、便捷的汽车解锁新选择
有了兼容的汽车和 Android 手机,Google car key可让您将Android 手机用作车钥匙。您可以通过兼容的 Android 手机锁定、解锁、启动汽车并执行更多功能。但是,Google car key安全吗?它是如何工作的?如果我的手机电池没电了怎么办&a…...

720全景展示:VR全景的技术原理及应用
VR720全景展示:技术原理及应用探索 720全景技术,作为当前全球范围内迅速崛起流行的视觉新技术,为用户带来了全新的真实现场感和交互式的体验。凭借全方位、无死角的视觉展示特性,在VR(虚拟现实)领域中得到…...

定制一款国密浏览器(13):预置国密根证书到浏览器
由于国密算法没有得到国外的认可,所以 Chromium、Firefox 等浏览器均不支持国密算法。即使我们修改了 Chromium 的源码,增加了国密算法的支持,但还不能在浏览器中正常使用。因为这涉及到证书的信任问题,国密证书都是国内厂商签发的,国密根证书并没有集成到系统和浏览器中。…...

PowerBI企业运营分析——线性回归销售预测
PowerBI企业运营分析——线性回归销售预测 欢迎来到Powerbi小课堂,在竞争激烈的市场环境中,企业运营分析平台成为提升竞争力的核心工具。 该平台通过整合多源数据,实现关键指标的实时监控,从而迅速洞察业务动态,精准…...
大模型运维过程中常见的一些操作
1. 模型部署与环境配置 基础设施准备:部署 GPU 集群、TPU 等专用硬件,配置分布式计算环境(如 Kubernetes)。推理服务搭建:使用 Triton Inference Server、TensorFlow Serving 等框架部署模型,优化批处理和…...
C# 关于闭包与多线程结合使用
开头先看一篇文章:【转】编写高质量代码改善C#程序的157个建议——建议75:警惕线程不会立即启动 - 指间的徘徊 - 博客园d 摘抄: static int _id 0; static void Main() { for (int i 0; i < 10; i, _id) { Thread t new Thread…...

LangFuse:开源LLM工程平台的革新实践
文章目录 一 架构设计与技术栈二 增强型监控能力三 提示词工程支持(新增)四 性能优化实践五 LangFuse部署(docker)和代码集成5.1 LangFuse平台部署5.2 LangFuse代码集成和检测体验 一 架构设计与技术栈 LangFuse采用模块化架构设…...

新视角!经济学顶刊QJE用文本分析探究新技术扩散
美国圣路易斯联邦储备银行Aakash Kalyani、美国斯坦福大学与国家经济研究局Nicholas Bloom、英国伦敦商学院Marcela Carvalho和其合作者们共同研究的“The Diffusion of New Technologies(新技术的扩散)”在顶刊The Quarterly Journal of Economics中发表…...
微信小程序返回上一页监听
本文实现的是微信小程序在返回上一页时获取通知并自定义业务。 最简单的实现: 使用 wx.enableAlertBeforeUnload() 优点:快速接入 缺点:手势不能识别、无法自定义弹窗内容(仅询问) 方法二: page-conta…...

5月31日day41打卡
简单CNN 知识回顾 数据增强卷积神经网络定义的写法batch归一化:调整一个批次的分布,常用与图像数据特征图:只有卷积操作输出的才叫特征图调度器:直接修改基础学习率 卷积操作常见流程如下: 1. 输入 → 卷积层 → Batch…...
“粽”览全局:分布式系统架构与实践深度解析(端午特别版)
第一部分:引言——技术世界的“端午”第二部分:分布式系统概述——粽子节点初探第三部分:核心技术详解——技术“粽子”大解构 粽叶篇:通信协议糯米篇:一致性算法馅料篇:任务调度与计算包扎篇:系…...

STM32G4 电机外设篇(一) GPIO+UART
目录 一、STM32G4 电机外设篇(一) GPIOUART1 GPIO1.1 STM32CUBEMX 配置以及Keil代码1.2 代码和实验现象 2 UART2.1 STM32CUBEMX 配置以及Keil代码2.2 代码和实验现象 附学习参考网址欢迎大家有问题评论交流 (* ^ ω ^) 一、STM32G4 电机外设篇࿰…...
代理IP在云计算中的应用:技术演进与场景实践
一、技术融合的必然性:代理IP与云计算的协同效应 在数字化转型的浪潮中,云计算已成为企业IT架构的核心底座,而代理IP技术则作为网络访问的关键基础设施,两者在技术演进路径上呈现出深度融合的趋势。云计算的弹性资源池与代理IP的…...