OpenCV和Tesseract OCR识别复杂验证码喽~~
目录
代码实现思路
流程:
主要流程:
整体代码
效果展示
原图
处理之后的图
总结
流程图
代码实现思路
使用 OpenCV 进行图像预处理,并通过 Tesseract OCR 来识别验证码中的字符。以下是其实现思路的详细讲解:
流程:
-
加载验证码图像:
- 使用
cv2.imread()
读取验证码图片,将其加载为 BGR 格式图像。
- 使用
-
灰度处理:
- 使用
cv2.cvtColor()
将彩色图像转换为灰度图。灰度图可以减少颜色信息的干扰,更适合后续的二值化处理和降噪。
- 使用
-
高斯模糊:
cv2.GaussianBlur()
被用来对灰度图像进行模糊处理,以减少图像中的噪声。模糊有助于平滑噪点,让后续的二值化效果更稳定。
-
二值化:
cv2.threshold()
通过设定一个阈值将灰度图转换为二值图像,即只有黑白两色。THRESH_BINARY_INV
是反向二值化,将前景变为白色,背景变为黑色。这样做是为了更容易找到字符的轮廓。
-
形态学操作:
cv2.morphologyEx()
用来进一步清理图像,通过开运算(先腐蚀后膨胀)去除小的噪声点。这里定义了一个 2x2 的内核(kernel)来执行形态学操作,帮助消除图像中不规则的小黑点。
-
查找轮廓:
cv2.findContours()
查找二值化图像中的轮廓,即可能的字符区域。每个轮廓都表示一个可能的字符边界。
-
轮廓排序:
- 通过
cv2.boundingRect()
获取轮廓的外接矩形,并按照从左到右的顺序对这些矩形进行排序。这是为了保证字符按正确顺序被识别。
- 通过
-
轮廓过滤和分割字符:
- 遍历每个轮廓,使用
cv2.boundingRect()
得到每个轮廓的位置信息(x, y, w, h),过滤掉那些宽度过小或高度过小的轮廓(这些可能是噪声)。对于符合条件的轮廓区域,将其切割出来作为单个字符图像。
- 遍历每个轮廓,使用
-
OCR 识别:
- 使用 Tesseract 的
pytesseract.image_to_string()
来识别单个字符。--psm 10
是 Tesseract 的配置,表示将图像视为单个字符进行识别。每个字符识别后追加到recognized_text
中。
- 使用 Tesseract 的
-
结果输出:
- 打印出识别到的验证码字符。
- 显示图像:
- 使用
cv2.imshow()
显示处理后的二值化图像。cv2.waitKey(0)
等待键盘事件,cv2.destroyAllWindows()
关闭所有窗口。
主要流程:
- 图像预处理(灰度、模糊、二值化、形态学操作)来去除噪声。
- 查找轮廓并过滤,将字符区域提取出来。
- OCR 识别,逐个字符识别并拼接为最终的验证码。
整体代码
import cv2
import pytesseract
import numpy as np
# 如果你在Windows上使用Tesseract,取消注释并设置Tesseract路径
# pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
# 加载验证码图像
image = cv2.imread('./img/code.jpg')
# 转为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 应用高斯模糊来去噪声
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# 二值化,设定阈值
_, binary = cv2.threshold(blurred, 150, 255, cv2.THRESH_BINARY_INV)
# 形态学操作(去除噪声)
kernel = np.ones((2, 2), np.uint8)
cleaned = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)
# 在图像上查找轮廓,并尝试将字符分割开
contours, _ = cv2.findContours(cleaned, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 对轮廓进行排序(从左到右)
contours = sorted(contours, key=lambda ctr: cv2.boundingRect(ctr)[0])
# 逐个轮廓识别字符
recognized_text = ""
for contour in contours:
x, y, w, h = cv2.boundingRect(contour)
# 过滤太小或太大的区域,避免识别噪声
if w > 5 and h > 15:
char_img = cleaned[y:y + h, x:x + w]
# 调用Tesseract OCR识别单个字符
char_text = pytesseract.image_to_string(char_img, config='--psm 10')
recognized_text += char_text.strip()
# 打印识别结果
print(f"识别出的验证码是: {recognized_text}")
# 显示预处理后的图像
cv2.imshow('Processed Image', cleaned)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果展示
原图
处理之后的图
其实处理效果非常的明显,大家只需要在加一个能够排除这种黑色小点的功能几乎就可以完美的实现识别这样及其复杂的验证码结构
总结
流程图
为什么我没有给出完整的实现方式 ,因为我是真的没有找到一个完美的去处黑色点的方法,所以其实这里识别起来还是有很大的几率让程序识别失败的,所以遗憾还是有的,但是我们至少做了些什么。