Java实现验证码识别:Tess4J与图像预处理实战指南
简介基于net.sourceforge.tess4j库的OCR验证码识别Java设计源码面向需要实现验证码自动识别的Java开发者提供了一套完整可用的工程实现方案。方案以tess4jTesseract-OCR的Java封装为核心组件完成光学字符识别适用于自动化测试登录绕过、数据采集辅助、无障碍服务等场景也适合作为研究OCR技术落地的入门参考。资源包为zip格式共20个文件整体大小约30.99MB包含9个Java源文件核心识别逻辑与调用接口、2个traineddata语言训练数据、2个GIF验证码样例图片以及ttf字体、xml配置、tessdata配置、api_config、hocr等辅助资源文件组织清晰便于导入工程后按模块理解。目前已有338人浏览学习。通过此源码读者可掌握tess4j的初始化配置、语言包加载、图像预处理与识别调用方法理解验证码识别系统的完整文件结构与实际落地要点同时还可了解针对复杂验证码结合深度学习进行优化的思路对从事Java OCR开发、自动化测试或安全研究的人员具有切实的参考价值。1. 验证码识别先别急着上云Tess4J 这套 Java 方案能直接落地做 Java 后端的人迟早会碰到一个需求登录页的图形验证码要自动识别测试环境要批量刷数据、内部系统要做自动化巡检。这类验证码大多只是防脚本复杂度不高用云 OCR 大材小用还得考虑网络和费用。我一般第一版就上基于 net.sourceforge.tess4j 的 OCR 方案。Tess4J 是 Tesseract OCR 引擎的 Java 封装通过 JNA 直接调用底层识别库离线可用、免费、集成简单配合语言包和字符白名单就能把纯数字或数字字母混合验证码的识别率做到可用水平。这篇笔记从依赖搭建、图像预处理到参数调优和踩坑给出一套可以直接照做的 Java 设计源码路线适合 Java 工程师、自动化测试和需要批量处理图片字符的开发场景。2. Tess4J 是什么、为什么选它先搞清楚它和 Tesseract 的关系2.1 Tess4J 本质是 JNA 封装核心还是 Tesseract 的 LSTM 识别引擎Tess4J 的 Maven 坐标是 net.sourceforge.tess4j:tess4j它做的事情非常纯粹用 JNA 加载 Tesseract 的本地库Windows 下是 dllLinux 下是 so然后把 Java 层的图片对象转成引擎能识别的格式再调用识别接口。真正干活的还是 Tesseract 的 LSTM 字符识别引擎Tess4J 只是把 C 接口翻译成了 Java 接口。这里要先建立一个认知Tess4J 不负责图像预处理。识别验证码之前去噪、二值化、去干扰线这些事都得在 Java 层自己做。Tess4J 提供的是doOCR(File)、doOCR(BufferedImage)这类接口你给它一张干净的二值图它返回识别字符串你给它一张带彩色噪点和扭曲背景的原图它照样执行但返回结果基本不能看。这是我做完第一个验证码识别项目后最深刻的体会——识别率低的锅八成在图片质量不在 OCR 引擎。那为什么还要选 Tess4J三个理由。第一离线可用部署到内网服务器不用申请外网权限也不存在接口调用费用。第二进程内直接调用省掉了命令行调用tesseract时的进程启动开销和文件流转适合在 Java 服务里做高并发识别。第三语言包机制成熟英文、中文、数字混排都能切换而且支持通过setVariable设置字符白名单这一点对验证码识别至关重要后面会专门讲。2.2 和百度 OCR、腾讯 OCR、原生 Tesseract 命令行对比各自的适用边界选型时我习惯把方案分四类列个对比表就清楚自己该走哪条路方案精度离线支持成本集成复杂度适用场景Tess4J中高依赖预处理支持免费低Maven 引依赖内网部署、批量识别、可离线环境百度/腾讯云 OCR高不支持按次计费低HTTP 调用复杂验证码、手写体、无内网限制原生 Tesseract 命令行中高支持免费中要管进程一次性脚本、批量命令行处理OpenCV 自研识别看模型支持免费高要训练模型强干扰、扭曲严重的对抗验证码百度 OCR 和腾讯 OCR 的云服务精度确实更高尤其对粘连字符和彩色背景的容错比 Tesseract 好一个档次但它们有两个硬伤一是要求外部网络畅通内网环境直接废掉二是按次收费测试环境一天刷几千次验证码账单会让人心疼。命令行方式偶尔跑脚本还行放进 Java Web 服务里要处理进程生命周期、超时杀进程这些杂事不划算。OpenCV 自研识别这条路上限最高但那是另一条技术路线了需要标注数据、训练 CNN 模型一个验证码识别需求用不上这么重的方案。Tess4J 是投入产出比最高的起点先跑通识别率不够再去叠图像预处理再不够才考虑升级到深度学习。这个递进路径也是我推荐给团队的做法。2.3 验证码识别的完整链路预处理、分割、识别Tess4J 只负责最后一环验证码的对抗逻辑很简单人眼能看懂但机器不容易看懂。手段无非是背景噪点、字符粘连、旋转扭曲、干扰线、颜色混淆。体现在 OCR 流程里标准链路是四步图像读取、图像预处理、字符分割、字符识别。Tess4J 接管的是最后一步前面三步要自己在 Java 里写。图像预处理的目的是把彩色验证码降维成黑白分明、字符边缘清晰的二值图。Tesseract 的 LSTM 模型是在大量印刷体文本上训练的它对「干净的黑字白底」最友好。验证码里的彩色噪点和干扰线对它来说就是噪声会直接干扰字符分割。所以预处理的优先级高于任何识别参数一张处理得当的图用默认参数都能有六成以上识别率一张原图直出参数调到天上也就两成。字符分割在 Tess4J 里是自动完成的引擎内部会根据连通域和行高把字符切分开。但遇到粘连严重的验证码自动分割会失败把两个字符认成一个。这个问题靠预处理能缓解一部分真正的硬解要上像素级分析本文后面会给出干扰线去除和尺寸归一化的具体做法。理解了这个分工你在调参时才不会瞎试——白名单解决的是「认识哪个字符」的问题预处理解决的是「能不能看清楚字符」的问题。3. 最小可运行Maven 依赖、语言包和第一版识别代码3.1 引入 tess4j 依赖并准备好语言包文件新建一个普通 Java 工程在pom.xml里加上 Tess4J 依赖。版本号建议用当前稳定版我写文章时用的坐标是这样的dependency groupIdnet.sourceforge.tess4j/groupId artifactIdtess4j/artifactId version5.x/version /dependency重点在这里5.x不是让你直接照抄而是提示你到 Maven 中央仓库看一眼最新版本。Tess4J 版本更新会连带 JNA 和 OpenCV 的版本变化不同版本的 API 基本一致但本地库的兼容性差异较大。装完依赖后去 Tesseract 官方语言包仓库下载eng.traineddata这是英文识别必需的语言文件。如果是纯数字验证码eng就够如果涉及中文再补chi_sim.traineddata。语言包放哪是有讲究的。常见做法是在src/main/resources下建tessdata目录把 traineddata 文件放进去这样打包成 jar 后语言包会被带进去。但运行时要注意某些容器环境从 classpath 加载会出问题更稳妥的方式是在服务器上建一个固定目录/opt/ocr/tessdata把语言包放绝对路径下代码里用setDatapath指向它。我自己倾向后者因为以后更新语言包不用重新打包重启直接替换文件就能生效。3.2 最小识别代码TessBaseAPI 初始化与 doOCR依赖就绪后整一套最小可用代码。用这张图测试白底、黑色四位纯字母验证码无干扰线。先跑通再看识别率问题。import net.sourceforge.tess4j.Tesseract; import net.sourceforge.tess4j.TesseractException; import java.io.File; public class SimpleCaptchaOcr { public static void main(String[] args) throws TesseractException { // 1. 创建 Tesseract 实例注意它不是线程安全的 Tesseract tesseract new Tesseract(); // 2. 指向训练数据目录这里用绝对路径 tesseract.setDatapath(/opt/ocr/tessdata); // 3. 设置语言包eng 对应英文chi_sim 对应简体中文 tesseract.setLanguage(eng); // 4. 识别模式设为 7单行文本适合验证码这种单行短字符串 tesseract.setPageSegMode(7); // 5. 白名单限制只识别数字和大写字母 tesseract.setVariable(tessedit_char_whitelist, 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ); // 6. 执行识别 File captchaFile new File(/tmp/captcha.png); String result tesseract.doOCR(captchaFile); // 7. 去掉结果里的换行和多余空格 System.out.println(识别结果: [ result.trim() ]); } }这段代码的每一步都对应一个会影响结果的决策点。setDatapath写错路径是新手最常见的错误路径要指到包含 traineddata 文件的目录而不是文件本身的路径。setLanguage要和实际语言包匹配指定eng但没放eng.traineddata会直接抛运行时异常。setPageSegMode(7)是专门给单行文本用的Tesseract 默认的 PSM 3 是自动分页对验证码这种没有段落结构的图片反而会浪费算力在错误的版面分析上。白名单这步尤其关键它直接告诉引擎这次识别只在规定的字符集合里选答案。验证码通常只有数字和少量字母把集合限定住就能排除掉把0认成O、把1认成l这类字母混淆。3.3 从 doOCR 到输出结果的内部逻辑结合 tess4j 语言包路径和代码排查的要点doOCR不是简单地把图片交给引擎就完事它内部做了好几层工作。Tess4J 先把图片转成二进制字节流初始化一个TessBaseAPI实例再调用 JNA 封装的本地方法逐层执行版面分析、字符分割、特征提取、LSTM 推理、置信度评估最后把识别出的文本拼接返回。理解这个流程的意义在于出了问题时你知道该去哪一层找原因。先排查数据路径。如果日志出现Could not initialize Tesseract API或TesseractException: Cannot read OCR一类的报错第一反应就是setDatapath指向的目录里没有语言包。我把语言包放/opt/ocr/tessdata/eng.traineddatasetDatapath就写/opt/ocr/tessdata两边对应上才能加载成功。再排查识别模式。PSM 是 Tesseract 里影响结果最直接的一个参数验证码场景优先级排序是7单行文本 8单个单词 6统一的文本块 13原始行。数字验证码用 7 效果最好单个大字符验证码用 8 更稳如果图片里混排了多行信息才考虑用 6。这里有个血泪经验不要盲目套默认值跑一批样本逐个 PSM 试你会发现同一张图在不同 PSM 下识别结果差异巨大。最后看输出值。识别成功的返回串可能有换行和空格验证码需要干净输出所以代码里加了trim()和后续的正则过滤。识别失败时引擎不会抛异常而是返回空字符串或乱码——非空白、但完全不是目标字符。这种静默失败最坑人后面避坑章节专门说。4. 图像预处理验证码识别率提升的实战细节4.1 灰度化与二值化把彩色噪点压缩成黑白二元信息拿到彩色验证码原图第一件事是灰度化。RGB 三通道信息对 Tesseract 没意义字符识别只看形状轮廓彩色信息反而是干扰源。灰度化最常用的是加权平均gray 0.299R 0.587G 0.114B人眼对绿色敏感这个权重更接近视觉感知。Java 的BufferedImage可以直接用 Graphics 绘制转灰度省去逐像素计算。import java.awt.Graphics2D; import java.awt.image.BufferedImage; public class CaptchaPreprocessor { /** 灰度化把彩色图转成单通道灰度图 */ public static BufferedImage toGray(BufferedImage src) { BufferedImage gray new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_GRAY); Graphics2D g gray.createGraphics(); g.drawImage(src, 0, 0, null); g.dispose(); return gray; } /** 二值化按阈值把灰度图转为纯黑纯白 */ public static BufferedImage binarize(BufferedImage src, int threshold) { BufferedImage binary new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_BINARY); for (int y 0; y src.getHeight(); y) { for (int x 0; x src.getWidth(); x) { int rgb src.getRGB(x, y); int r (rgb 16) 0xFF; int g (rgb 8) 0xFF; int b rgb 0xFF; int gray (r g b) / 3; // 大于阈值的像素设为白色否则设为黑色 binary.setRGB(x, y, gray threshold ? 0xFFFFFF : 0x000000); } } return binary; } }灰度化的逻辑很简单TYPE_BYTE_GRAY直接让 JVM 按灰度模型绘制底层做好了对 RGB 的加权转换。二值化的threshold参数要调试常见取值在 120-180 之间。阈值太高会把浅色字符滤掉太低会把噪点认成前景。我给个经验策略验证码背景是浅色、字符是深色时阈值取 150 起步对照输出效果微调。注意代码里的gray threshold ? 0xFFFFFF : 0x000000把最亮的设为白字符深色就变成了黑色前景这正是和 Tesseract 训练样本一致的方向。顺带说明/3的平均灰度算法虽然简单但对红绿蓝占比不敏感遇到红色背景这类极端场景会失真。此时建议换成加权公式gray (int) (0.299 * r 0.587 * g 0.114 * b)用这个值参与阈值判断。识别率不够时这里是第一个优化点。4.2 干扰线去除用像素扫描和颜色统计滤掉细线条灰度化只去掉了色彩干扰线在灰度图里依然是可见线条必须进一步处理。常规干扰线是一条或多条横穿字符的细曲线颜色与字符接近但通常更浅、更细。针对这个特征最实用的方法有两个颜色聚类和连通域大小过滤。颜色聚类的出发点是验证码为了可读性字符主色和背景、干扰线的颜色分布是有统计规律的。统计整张图片每个像素的灰度值出现频率最高的值是背景次高的可能来自干扰线。把低频率的孤立像素置成背景色就能有效擦掉细线。这里给出一个按像素邻域判断的实现public static BufferedImage removeNoiseByNeighbor(BufferedImage src, int threshold) { int w src.getWidth(); int h src.getHeight(); BufferedImage dest new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY); for (int y 0; y h; y) { for (int x 0; x w; x) { int rgb src.getRGB(x, y); int r (rgb 16) 0xFF; int g (rgb 8) 0xFF; int b rgb 0xFF; int gray (r g b) / 3; // 统计 8 邻域中与当前像素灰度接近的数量 int similarCount 0; for (int dy -1; dy 1; dy) { for (int dx -1; dx 1; dx) { if (dx 0 dy 0) continue; int nx x dx; int ny y dy; if (nx 0 || ny 0 || nx w || ny h) continue; int neighborRgb src.getRGB(nx, ny); int nGray (((neighborRgb 16) 0xFF) ((neighborRgb 8) 0xFF) (neighborRgb 0xFF)) / 3; if (Math.abs(gray - nGray) threshold) { similarCount; } } } // 邻域颜色一致性低判定为孤立的噪点置为背景色白色 if (similarCount 2) { dest.setRGB(x, y, 0xFFFFFF); } else { dest.setRGB(x, y, gray 150 ? 0xFFFFFF : 0x000000); } } } return dest; }这段代码的思路是字符笔画是连续的相邻像素灰度接近噪点和干扰线是稀疏的周围像素与它差异大。similarCount统计 8 邻域里灰度差不超threshold的像素数少于 2 就认为是孤立点。参数threshold建议取值 30-60越小过滤越激进但也可能伤字符边缘。这种逐像素遍历的性能不差单张 300x100 的验证码在毫秒级能跑完。如果图片中干扰线特别粗单纯邻域判断不够需要配合形态学处理用 OpenCV 的开运算去掉细线。Maven 里引入 OpenCV Java 绑定后核心操作浓缩成三行Mat src Imgcodecs.imread(imagePath, Imgcodecs.IMREAD_GRAYSCALE); Mat binary new Mat(); Imgproc.threshold(src, binary, 150, 255, Imgproc.THRESH_BINARY); Mat kernel Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2, 2)); Imgproc.morphologyEx(binary, binary, Imgproc.MORPH_OPEN, kernel);第一行把图片以灰度模式读入。第二行做全局阈值二值化。第三行创建了一个 2x2 的矩形结构元这个尺寸是关键它恰好小于字符笔画宽度、大于干扰线宽度开运算就能优先擦除细线。如果干扰线比字符粗把Size(2, 2)改成Size(1, 3)这类长条结构元按方向过滤。4.3 字符白名单与 PageSegModetess4j 语言包参数设置的 3 个必调项预处理把图片做干净后识别参数就是最后一道精度开关。我每次接新验证码项目必调三个参数setPageSegMode、setVariable(tessedit_char_whitelist)、setLanguage。这套组合搞不定再加setVariable(user_defined_dpi, 300)和setVariable(preserve_interword_spaces, 1)。先解释白名单为什么是验证码识别的神器。验证码字符集通常是已知的纯数字就0123456789数字加字母就加上ABCDEFGHIJKLMNOPQRSTUVWXYZ。Tesseract 的 LSTM 模型在识别时会在整个字符集里做概率排序白名单的作用是把候选集锁死在指定范围内大幅度降低混淆率。比如0和O在白名单里同时存在时引擎会结合上下文选如果只允许数字O直接被排除识别率立竿见影。然后是 PSM 的配合。白名单解决识别内容范围PSM 解决版面结构假设。验证码是单行短文本setPageSegMode(7)告诉引擎按单行处理不用做复杂的版面分析。遇到极短的单个字符验证码改用 PSM 8遇到包含运算式比如35?的验证码PSM 7 依然适用但要额外在图像预处理时保证?符号的清晰度。语言包的选择容易被忽略。英文数字验证码用eng最合适eng.traineddata内置了数字和全字母表纯中文验证码要加chi_sim。但注意中英文混排验证码不要同时加载两个语言包setLanguage(engchi_sim)虽然语法支持识别速度会变慢而且混合语言模型对字符分割的约束更多反而容易误判。实战里先加载单一语言包测效果不佳再叠加不要一开始就都拉上。5. 避坑与常见问题排查从 UnsatisfiedLinkError 到识别乱码5.1 现象启动即抛UnsatisfiedLinkError或NoClassDefFoundError识别功能完全不可用原因Tess4J 通过 JNA 加载本地库本地库文件在 Windows 是libtesseract.dllLinux 是libtesseract.so。这些文件通常由 Tess4J 的 jar 包自动从win32-x86-64或linux-x86-64目录释放但如果服务器架构特殊ARM、MIPS自动释放的库用不了路径加载失败。解决先看 Java 进程的java.library.path包含哪些目录把对应平台的本地库手动放到其中一个目录再启动。另一种做法是用 JNA 的显式加载替代默认机制在代码里先Native.register(tesseract)再创建 Tesseract 实例。实际排查时优先换用与服务器架构匹配的 Tess4J 版本版本号对上后这类错误九成能消失。5.2 现象doOCR返回空字符串或完全乱码但代码没有异常原因一张图上可能出现三种静默失败语言包不匹配、图片对比度过低、字符方向旋转了。语言包不匹配时引擎按错误语言的特征集做识别结果自然不可读。对比度过低时字符和背景灰度相近二值化后字符断裂引擎每个字符都只有一半像素分割失败。字符旋转角度超过 30 度也会让 LSTM 模型彻底认不出来。解决按顺序排查。先确认识别前调用了二值化且二值化参数适配当前验证码背景再检查语言包和图片的字符类型是否一致英文验证码必须用eng最后在预处理阶段加旋转矫正对BufferedImage做旋转后重采样通常用AffineTransform旋转 -5 到 5 度测一轮选置信度最高的一次输出。增加 DPI 参数setVariable(user_defined_dpi, 300)也能改善小图片的乱码问题Tesseract 对低 DPI 图的特征提取会打折。5.3 现象数字验证码识别结果混入字母0被识别成O、1被识别成l原因跑通了但识别内容不对这不是引擎坏了是候选字符集没有限制。默认的eng语言包包含全部英文字母和数字LSTM 模型对形近字符的区分本来就吃力加上验证码字体通常是变形的数字和字母的边界更模糊。没有白名单引擎就会在O和0之间犹豫最终给出一个概率稍高的错误答案。解决给Tesseract实例设置白名单。代码里setVariable(tessedit_char_whitelist, 0123456789)即可注意必须在doOCR前调用。更彻底的方案是统一转大写过滤识别结果出来后用正则replaceAll([^0-9A-Z], )把杂质字符清理掉。这一步不属于调模型属于后处理兜底但它能把识别率从六成拔到八成。5.4 现象单张识别耗时几秒到十几秒高并发场景直接卡死原因Tess4J 初始化TessBaseAPI的成本很高每次doOCR时创建新实例相当于反复加载语言包和模型文件耗时全耗在初始化上。另一个隐性问题是 PSM 用默认的自动模式引擎会做不必要的版面分析对验证码这种小图也是浪费。解决把 Tesseract 实例设计成复用对象每个线程持有自己的 Tesseract 实例。Tess4J 官方文档明确实例不是线程安全的所以不能全局单例共享但可以用ThreadLocalTesseract包一层每个线程复用。另外将 PSM 固定为 7省掉版面分析。优化后单张耗时通常能降到 500 毫秒以内接近可接受范围。如果还嫌慢就得考虑缩小图片尺寸或换轻量模型不再推荐在 Tess4J 框架内继续优化。5.5 现象换一台服务器部署识别率骤降同样的代码同样的图片原因最常见的是环境差异导致的字体和 DPI 问题。验证码字体在本地 Windows 上测试时字符渲染方式和测试服务器不一致另一台服务器上 OpenCV 或本地库版本不同预处理阶段就输出了不同的二值图。这类问题最玄学排查半天经常发现是本地库版本把图片解码方式改了。解决把预处理结果先落盘直接看图。我会在binarize之后把结果ImageIO.write(binary, png, new File(/tmp/debug.png))输出肉眼确认字符是否清晰、干扰线是否去除。这个习惯帮我避开了好几次「图片处理逻辑没问题、实际输出一团糟」的翻车。确认预处理后的图片质量一致再对比两边的 Tess4J 版本和语言包文件大小语言包版本不一致是最容易被忽略的黑匣子。6. 进阶技巧用四步组合拳把特定验证码识别率拉到八成以上当你手里的验证码是「白底、四到五位、数字加大写字母、带一条干扰线」这类常见配置上面的散装技巧已经够用但组合起来有顺序讲究。我给自己的代码库沉淀了一套固定流程只改两个参数就能适配大部分同类验证码。完整流程是先放大、再灰度、然后二值化、最后白名单识别。放大是第一步因为验证码原始尺寸往往很小Tesseract 对低于 200 DPI 的图片识别率会明显下降。把图片放大三倍等于把 DPI 抬上去LSTM 模型能提取到更完整的笔画特征。放大时插值算法也有讲究VALUE_INTERPOLATION_BICUBIC比默认的双线性插值保留更多边缘细节。public String recognizeCaptcha(BufferedImage captchaImage) { // 第一步双三次插值放大三倍 int targetW captchaImage.getWidth() * 3; int targetH captchaImage.getHeight() * 3; BufferedImage scaled new BufferedImage(targetW, targetH, BufferedImage.TYPE_INT_RGB); Graphics2D g scaled.createGraphics(); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); g.drawImage(captchaImage, 0, 0, targetW, targetH, null); g.dispose(); // 第二步灰度化 BufferedImage gray toGray(scaled); // 第三步二值化阈值 160 需要按实际图片微调 BufferedImage binary binarize(gray, 160); // 第四步白名单 单行模式识别 Tesseract tesseract threadLocalTesseract.get(); tesseract.setPageSegMode(7); tesseract.setVariable(tessedit_char_whitelist, 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ); String raw tesseract.doOCR(binary); // 后处理只保留目标字符 return raw.replaceAll([^0-9A-Za-z], ); }代码里的threadLocalTesseract是复用 Tesseract 实例的ThreadLocalT容器实际项目中初始化代码长这样ThreadLocalTesseract threadLocalTesseract ThreadLocal.withInitial(() - { Tesseract t new Tesseract(); t.setDatapath(/opt/ocr/tessdata); t.setLanguage(eng); return t; });。这一步不做高并发场景的耗时和内存占用会把你拖垮。这套流程我跑过不少内部系统的登录验证码四到五位的数字加字母混合验证码识别率稳定在八成以上。剩下的失败样本大多是字符极度粘连或字体太艺术化的类型那种场景 Tess4J 已经到能力边界了再用它死磕纯属浪费时间换深度学习方案才是正路。事后复盘我最想提醒的是先花十分钟确认验证码的生成规则再动手写代码。有的验证码把字符集写死在小写字母加数字白名单写小写有的图片固定 60x20 像素放大四倍比三倍更合适有的干扰线颜色和字符完全相同邻域过滤要反过来先判断颜色连通域。每套验证码都有自己的小脾气把这些前置信息摸清我后续调参的时间能省一半。这是做了六七个验证码识别需求后最值钱的一条经验希望帮到你。本文还有配套的精品资源点击获取

相关新闻

voxtral.c 滚动 KV 缓存解析:让语音识别轻松支持无限量长音频

voxtral.c 滚动 KV 缓存解析:让语音识别轻松支持无限量长音频

【免费下载链接】voxtral.c Pure C inference of Mistral Voxtral Realtime 4B speech to text model 项目地址: https://gitcode.com/gh_mirrors/vo/voxtral.c 点击查看 免费下载 voxtral.c 是一个纯 C 语言实现的 Mistral Voxtral Realtime 4B 语音识别&#xff…

2026/10/11 12:05:25 阅读更多 →
光纤水声信号识别:从时序预处理到TCN部署实战

光纤水声信号识别:从时序预处理到TCN部署实战

简介:本资源是一套面向毕业设计、课程设计与期末大作业的深度学习实践项目,聚焦光纤水声信号识别这一典型海洋声学应用场景,适用于具备Python与PyTorch基础的本科生及入门级研究者。压缩包共276个文件,含11个核心Python脚本&#…

2026/10/11 12:05:25 阅读更多 →
GDNet 4.0.0轻量级网络库:Unity接入与避坑实战

GDNet 4.0.0轻量级网络库:Unity接入与避坑实战

简介:GDNet 4.0.0 是一套基于 System.Net 的开源 C# 游戏网络框架,适用于 Unity 及各类 VS 项目,面向独立开发者与公司团队,主要解决高并发、多人在线及网络同步难题,学习曲线平缓,几天即可上手。资源包为 …

2026/10/11 12:05:25 阅读更多 →

最新新闻

泥石流滑坡目标检测数据集:YOLO+VOC双格式解析与YOLOv8训练避坑指南

泥石流滑坡目标检测数据集:YOLO+VOC双格式解析与YOLOv8训练避坑指南

简介:目标检测数据集聚焦泥石流与滑坡两类地质灾害场景,面向需要训练YOLO、Faster R-CNN等检测模型的算法工程师、研究生及防灾减灾研究人员。数据集以VOC与YOLO双格式组织,JPEGImages、Annotations、labels三个文件夹一一对应,共…

2026/10/11 20:37:23 阅读更多 →
Axure原型设计实战:组件对齐、动态面板与母版复用全解析

Axure原型设计实战:组件对齐、动态面板与母版复用全解析

简介:《Axure教程[汇编].pdf》是一份面向产品经理、UI/UX 设计师及软件开发人员的 Axure RP Pro 原型设计实战指南,内容结构完整,从基础操作到高级交互循序渐进。教程从新建项目、拖拽组件、编辑属性等基本操作讲起,逐步覆盖组件位…

2026/10/11 20:37:23 阅读更多 →
房屋租赁推荐系统

房屋租赁推荐系统

房屋租赁推荐系统选题背景与意义 随着城市化进程的不断加快以及人口流动性的显著提升,住房需求呈现出日益增长且结构复杂化的趋势。尤其是在一线及新一线城市,大量外来务工人员、高校毕业生以及年轻职场人士对短期或中长期住房租赁服务的需求持续攀升。传…

2026/10/11 20:37:23 阅读更多 →
基于VGG16的图像检索系统:毕业设计实战指南与避坑技巧

基于VGG16的图像检索系统:毕业设计实战指南与避坑技巧

简介:这份资源是一套基于VGG16的图像检索系统完整项目,面向深度学习入门者、图像处理方向学生及需要完成毕业设计的人群,帮助解决以图搜图场景下特征提取与相似度匹配的实现问题。项目使用Python与Keras搭建,涵盖图像预处理、VGG1…

2026/10/11 20:37:23 阅读更多 →
多前置仓模式下生鲜电商系统设计:库存、路由与履约实战

多前置仓模式下生鲜电商系统设计:库存、路由与履约实战

做生鲜电商的人应该都有体会:一个仓管不住,谈一百个仓就是灾难。万象生鲜系统走的是多前置仓模式,核心就是把库存压到离用户足够近的位置,用密度换时效。听起来不复杂,但真正落地时需要面对的是库存碎片化、订单路由、…

2026/10/11 20:37:23 阅读更多 →
LingBot-World 2.0源码结构全解读:wan目录如何把Wan2.2改造成因果世界模型

LingBot-World 2.0源码结构全解读:wan目录如何把Wan2.2改造成因果世界模型

【免费下载链接】lingbot-world-v2 Infinite Worlds with Versatile Interactions 项目地址: https://gitcode.com/gh_mirrors/li/lingbot-world-v2 点击查看 免费下载 LingBot-World 2.0(LingBot-World-Infinity) 是一款可无限交互的世界模…

2026/10/11 20:36:23 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →