Python 生成随机验证码(数字与大小写字母组合,验证码图像旋转并添加图像噪声,生成bmp图像)
代码如下:
from array import array
import random
import cv2
import PIL.ImageFont as ImageFont
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
# http://mirrors.aliyun.com/pypi/simple/
class bmp:
""" bmp data structure """
def __init__(self, w=1080, h=1920, color = 0xffffff):
self.w = w
self.h = h
self.gen_bmp_header()
self.paint_bgcolor(color)
def calc_data_size (self):
if((self.w*3)%4 == 0):
self.dataSize = self.w * 3 * self.h
else:
self.dataSize = (((self.w * 3) // 4 + 1) * 4) * self.h
self.fileSize = self.dataSize + 54
def conv2byte(self, l, num, len):
tmp = num
for i in range(len):
l.append(tmp & 0x000000ff)
tmp >>= 8
def gen_bmp_header (self):
self.calc_data_size();
self.bmp_header = [0x42, 0x4d]
self.conv2byte(self.bmp_header, self.fileSize, 4) #file size
self.conv2byte(self.bmp_header, 0, 2)
self.conv2byte(self.bmp_header, 0, 2)
self.conv2byte(self.bmp_header, 54, 4) #rgb data offset
self.conv2byte(self.bmp_header, 40, 4) #info block size
self.conv2byte(self.bmp_header, self.w, 4)
self.conv2byte(self.bmp_header, self.h, 4)
self.conv2byte(self.bmp_header, 1, 2)
self.conv2byte(self.bmp_header, 24, 2) #888
self.conv2byte(self.bmp_header, 0, 4) #no compression
self.conv2byte(self.bmp_header, self.dataSize, 4) #rgb data size
self.conv2byte(self.bmp_header, 0, 4)
self.conv2byte(self.bmp_header, 0, 4)
self.conv2byte(self.bmp_header, 0, 4)
self.conv2byte(self.bmp_header, 0, 4)
def print_bmp_header (self):
length = len(self.bmp_header)
for i in range(length):
print("{:0>2x}".format(self.bmp_header[i]), end=' ')
if i%16 == 15:
print('')
print('')
def paint_bgcolor(self, color=0xFFB6C1):
self.rgbData = []
for r in range(self.h):
self.rgbDataRow = []
for c in range(self.w):
self.rgbDataRow.append(color)
self.rgbData.append(self.rgbDataRow)
def paint_line(self, x1, y1, x2, y2, color):
k = (y2 - y1) / (x2 - x1)
for x in range(x1, x2+1):
y = int(k * (x - x1) + y1)
self.rgbData[y][x] = color
def paint_rect(self, x1, y1, w, h, color):
for x in range(x1, x1+w):
for y in range(y1, y1+h):
self.rgbData[y][x] = color
def paint_point(self, x, y, color=0x000000):
self.rgbData[y][x] = color
def save_image(self, name="save.bmp"):
f = open(name, 'wb')
#write bmp header
f.write(array('B', self.bmp_header).tobytes())
#write rgb data
zeroBytes = self.dataSize // self.h - self.w * 3
for r in range(self.h):
l = []
for i in range(len(self.rgbData[r])):
p = self.rgbData[r][i]
l.append(p & 0x0000ff)
p >>= 8
l.append(p & 0x0000ff)
p >>= 8
l.append(p & 0x0000ff)
f.write(array('B', l).tobytes())
for i in range(zeroBytes):
f.write(bytes([0x00]))
#close file
f.close()
def generate_text(text):
global mask
fnt = ImageFont.truetype('arial.ttf', 60)
img = Image.new("RGB",fnt.getsize(text),(255,182,193))
#img = Image.new("RGB",(32,32),(255,182,193))
mask = [x for x in fnt.getmask(text, mode='RGB')]
img.putdata(mask)
#img = img.convert('RGB')
return img
def rgb2hex(RGB):
text = '0x' + ''.join([hex(i)[-2:].replace('x', '0') for i in list(map(int, RGB))])
return text
if __name__ == '__main__':
w = int(45*6*2*0.677)
h = 45*2
image = bmp(w, h)
image.paint_bgcolor(color=0xFFB6C1)
for i in range(w):
ii = random.randint(0,h-1)
r = random.randint(0,255)
g = random.randint(0,255)
b = random.randint(0,255)
rgb = r*256*256+g*256+b
image.paint_point(i,ii,rgb)
image.save_image("save1.bmp")
import os
os.system("save1.bmp")
img_bg = cv2.imread("save1.bmp")
img3 = img_bg
img_change = Image.fromarray(cv2.cvtColor(img_bg, cv2.COLOR_BGR2RGB))
code = ''
code_end = ""
for i in range(6):
code = ''
n = random.randint(0, 9)
b = chr(random.randint(65, 90))
s = chr(random.randint(97, 122))
#code = str(random.choice([n, b, s]))
code_c = [n,b,s]
choice = random.randint(0,2)
code = code_c[choice]
code_end += str(code)
img_smaller = generate_text(str(code))
angle = random.randint(0,4)
angle2 = random.randint(0,90)
img_smaller = img_smaller.rotate(angle2)
if angle == 0:
img_smaller = img_smaller.transpose(Image.ROTATE_270)
elif angle == 1:
img_smaller = img_smaller.transpose(Image.ROTATE_180)
elif angle == 2:
img_smaller = img_smaller.transpose(Image.ROTATE_90)
else:
print(end="")
#img_smaller.resize((28,22))
#img2 = cv2.imread("1.jpg")
img_change.paste(img_smaller,(60*i,10))
print(code_end)
img_change.show()
效果如下: