使用 Swift 解析验证码(结合 Tesseract OCR)

news/2025/10/28 23:23:17/文章来源:https://www.cnblogs.com/ocr12/p/19172930
  1. 环境准备
    1.1 安装 Swift

macOS 自带 Swift,如需更新,可使用:

xcode-select --install

更多内容访问ttocr.com或联系1436423940
然后检查 Swift 版本:

swift --version

Linux 用户可以从 Swift 官方网站
下载对应版本,并按照说明安装。

1.2 安装 Tesseract OCR
macOS(Homebrew 安装)
brew install tesseract

Linux(Ubuntu 示例)
sudo apt update
sudo apt install tesseract-ocr -y

Windows

Windows 用户可以从 Tesseract 官方 GitHub
下载并安装 Tesseract,并配置环境变量。

检查 Tesseract 是否安装成功:

tesseract --version

1.3 创建 Swift 项目
mkdir SwiftOCR
cd SwiftOCR
swift package init --type executable

然后,在 Package.swift 中添加 Tesseract 相关依赖:

// swift-tools-version:5.5
import PackageDescription

let package = Package(
name: "SwiftOCR",
dependencies: [
.package(url: "https://github.com/gali8/Tesseract-OCR-iOS.git", from: "4.0.0")
],
targets: [
.executableTarget(
name: "SwiftOCR",
dependencies: ["Tesseract-OCR-iOS"]
)
]
)

运行:

swift build

  1. 代码实现

编辑 Sources/SwiftOCR/main.swift,写入以下代码:

import Foundation
import TesseractOCR

// 图像预处理
func preprocessImage(inputPath: String, outputPath: String) {
guard let image = NSImage(contentsOfFile: inputPath) else {
print("无法打开图片")
return
}

// 转换为灰度图像
let grayscaleImage = CIImage(data: image.tiffRepresentation!)?.applyingFilter("CIPhotoEffectMono")// 二值化处理
let context = CIContext()
if let outputImage = grayscaleImage, let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {let processedImage = NSImage(cgImage: cgImage, size: image.size)// 保存处理后的图像let data = processedImage.tiffRepresentationtry? data?.write(to: URL(fileURLWithPath: outputPath))
}

}

// 识别验证码
func recognizeCaptcha(imagePath: String) -> String {
if let tesseract = G8Tesseract(language: "eng") {
tesseract.engineMode = .tesseractOnly
tesseract.pageSegmentationMode = .singleLine
tesseract.image = NSImage(contentsOfFile: imagePath)
tesseract.recognize()
return tesseract.recognizedText ?? "识别失败"
}
return "初始化失败"
}

let inputImage = "captcha.png" // 你的验证码图片路径
let processedImage = "processed_captcha.png"

// 预处理验证码图像
preprocessImage(inputPath: inputImage, outputPath: processedImage)

// OCR 识别
let result = recognizeCaptcha(imagePath: processedImage)
print("识别出的验证码: (result)")

  1. 代码解析
    3.1 图像预处理

为了提高 OCR 识别率,我们对验证码进行了优化:

转换为灰度图像:

let grayscaleImage = CIImage(data: image.tiffRepresentation!)?.applyingFilter("CIPhotoEffectMono")

二值化处理(增强对比度):

if let outputImage = grayscaleImage, let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
let processedImage = NSImage(cgImage: cgImage, size: image.size)
}

保存处理后的图像:

let data = processedImage.tiffRepresentation
try? data?.write(to: URL(fileURLWithPath: outputPath))

3.2 OCR 解析

初始化 Tesseract OCR:

if let tesseract = G8Tesseract(language: "eng") {

设置 OCR 识别模式(PSM 6 适用于验证码):

tesseract.pageSegmentationMode = .singleLine

加载验证码图像并执行 OCR 识别:

tesseract.image = NSImage(contentsOfFile: imagePath)
tesseract.recognize()

获取识别结果:

tesseract.recognizedText ?? "识别失败"

  1. 运行程序

确保 captcha.png 存在于项目目录,然后运行:

swift run

示例输出:

识别出的验证码: X9GH5

  1. 提高 OCR 识别率
    5.1 选择合适的 PSM 模式

Tesseract 提供了不同的页面分割模式:

tesseract.pageSegmentationMode = .singleChar

PSM 6:假设是单行文本(默认推荐)

PSM 7:只检测单个文本行

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

5.2 只识别特定字符

如果验证码仅包含字母和数字:

tesseract.charWhitelist = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

5.3 进一步优化

降噪处理:可以使用 Core Image 的 CIMinimumComponent 或 CIColorControls 来提高对比度

字符分割:如果验证码字符粘连,可尝试 OpenCV-Swift 进行字符分割

使用深度学习:如果 Tesseract 不能满足需求,可以结合 Core ML 或 TensorFlow Lite 进行训练,提高验证码识别成功率

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

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

相关文章

常见排序算法Java实现

/**常见排序算法汇总 */ public class SortAlgorithms { /**冒泡排序(Bubble Sort) 思想:相邻元素两两比较,大的往后沉。 时间复杂度:O(n^2) 稳定性:稳定 */ public static void bubbleSort(int[] arr) { for (i…

题解:qoj1875 Nein

题意:给出 \(k,n\),问第 \(n\) 个是 \(10^k-1\) 的倍数的且每个数字不含有 \(9\) 的数是多少。\(k\le 18,n\le 10^{18}\)。 做法: 首先先跳出一个很显然的想法,一开始看这个东西觉得应该是拆成 \(x10^k-x\) 去讨论…

【uni-app】申请高德地图key,封装map.js,实现H5、iOS、Android通过getlocation获取地图定位信息(摘)

一、map组件基础使用<template><view class="contact"><image class="img" :src="formData.headImg"></image><view class="info"><view @…

.NET开发上手Microsoft Agent Framework(一)从开发一个AI美女聊天群组开始

前言 在AI快速发展的今天,微软推出了多个AI开发框架,从早期的AutoGen到Semantic Kernel,再到最新的Microsoft Agent Framework。很多开发者可能会有疑问:为什么微软要推出这么多框架?它们之间有什么区别?本文将通…

10/28

10/28今天在工程实训里学习了金属工艺加工,学习了java的相关网课

大学四年的学费/生活费自足攻略

1997年夏天带着通过亲戚朋友筹集的学费4000元踏上了北上兰州的旅程。我独自一人第一次穿越3000公里来到兰州,办好入学手续住进宿舍。虽然没有政和的老乡,但是有几位南平的老乡来找我,特别是建瓯话和政和话是一样的,…

175天 隧道技术篇防火墙组策略FRPNPSChiselSocks代理端口映射C2上线

三种工具 frp/NPS/Chisel 不用过多的纠结去使用哪一款工具 frp的C2上线 解决的问题: 1.C2上线 2.实现信息收集(两个) 这边可以使用CS生成一个47.xx.xx.xx的后门,然后搭建frp后,进行上线 下面相当于是把端口映射出…

10.28每日总结

今天的主要课程有人机交互技术,软件构造,软件企业文化。完成了上周机器学习的作业以及企业文化的报告,软考准备开始专精刷题里,加油!

102302126李坤铭作业1

作业1 用requests和BeautifulSoup库方法定向爬取给定网址(http://www.shanghairanking.cn/rankings/bcur/2020 )的数据,屏幕打印爬取的大学排名信息。 1)代码: 点击查看代码 import requests from bs4 import Bea…

10月28日日记

1.今天进行工程实训 2.明天学习马哲 3.负载因子为什么通常设置为0.75?

【大模型应用开发】之本地部署大模型

本地部署本地部署一般是在自己的服务器上部署,但这里以本地电脑进行部署为例,由于电脑配置远远无法支持大模型配置要求,届时部署下来的也是阉割版的。本地部署一种方案就是ollama,官方地址:https://ollama.com访问…

link元素的用法及HTML样板

本人学习时候很容易额外扩展,因为很多次见到同一个熟悉但不了解的代码或用法我会很难受,所以我把基本用法都列出来了,看起来会很冗杂(因为不仅不同文章重复,相同文章我也在重复-.-),但结合实例来回对比查阅让我…

Raft 一致性算法简介

引言与背景 分布式系统中,为了在 非拜占庭故障(如节点宕机或网络分区)情况下保持数据一致性,往往需要分布式共识算法来确保多个副本状态统一 。长期以来,Leslie Lamport 提出的 Paxos 算法 一直是这一领域的代表…

10月28号

今天上午进行了铁道认知实训

URL验证绕过速查表:全面解析SSRF与CORS绕过技术

本文详细介绍了PortSwigger最新发布的URL验证绕过速查表工具,涵盖域名混淆、伪相对URL、环回地址编码等核心技术,帮助安全测试人员快速生成绕过payload,有效检测SSRF、CORS配置错误等漏洞。介绍URL验证绕过速查表 U…

https://avoid.overfit.cn/post/44c8d547475340d59aa4480f634ea67f

现在的 Agent 系统有个很明显的问题 —— 会话一结束,什么都忘了。 这不是个技术缺陷,但是却限制了整个系统的能力边界。Agent 可以做推理、规划、执行复杂任务,但就是记不住之前发生过什么。每次对话都像是第一次见…

23题黄金分割

某同学在学习了黄金分割后对于黄金分割产生了浓厚的兴趣,于是他开始探究有关黄金分割的相关性质,请你帮助他完成以下任务。【任务一】作一个黄金分割 (1)如图, \(BC \perp AB\), \(BC = \frac{1}{2} AB\),作 \(…

记录一次成功的springboot2

pom文件<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"x…

算法学习-素数筛法【埃氏筛法、线性筛法】

普通筛法: 核心思路: 使用一个布尔数组记录此数是否为素数, 从2~n便利, 如果是此数记录为素数 向后维护数组,此素数的K倍均为非素数,直到大于n. ^时间复杂度O(nlogn) 便利+维护 埃式筛法 初式: 同线性筛法,依次遍历向后…