# 8.1 图形验证码的识别

我们首先识别最简单的一种验证码，即图形验证码。这种验证码最早出现，现在也很常见，一般由 4 位字母或者数字组成。例如，中国知网的注册页面有类似的验证码，链接为：[http://my.cnki.net/elibregister/commonRegister.aspx](http://my.cnki.net/elibregister/commonRegister.aspx)，页面如图 8-1 所示：

![](./assets/8-1.png)

图 8-1 知网注册页面

表单的最后一项就是图形验证码，我们必须完全正确输入图中的字符才可以完成注册。

### 1. 本节目标

以知网的验证码为例，讲解利用 OCR 技术识别图形验证码的方法。

### 2. 准备工作

识别图形验证码需要库 tesserocr。安装此库可以参考第 1 章的安装说明。

### 3. 获取验证码

为了便于实验，我们先将验证码的图片保存到本地。

打开开发者工具，找到验证码元素。验证码元素是一张图片，它的 src 属性是 CheckCode.aspx。我们直接打开这个链接 [http://my.cnki.net/elibregister/CheckCode.aspx](http://my.cnki.net/elibregister/CheckCode.aspx)，就可以看到一个验证码，右键保存即可，将其命名为 code.jpg，如图 8-2 所示。

![](./assets/8-2.jpg)

图 8-2 验证码

这样我们就可以得到一张验证码图片，以供测试识别使用。

### 4. 识别测试

接下来新建一个项目，将验证码图片放到项目根目录下，用 tesserocr 库识别该验证码，代码如下所示：

```python
import tesserocr
from PIL import Image

image = Image.open('code.jpg')
result = tesserocr.image_to_text(image)
print(result)
```
在这里我们新建了一个 Image 对象，调用了 tesserocr 的 image_to_text() 方法。传入该 Image 对象即可完成识别，实现过程非常简单，结果如下所示：
```
JR42
```
另外，tesserocr 还有一个更加简单的方法，这个方法可直接将图片文件转为字符串，代码如下所示：
```python
import tesserocr
print(tesserocr.file_to_text('image.png'))
```

不过，此种方法的识别效果不如上一种方法好。

### 5. 验证码处理

接下来我们换一个验证码，将其命名为 code2.jpg，如图 8-3 所示。

![](./assets/8-3.jpg)

图 8-3 验证码

重新用下面的代码来测试：

```python
import tesserocr
from PIL import Image

image = Image.open('code2.jpg')
result = tesserocr.image_to_text(image)
print(result)
```
可以看到如下输出结果：
```
FFKT
```

这次识别和实际结果有偏差，这是因为验证码内的多余线条干扰了图片的识别。

对于这种情况，我们还需要做一下额外的处理，如转灰度、二值化等操作。

我们可以利用 Image 对象的 convert() 方法参数传入 L，即可将图片转化为灰度图像，代码如下所示：

```python
image = image.convert('L')
image.show()
```
传入 1 即可将图片进行二值化处理，如下所示：
```python
image = image.convert('1')
image.show()
```
我们还可以指定二值化的阈值。上面的方法采用的是默认阈值 127。不过我们不能直接转化原图，要将原图先转为灰度图像，然后再指定二值化阈值，代码如下所示：
```python
image = image.convert('L')
threshold = 80
table = []
for i in range(256):
    if i < threshold:
        table.append(0)
    else:
        table.append(1)

image = image.point(table, '1')
image.show()
```

在这里，变量 threshold 代表二值化阈值，阈值设置为 80。之后我们看看结果，如图 8-4 所示。

![](./assets/8-4.jpg)

图 8-4 处理结果

我们发现原来验证码中的线条已经去除，整个验证码变得黑白分明。这时重新识别验证码，代码如下所示：

```python
import tesserocr
from PIL import Image

image = Image.open('code2.jpg')

image = image.convert('L')
threshold = 127
table = []
for i in range(256):
    if i < threshold:
        table.append(0)
    else:
        table.append(1)

image = image.point(table, '1')
result = tesserocr.image_to_text(image)
print(result)
```
即可发现运行结果变成如下所示：
```python
PFRT
```

那么，针对一些有干扰的图片，我们做一些灰度和二值化处理，这会提高图片识别的正确率。

### 6. 本节代码

本节代码地址为：[https://github.com/Python3WebSpider/CrackImageCode](https://github.com/Python3WebSpider/CrackImageCode)。

### 7. 结语

本节我们了解了利用 tesserocr 识别验证码的过程。我们可以直接用简单的图形验证码得到结果，也可以对验证码图片做预处理来提高识别的准确度。