用 Rust 和 Tesseract OCR 解析验证码

news/2025/11/6 23:30:21/文章来源:https://www.cnblogs.com/ocr12/p/19197978
  1. 环境准备
    1.1 安装 Rust

如果尚未安装 Rust,可以使用官方推荐的 rustup 进行安装:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

然后检查安装是否成功:

rustc --version

1.2 安装 Tesseract OCR

在不同操作系统上安装 Tesseract:

macOS(使用 Homebrew):

brew install tesseract

Ubuntu/Linux:

sudo apt update
sudo apt install tesseract-ocr

Windows(使用 Scoop):

scoop install tesseract

安装完成后,检查 Tesseract 是否可用:

tesseract --version

1.3 创建 Rust 项目

创建一个新的 Rust 项目:

cargo new rust_ocr
cd rust_ocr

然后在 Cargo.toml 中添加依赖:

[dependencies]
image = "0.24"
tesseract = "0.14"

image 处理图像

tesseract 绑定到 Tesseract OCR

  1. 代码实现

在 src/main.rs 中添加以下代码:

use image::{GrayImage, Luma, ImageBuffer};
use tesseract::Tesseract;
use std::path::Path;
use std::fs::File;
use std::io::BufReader;

/// 读取验证码图片
fn load_captcha_image(image_path: &str) -> GrayImage {
let img = image::open(image_path).expect("无法打开图片").into_luma8();
img
}

/// 预处理图像(灰度化 + 二值化)
fn preprocess_image(img: &GrayImage) -> GrayImage {
let mut processed = ImageBuffer::new(img.width(), img.height());

for (x, y, pixel) in img.enumerate_pixels() {let new_pixel = if pixel[0] > 128 { Luma([255]) } else { Luma([0]) };processed.put_pixel(x, y, new_pixel);
}processed

}

/// 保存处理后的图像
fn save_image(img: &GrayImage, output_path: &str) {
img.save(output_path).expect("无法保存处理后的图片");
}

/// 进行 OCR 识别
fn recognize_text(image_path: &str) -> String {
let text = Tesseract::new(None, "eng")
.expect("无法初始化 Tesseract")
.set_image(image_path)
.recognize()
.expect("OCR 识别失败");

text.trim().to_string()

}

fn main() {
let image_path = "captcha.png"; // 请替换为你的验证码图片路径
let processed_path = "processed_captcha.png";

println!("加载验证码图片...");
let img = load_captcha_image(image_path);println!("预处理图像...");
let processed_img = preprocess_image(&img);
save_image(&processed_img, processed_path);println!("执行 OCR 识别...");
let text = recognize_text(processed_path);println!("识别出的验证码: {}", text);

}

  1. 代码解析
    3.1 读取并预处理图像
    let img = image::open(image_path).expect("无法打开图片").into_luma8();

将图片转换为灰度

二值化 处理,增强字符对比度

3.2 调用 Tesseract 进行 OCR 解析
let text = Tesseract::new(None, "eng")
.expect("无法初始化 Tesseract")
.set_image(image_path)
.recognize()
.expect("OCR 识别失败");

调用 Tesseract

设置语言 为 "eng"

识别验证码文本

  1. 运行程序

执行:

cargo run

程序会处理验证码图片并输出识别结果。

  1. 提高识别准确率
    5.1 调整 Tesseract PSM 模式

不同的 PSM 模式适用于不同场景:

PSM 6:假设为单行文本

PSM 7:单行纯文本(更适合验证码)

PSM 10:单字符模式(适用于分割验证码)

可以调整:

Tesseract::new(None, "eng")
.expect("无法初始化 Tesseract")
.set_image(image_path)
.set_variable("tessedit_pageseg_mode", "7")
.recognize()
.expect("OCR 识别失败");

5.2 进一步图像优化

降噪处理:使用 OpenCV 进一步去除噪点

字符分割:适用于粘连字符的验证码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/958185.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

题解:AT_abc225_h [ABC225H] Social Distance 2

组合意义太吃操作了,还是得我代数推导牛。 题意:给出若干个已有元素 \(a_i\),要求加入一些 \([1,n]\) 内的数且不能和 \(a\) 中已有的相同,使得长度为 \(m\)。定义 \(f(a) = \prod\limits_{i=1}^{m-1} (a_{i+1}-a_…

Apollo场景建议配置指南:充分发挥分布式配置中心优势

Apollo场景建议配置指南:充分发挥分布式配置中心优势随着微服务架构的广泛应用,配置管理已成为系统运维中的关键挑战。Apollo作为业界广泛认可的分布式配置解决方案,正是为了应对这一挑战而诞生。它能够集中化管理应…

CSAPP学习笔记

CSAPP CSAPP Datalab 数字的存储 内存被划分为不同大小的字块,32位CPU->4字节,64位CPU->8字节 对字长\(w\)的机器而言,虚拟地址范围为\(0~2^w-1\),即有\(2^w\)个字节 64位架构地址空间限制为48位虚拟地址,…

英伟达领投,语音AI初创Uniphore估值25亿美元;ElevenLabs创始人:语音的意义不在准确,而在打动丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的技术」、「有亮点的产品」、「有思考的文章」、「有态…

数学分析A 定理简单整理(部分)

第一章 集合和函数一些基础的就不理了。 可列集:与自然数集合等势的无限集 第二章 数列极限 最大数和最小数: \(\max S=x \iff \exist x \in S,\forall y \in S,y\le x\) \(\min S=x \iff \exist x \in S,\forall y …

第3章 多线程服务器的适用场合与常用编程模型 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

表相关操作

表介绍 表相当于文件,表中的一条记录就相当于文件的一行内容,不同的是,表中的一条记录有对应的标题,称为表的字段id name sex age1 cy male 252 ziy female 24id,name,sex,age称为字段,其余的,一行内容称为一…

部分页面统计用户访问时长

方式1 import { createApp } from "vue"; import { createPinia } from "pinia";import App from "./App.vue"; import router from "./router";const app = createApp(App);…

单词故事

→点击前往下载软件← 用户QQ群:656365129

【Linux笔记】网络部分——Socket编程 UDP搭建网络云服务器与本地虚拟机的基本通信

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

11月6日日记

1.今天体育课打比赛 2.明天学习java 3.多条件模糊查询时,如何处理 “项目编号 + 项目名称” 组合查询的 SQL 动态拼接?

102302149赖翊煊数据采集第二次作业

作业一 代码及其展示部分点击查看代码 from bs4 import BeautifulSoup from bs4 import UnicodeDammit import urllib.request import sqlite3class WeatherDB:def openDB(self):self.con = sqlite3.connect("wea…

ai学习机哪个品牌好?松鼠 AI 双线矩阵:学习机 + 自习室,提分更高效

2025 年 11 月 AI 学习机首选!松鼠 AI 双线矩阵:学习机 + 自习室,提分更高效! 在教育数字化加速的 2025 年,AI 学习机已成为家庭学习核心工具,但单一依赖学习机常陷入 “诊断不深、练习盲目、缺乏监督” 的困境。…

招聘实习生丨加入我们,共建 RTE 开发者社区

RTE 开发者社区运营实习生(实时互动 / Voice AI 方向,本招聘长期有效)地点:北京朝阳区望京南/上海杨浦区五角场这份实习将给你带来:产品与技术成长: 深入学习垂类 AI 产品从技术到落地的全生命周期,构建全面的产…

引领未来,智启新程:Compete MIS平台——低代码时代的全能信息化管理解决方案

平台核心优势包括: 1. 双核驱动架构:提供Java和Go双版本服务端,分别满足高稳定性与高效能需求;客户端采用C# WPF开发,通过插件化设计实现灵活扩展与快速更新。 2. Manager默认应用:集成进销存与财务管理功能,实…

终端

参见:从电传打字机到 xterm ——人类与终端的 70 年 | 小红书

2025.11.06 - A

今天上了数据结构和体育,感觉挺好,就是眼睛片碎一地了,惶恐惶恐

CF2085D Serval and Kaitenzushi Buffet

这里是摘要题目链接 比较 mini 的模拟赛考到了,想了半小时 DP 终于在结束前 5min 成功想出正解但是并没有写完。 解题思路 首先我们考虑什么时候可以拿取寿司。容易发现因为我们必须在 \(n\) 分钟结束时吃完所有拿取的…