python 图片真伪_图片验证码识别 Python版

本文介绍了使用Python解决图片验证码识别的方法,通过PythonImageLibrary(PIL)库进行图像处理,建立特征库,然后通过比较算法匹配验证码中的数字。首先提取足够多的验证码图片创建特征库,再按列扫描图片找到数字起始位置,与特征库对比找到最接近的匹配。最后,给出一个Captcha类用于识别验证码。
摘要由CSDN通过智能技术生成

这几天在用Python做数据采集的时候碰到了图片验证码的问题,于是在Redice的博客中找到了非常好用的方法,在此我转载过来并做简单说明。

首先,你的python必须装有Python Image Library(PIL)的库。如果你没有安装,那你需要下载安装一个,可能你从官网下载下来的是32位的,如果你的是64位操作系统,你可以在这里下载http://pan.baidu.com/s/1mgHQh2g

拿一个简单的例子讲,如下图。

这是一个较为简单的验证码图片,内容为纯数字0-9,单个字符宽度固定,字符垂直位置固定,背景有很少的杂色。

1. 提取特征库。

下载足够多的验证码图片(至少包含0-9所有数字)。截取每个数字(8×20像素矩阵)单独存储作为特征库。为什么是8*20的像素矩阵,因为上图的单个数字宽度是8像素,图片的高度是20像素,所以我这么截取。如果你的宽度和高度与我的不一样,你需要稍作修改。

实现截取的方法如下(用到了Python的PIL库):

import Image

def make_lib():

img = Image.open('code.jpg')

gray_img = img.convert('1')

gray_img.save('gray.jpg')

width, height = gray_img.size

# find each number

w = 0

while w < width:

column = []

for h in range(height):

column.append(gray_img.getpixel((w, h)))

# begining of a number

if sum(column)/height < 245:

box = (w, 0, w+8, 20)

region = gray_img.crop(box)

region.save('%s.jpg' % w)

w = w + 10

else:

w = w + 1

if __name__ == '__main__':

make_lib()

将验证么图片命名为code.jpg,放在同一目录下,执行程序后会看到验证码中的数字被截取。

注:img.convert(‘1’)作用是将彩色图二值化(只有0和255两种像素值)。

原理是:按列扫描,依次找到每个数字的起始位置,截取宽度为8像素,高度为20像素的区域保存。

如何识别字符的开始位置?

测试发现,列像素之合小于245的是有数字的部分。

最终建立如下特征库:

2. 匹配

按列扫描,依次找到每个数字的起始位置,获取宽度为8像素,高度为20像素的矩阵A。(8*20像素在上已经说明)

拿矩阵A一次跟特征库矩阵进行对比,以差值数(详见下面Captcha类中的_cmpmatrix方法)最小的特征字符为匹配字符。

# coding: utf-8

# captcha.py

import Image

class Captcha:

def __init__(self):

self.imglib = {}

self._loadlib()

def _loadlib(self):

"""Load characteristic image lib"""

import os

if not os.path.exists('imglib'):

print 'Can not find imglib dir.'

return

for i in range(10):

self.imglib[i] = []

img = Image.open('imglib/%d.jpg' % i).convert('1')

width, height = img.size

for w in range(width):

# store all pixels in a column

column = []

for h in range(height):

column.append(img.getpixel((w, h)))

self.imglib[i].append(column)

def _cmpmatrix(self, listA, listB):

"""Return the count of difference between two list"""

if len(listA) != len(listB): return

num = 0

for i, column in enumerate(listA):

if len(column) != len(listB[i]): return

for j, pixel in enumerate(column):

if pixel != listB[i][j]:

num += 1

return num

def _whichnum(self, piexls_matrix):

"""Identify single number"""

minnum = None

index = 0

for i in range(10):

ret = self._cmpmatrix(self.imglib.get(i, []), piexls_matrix)

if ret!= None:

if minnum == None or minnum > ret:

minnum = ret

index = i

if minnum != None:

return str(index)

else:

return '?'

def identify(self, filepath=None, fileobj=None):

"""Identify captcha"""

if filepath:

img = Image.open(filepath)

elif fileobj:

img = Image.open(fileobj)

else:

print 'Invalid input.'

return

img = img.convert('1')

width, height = img.size

w = 0

number = ''

while w < width:

column = []

for h in range(height):

column.append(img.getpixel((w, h)))

# begining of a number

if sum(column)/height < 245:

piexls_matrix = []

for i in range(8):

piexls_column = []

for j in range(20):

piexls_column.append(img.getpixel((w + i, j)))

piexls_matrix.append(piexls_column)

number += self._whichnum(piexls_matrix)

w = w + 10

else:

w = w + 1

return number

if __name__ == '__main__':

"""Test performance of Captcha Class"""

captcha = Captcha()

try:

import urllib2

response = urllib2.urlopen('这里填写图片验证码地址') # 如response = urllib2.urlopen('https://sn.ac.10086.cn/SSO/servlet/CreateImage')

open('code.jpg', 'wb').write(response.read())

Image.open('code.jpg').show()

print captcha.identify('code.jpg')

except Exception, e:

print 'Download captcha fail.', e

OK了,试一下吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值