文章目录
一、image库基础使用
#coding:utf-8
#典型应用:
>>> from PIL import Image
>>> im = Image.open('/Users/Ezy/Documents/Test/image/test.jpg')
>>> print im.format, im.size, im.mode
JPEG (440, 330) RGB
#size元组表示宽和高,mode表示RGB(true color image),此外还有,L(luminance),CMTK(pre-press image)
>>> im = im.convert('L') #转为灰度模式
>>> im.show()
>>> pix = im.load()
>>> pix[0,1]
255
#新建一个空白的图片
>>> from PIL import Image
>>> im = Image.new('1', (100, 100), 'white')
#或者
>>> im = Image.new('1', (100, 100), 255) #255表示白色,1表示黑色
>>> im.show()
>>> im = Image.new('L', (100, 100), 128)
>>> im.show()
>>> im = Image.new('RGBA', (100, 100), (12,34,23,1))
>>> im.show() #将图片展现出来
"""
new方法可以创建图片对象,new参数说明:
第一个参数:指定模式:
L:灰度模式,每个像素的颜色使用 0-255 的整数表示。
1:表示单色模式
RGBA:三元色加透明度的表示方式,每个像素的颜色使用类似 (12,34,23,1) 的 tuple 表示。
第二个参数:指定图片大小
第三个参数:指定背景色
"""
#新建一个带文字的图片
from PIL import Image
from PIL import ImageDraw
>>> im = Image.new('1', (100, 100), 'white')
>>> draw = ImageDraw.Draw(im)
>>> draw.text((0, 0), 'hello world!')
#两个参数,第一个是字母开始的位置,第二个为输入的内容,可以新增第三个参数,font=FONT,来指定字体
>>> draw.text((wdraw, hdraw), msgNum, font=fron, fill=(255, 33, 33))
#定义图像格式
#(wdraw, hdraw):坐标
#msgNum: 随机数
# font: 自定义字体及大小
# fill:定义颜色,可以为数字格式也可以直接指定英文如:fill="red"
>>> im.show()
#图片处理
>>> im = Image.open('test.jpg')
>>> box = (100, 100, 200, 200)
>>> region = im.crop(box) #将图片扣出来一块内容
>>> region.show() #展示抠出来的图片
>>> region = region.transpose(Image.ROTATE_180) #将抠出来的图片旋转180度
>>> region.show() #展示旋转后的图片
>>> im.paste(region, box) #将旋转后的图片放回原来的区域中
>>> im.show() #展示图片
#crop() : 从图像中提取出某个矩形大小的图像。它接收一个四元素的元组作为参数,各元素为(left, upper, right, lower),坐标系统的原点(0, 0)是左上角。
#图片的其他操作:
>>> out = im.resize((128, 128)) #压缩原图片
>>> out = im.rotate(45) #逆时针旋转 45 度角。
>>> out = im.transpose(Image.FLIP_LEFT_RIGHT) #左右对换。
>>> out = im.transpose(Image.FLIP_TOP_BOTTOM) #上下对换。
>>> out = im.transpose(Image.ROTATE_90) #旋转 90 度角。
>>> out = im.transpose(Image.ROTATE_180) #旋转 180 度角。
>>> out = im.transpose(Image.ROTATE_270) #旋转 270 度角。
>>> out.show() #展示处理后的图片
#图像增强
>>> import ImageFilter
>>> imfilter = im.filter(ImageFilter.DETAIL)
>>> imfilter.show()
#取出某个图像中某个点的RGB值:
>>> im = Image.open('/Users/Ezy/Documents/Test/image/test.jpg')
>>> pix = im.load()
>>> print pix[1,2]
0
>>> print pix[1,3]
8
#更改某个图像中某个点的RGB值:
>>> from PIL import Image
>>> im = Image.open('/Users/Ezy/Documents/Test/image/test.jpg')
>>> im = im.convert('L')
>>> pix = im.load()
>>> pix[0,1]
23
>>> im.putpixel((0,1), 0)
>>> pix[0,1]
0
#注意,此时改变还只是对im对象的改变,要想生效就需要保存图片,如下所示
>>> im.save('/Users/Ezy/Documents/Test/image/test2.jpg')
补充:图片几种色彩模式
- 灰度(黑白)
- RGB(三色)
- CMYK(印刷色)
- Lab(肉眼识别色)
二、验证码识别
首先需要安装Tesseract-OCR软件,参考:
Windows安装Tesseract-OCR 4.00并配置环境变量,下载一下安装包,安装一下然后配置下一环境变量
然后需要安装python库
pip install pytesseract
pip install pillow
然后就开始验证码识别啦,先来一个简单的验证码识别,没有干扰
import pytesseract
from PIL import Image
image = Image.open("./1.png")
code = pytesseract.image_to_string(image)
print(code)
效果如下
但是像这种有干扰的就不行了,识别不出来
我们需要进行去噪,代码如下
#coding:utf-8
#auther:Ezy
#statement:使用image函数来自定义去除干扰线
"""
选择验证码颜色
1、颜色数目太少
2、范围太大,61>x2-x1>9, y2-y1 <11
3、若干扰线也在范围内,选择像素点数目多的
"""
from PIL import Image
from pytesseract import * #若要正常使用需要首先安装好tesseract-ocr,否则会报错
import requests
def scan(im, xx, yy):
pix = im.load()
dic = {} #{23:{'count':1, 'left':0, 'right':0, 'up':1, 'down':1}, ……}
for x in range(xx):
for y in range(yy):
if pix[x,y] in dic.keys():
dic[pix[x,y]]['count'] = dic[pix[x,y]]['count'] + 1
if x > dic[pix[x,y]]['right']:
dic[pix[x,y]]['right'] = x
if x < dic[pix[x,y]]['left']:
dic[pix[x,y]]['left'] = x
if y > dic[pix[x,y]]['up']:
dic[pix[x,y]]['up'] = y
if y < dic[pix[x,y]]['down']:
dic[pix[x,y]]['down'] = y
else:
dic[pix[x,y]] = {'count':1, 'left':x, 'right':x, 'up':y, 'down':y}
return dic
def geticode(dic):
l = []
for i in dic.keys():
if 9 < abs(dic[i]['right']-dic[i]['left']) < 61 and abs(dic[i]['up']-dic[i]['down']) < 11:
l.append(i)
tmp = 0 #验证码颜色
for i in l:
# print(str(i) + '\t' + str(dic[i]))
if dic[i]['count'] > tmp:
tmp = i
# print(str(tmp) + '\t' + str(dic[tmp]))
return tmp
def clean(im, xx, yy, icode):
pix = im.load()
for x in range(xx):
for y in range(yy):
if pix[x,y] != icode:
im.putpixel((x,y), 255)
return im
def main(file):
im = Image.open(file)
im = im.convert('L')
xx, yy = im.size
icode = geticode(scan(im, xx, yy))
im = clean(im, xx, yy, icode)
# im.show()
test = image_to_string(im)
print(test)
if __name__ == "__main__":
file = "./2.gif"
main(file)
效果如下
具体步骤:
先将图片转换为灰度模式
im = im.convert('L')
转换后就像下面这种
然后遍历每个像素,把颜色相同的放在一起,并计算出这个颜色的范围
for x in range(xx):
for y in range(yy):
if pix[x, y] in dic.keys():
dic[pix[x, y]]['count'] = dic[pix[x, y]]['count'] + 1
if x > dic[pix[x, y]]['right']:
dic[pix[x, y]]['right'] = x
if x < dic[pix[x, y]]['left']:
dic[pix[x, y]]['left'] = x
if y > dic[pix[x, y]]['up']:
dic[pix[x, y]]['up'] = y
if y < dic[pix[x, y]]['down']:
dic[pix[x, y]]['down'] = y
else:
dic[pix[x, y]] = {'count': 1, 'left': x, 'right': x, 'up': y, 'down': y}
运行出来就类似于这种
比如,第一个86,这个颜色的像素范围在x轴上为0到9,y轴范围为1到35,而我们图片的范围为x轴91个像素,y轴36个像素
目测一下验证码左右像素为20到85,上下像素为0到12,那么第一个肯定不满足
for i in dic.keys():
if 20 < abs(dic[i]['right'] - dic[i]['left']) < 85 and 1< abs(dic[i]['up'] - dic[i]['down']) < 12:
l.append(i)
print(dic[i])
我们把满足值的颜色提取出来,然后像素数量最多的多半就是验证码的颜色了
for i in l:
# print(str(i) + '\t' + str(dic[i]))
if dic[i]['count'] > tmp:
tmp = i
遍历所有像素,不是验证码颜色的直接改成白色
def clean(im, xx, yy, icode):
pix = im.load()
for x in range(xx):
for y in range(yy):
if pix[x, y] != icode:
im.putpixel((x, y), 255)
return im
最后去噪效果如下:
再用pytesseract.image_to_string
识别一下即可
test = image_to_string(im)
print(test)
成功识别!