python验证码识别代码合集

编程入门 行业动态 更新时间:2024-10-04 03:21:25

python<a href=https://www.elefans.com/category/jswz/34/1771040.html style=验证码识别代码合集"/>

python验证码识别代码合集

代码1: 

# -*-coding:utf-8-*-
import osdef test(path):img = Image.open(path)w, h = img.sizefor x in range(w):for y in range(h):r, g, b = img.getpixel((x, y))if 190 <= r <= 255 and 170 <= g <= 255 and 0 <= b <= 140:img.putpixel((x, y), (0, 0, 0))if 0 <= r <= 90 and 210 <= g <= 255 and 0 <= b <= 90:img.putpixel((x, y), (0, 0, 0))img = img.convert('L').point([0] * 150 + [1] * (256 - 150), '1')return img# -*-coding:utf-8-*-# coding:utf-8
from PIL import Image, ImageDraw# 二值数组
t2val = {}def twoValue(image, G):for y in range(0, image.size[1]):for x in range(0, image.size[0]):g = image.getpixel((x, y))if g > G:t2val[(x, y)] = 1else:t2val[(x, y)] = 0# 根据一个点A的RGB值,与周围的8个点的RBG值比较,设定一个值N(0 <N <8),当A的RGB值与周围8个点的RGB相等数小于N时,此点为噪点
# G: Integer 图像二值化阀值
# N: Integer 降噪率 0 <N <8
# Z: Integer 降噪次数
# 输出
#  0:降噪成功
#  1:降噪失败
def clearNoise(image, N, Z):for i in range(0, Z):t2val[(0, 0)] = 1t2val[(image.size[0] - 1, image.size[1] - 1)] = 1for x in range(1, image.size[0] - 1):for y in range(1, image.size[1] - 1):nearDots = 0L = t2val[(x, y)]if L == t2val[(x - 1, y - 1)]:nearDots += 1if L == t2val[(x - 1, y)]:nearDots += 1if L == t2val[(x - 1, y + 1)]:nearDots += 1if L == t2val[(x, y - 1)]:nearDots += 1if L == t2val[(x, y + 1)]:nearDots += 1if L == t2val[(x + 1, y - 1)]:nearDots += 1if L == t2val[(x + 1, y)]:nearDots += 1if L == t2val[(x + 1, y + 1)]:nearDots += 1if nearDots < N:t2val[(x, y)] = 1def saveImage(filename, size):image = Image.new("1", size)draw = ImageDraw.Draw(image)for x in range(0, size[0]):for y in range(0, size[1]):draw.point((x, y), t2val[(x, y)])image.save(filename)# -*-coding:utf-8-*-from PIL import Image
import pytesseractdef recognize_captcha(img_path):im = Image.open(img_path)# threshold = 140# table = []# for i in range(256):#     if i < threshold:#         table.append(0)#     else:#         table.append(1)## out = im.point(table, '1')num = pytesseract.image_to_string(im)return numif __name__ == '__main__':dir = '../download/'# dir = './image/'# dir = './'correct_count = 0  # 图片总数total_count = 0  # 识别正确的图片数量# 遍历figures下的png,jpg文件for file in os.listdir(dir):if file.endswith('.png') or file.endswith('.jpg'):img_path = '%s/%s' % (dir, file)  # 图片路径res = recognize_captcha(img_path)strs = res.split("\n")if len(strs) >= 1:print(file + ":" + strs[0])

代码2:

import os
import pytesseract
from PIL import Image
from collections import defaultdict# tesseract.exe所在的文件路径
pytesseract.pytesseract.tesseract_cmd = 'G://tesseract/tesseract.exe'# 获取图片中像素点数量最多的像素
def get_threshold(image):pixel_dict = defaultdict(int)# 像素及该像素出现次数的字典rows, cols = image.sizefor i in range(rows):for j in range(cols):pixel = image.getpixel((i, j))pixel_dict[pixel] += 1count_max = max(pixel_dict.values())  # 获取像素出现出多的次数pixel_dict_reverse = {v: k for k, v in pixel_dict.items()}threshold = pixel_dict_reverse[count_max]  # 获取出现次数最多的像素点return threshold# 按照阈值进行二值化处理
# threshold: 像素阈值
def get_bin_table(threshold):# 获取灰度转二值的映射tabletable = []for i in range(256):rate = 0.1  # 在threshold的适当范围内进行处理if threshold * (1 - rate) <= i <= threshold * (1 + rate):table.append(1)else:table.append(0)return table# 去掉二值化处理后的图片中的噪声点
def cut_noise(image):rows, cols = image.size  # 图片的宽度和高度change_pos = []  # 记录噪声点位置# 遍历图片中的每个点,除掉边缘for i in range(1, rows - 1):for j in range(1, cols - 1):# pixel_set用来记录该店附近的黑色像素的数量pixel_set = []# 取该点的邻域为以该点为中心的九宫格for m in range(i - 1, i + 2):for n in range(j - 1, j + 2):if image.getpixel((m, n)) != 1:  # 1为白色,0位黑色pixel_set.append(image.getpixel((m, n)))# 如果该位置的九宫内的黑色数量小于等于4,则判断为噪声if len(pixel_set) <= 4:change_pos.append((i, j))# 对相应位置进行像素修改,将噪声处的像素置为1(白色)for pos in change_pos:image.putpixel(pos, 1)return image  # 返回修改后的图片# 识别图片中的数字加字母
# 传入参数为图片路径,返回结果为:识别结果
def OCR_lmj(img_path):image = Image.open(img_path)  # 打开图片文件imgry = image.convert('L')  # 转化为灰度图# 获取图片中的出现次数最多的像素,即为该图片的背景max_pixel = get_threshold(imgry)# 将图片进行二值化处理table = get_bin_table(threshold=max_pixel)out = imgry.point(table, '1')# 去掉图片中的噪声(孤立点)out = cut_noise(out)# 保存图片# out.save('E://figures/img_gray.jpg')# 仅识别图片中的数字# text = pytesseract.image_to_string(out, config='digits')# 识别图片中的数字和字母text = pytesseract.image_to_string(out)# 去掉识别结果中的特殊字符exclude_char_list = ' .:\\|\'\"?![],()~@#$%^&*_+-={};<>/¥'text = ''.join([x for x in text if x not in exclude_char_list])# print(text)return textdef main():# 识别指定文件目录下的图片# 图片存放目录figuresdir = '../download/'# dir = './image/'# dir = './'correct_count = 0  # 图片总数total_count = 0  # 识别正确的图片数量# 遍历figures下的png,jpg文件for file in os.listdir(dir):if file.endswith('.png') or file.endswith('.jpg'):# print(file)image_path = '%s/%s' % (dir, file)  # 图片路径answer = file.split('.')[0]  # 图片名称,即图片中的正确文字recognizition = OCR_lmj(image_path)  # 图片识别的文字结果print((answer, recognizition))if recognizition == answer:  # 如果识别结果正确,则total_count加1correct_count += 1total_count += 1print('Total count: %d, correct: %d.' % (total_count, correct_count))'''# 单张图片识别image_path = 'E://figures/code (1).jpg'OCR_lmj(image_path)'''main()

 代码3:

from PIL import ImageDraw, Image
from pytesseract import pytesseractdef getPixel(image, x, y):L = image.getpixel((x, y))  # 获取当前像素点的像素if L == 0:  # 判读此像素点是否为黑,因为如果是白的就没必要处理了nearDots = 0  # 初始化记录周围有没有黑像素数量的值# 判断周围像素点if L - image.getpixel((x - 1, y - 1)):nearDots += 1if L - image.getpixel((x - 1, y)):nearDots += 1if L - image.getpixel((x - 1, y + 1)):nearDots += 1if L - image.getpixel((x, y - 1)):nearDots += 1if L - image.getpixel((x, y + 1)):nearDots += 1if L - image.getpixel((x + 1, y - 1)):nearDots += 1if L - image.getpixel((x + 1, y)):nearDots += 1if L - image.getpixel((x + 1, y + 1)):nearDots += 1if nearDots == 8:  # 这里如果周围八个全是白点那么就返回一个白点,实现去黑点的操作return 1# 这里主要是有俩个黑点连在一起,所有周围会有七个黑点扩大范围进一步判断elif nearDots == 7:nearDots = 0if L - image.getpixel((x - 2, y - 2)):nearDots += 1if L - image.getpixel((x - 2, y)):nearDots += 1if L - image.getpixel((x - 2, y + 2)):nearDots += 1if L - image.getpixel((x, y - 2)):nearDots += 1if L - image.getpixel((x, y + 2)):nearDots += 1if L - image.getpixel((x + 2, y - 2)):nearDots += 1if L - image.getpixel((x + 2, y)):nearDots += 1if L - image.getpixel((x + 2, y + 2)):nearDots += 1if nearDots == 8:return 1  # 返回白点else:return 0  # 返回黑点else:return 1def clearNoise(image):draw = ImageDraw.Draw(image)# 循环遍历每个像素点for x in range(0, image.size[0]):for y in range(0, image.size[1]):color = getPixel(image, x, y)draw.point((x, y), color)return imageim = Image.open('../download/32.jpg')  # 用pil打开这个图片im = im.convert('L')
# im = im.point(lambda x: 0 if x<50 else 255)
im = im.point(lambda x: 0 if x < 142 else x >= 142, '1')
# im = im.point(lambda x: 0 if x < 143 else 255)
im.show()
# 将上一步处理完成的im对象传给clearNoise()函数
im = clearNoise(im)
im.show()# lang只用哪个库来识别 默认有个eng库,config 指代识别单行还是多行-psm 7只的是单行
result = pytesseract.image_to_string(im, lang='eng', config="--psm 10")
print(result)

代码4:

import os
from fnmatch import fnmatch
from queue import Queueimport cv2
from PIL import Image
from pytesseract import *import subprocessdef clear_border(img, img_name):'''去除边框'''filename = './out_img/' + img_name.split('.')[0] + '-clearBorder.jpg'h, w = img.shape[:2]for y in range(0, w):for x in range(0, h):# if y ==0 or y == w -1 or y == w - 2:if y < 4 or y > w - 4:img[x, y] = 255# if x == 0 or x == h - 1 or x == h - 2:if x < 4 or x > h - 4:img[x, y] = 255cv2.imwrite(filename, img)return imgdef interference_line(img, img_name):'''干扰线降噪'''filename = './out_img/' + img_name.split('.')[0] + '-interferenceline.jpg'h, w = img.shape[:2]# !!!opencv矩阵点是反的# img[1,2] 1:图片的高度,2:图片的宽度for y in range(1, w - 2):for x in range(1, h - 2):count = 0if img[x, y - 1] > 245 or img[x, y - 2] > 245:count = count + 1if img[x, y + 1] > 245 or img[x, y + 2] > 245:count = count + 1if img[x - 1, y] > 245 or img[x - 2, y] > 245:count = count + 1if img[x + 1, y] > 245 or img[x + 1, y] > 245:count = count + 1if count > 2:img[x, y] = 255cv2.imwrite(filename, img)return imgdef interference_point(img, img_name, x=0, y=0):"""点降噪9邻域框,以当前点为中心的田字框,黑点个数:param x::param y::return:"""filename = './out_img/' + img_name.split('.')[0] + '-interferencePoint.jpg'# todo 判断图片的长宽度下限cur_pixel = img[x, y]  # 当前像素点的值height, width = img.shape[:2]for y in range(0, width - 1):for x in range(0, height - 1):if y == 0:  # 第一行if x == 0:  # 左上顶点,4邻域# 中心点旁边3个点sum = int(cur_pixel) \+ int(img[x, y + 1]) \+ int(img[x + 1, y]) \+ int(img[x + 1, y + 1])if sum <= 2 * 245:img[x, y] = 0elif x == height - 1:  # 右上顶点sum = int(cur_pixel) \+ int(img[x, y + 1]) \+ int(img[x - 1, y]) \+ int(img[x - 1, y + 1])if sum <= 2 * 245:img[x, y] = 0else:  # 最上非顶点,6邻域sum = int(img[x - 1, y]) \+ int(img[x - 1, y + 1]) \+ int(cur_pixel) \+ int(img[x, y + 1]) \+ int(img[x + 1, y]) \+ int(img[x + 1, y + 1])if sum <= 3 * 245:img[x, y] = 0elif y == width - 1:  # 最下面一行if x == 0:  # 左下顶点# 中心点旁边3个点sum = int(cur_pixel) \+ int(img[x + 1, y]) \+ int(img[x + 1, y - 1]) \+ int(img[x, y - 1])if sum <= 2 * 245:img[x, y] = 0elif x == height - 1:  # 右下顶点sum = int(cur_pixel) \+ int(img[x, y - 1]) \+ int(img[x - 1, y]) \+ int(img[x - 1, y - 1])if sum <= 2 * 245:img[x, y] = 0else:  # 最下非顶点,6邻域sum = int(cur_pixel) \+ int(img[x - 1, y]) \+ int(img[x + 1, y]) \+ int(img[x, y - 1]) \+ int(img[x - 1, y - 1]) \+ int(img[x + 1, y - 1])if sum <= 3 * 245:img[x, y] = 0else:  # y不在边界if x == 0:  # 左边非顶点sum = int(img[x, y - 1]) \+ int(cur_pixel) \+ int(img[x, y + 1]) \+ int(img[x + 1, y - 1]) \+ int(img[x + 1, y]) \+ int(img[x + 1, y + 1])if sum <= 3 * 245:img[x, y] = 0elif x == height - 1:  # 右边非顶点sum = int(img[x, y - 1]) \+ int(cur_pixel) \+ int(img[x, y + 1]) \+ int(img[x - 1, y - 1]) \+ int(img[x - 1, y]) \+ int(img[x - 1, y + 1])if sum <= 3 * 245:img[x, y] = 0else:  # 具备9领域条件的sum = int(img[x - 1, y - 1]) \+ int(img[x - 1, y]) \+ int(img[x - 1, y + 1]) \+ int(img[x, y - 1]) \+ int(cur_pixel) \+ int(img[x, y + 1]) \+ int(img[x + 1, y - 1]) \+ int(img[x + 1, y]) \+ int(img[x + 1, y + 1])if sum <= 4 * 245:img[x, y] = 0cv2.imwrite(filename, img)return imgdef _get_dynamic_binary_image(filedir, img_name):'''自适应阀值二值化'''filename = './out_img/' + img_name.split('.')[0] + '-binary.jpg'img_name = filedir + '/' + img_nameprint('.....' + img_name)im = cv2.imread(img_name)im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)th1 = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 1)cv2.imwrite(filename, th1)return th1def _get_static_binary_image(img, threshold=140):'''手动二值化'''img = Image.open(img)img = img.convert('L')pixdata = img.load()w, h = img.sizefor y in range(h):for x in range(w):if pixdata[x, y] < threshold:pixdata[x, y] = 0else:pixdata[x, y] = 255return imgdef cfs(im, x_fd, y_fd):'''用队列和集合记录遍历过的像素坐标代替单纯递归以解决cfs访问过深问题'''# print('**********')xaxis = []yaxis = []visited = set()q = Queue()q.put((x_fd, y_fd))visited.add((x_fd, y_fd))offsets = [(1, 0), (0, 1), (-1, 0), (0, -1)]  # 四邻域while not q.empty():x, y = q.get()for xoffset, yoffset in offsets:x_neighbor, y_neighbor = x + xoffset, y + yoffsetif (x_neighbor, y_neighbor) in (visited):continue  # 已经访问过了visited.add((x_neighbor, y_neighbor))try:if im[x_neighbor, y_neighbor] == 0:xaxis.append(x_neighbor)yaxis.append(y_neighbor)q.put((x_neighbor, y_neighbor))except IndexError:pass# print(xaxis)if (len(xaxis) == 0 | len(yaxis) == 0):xmax = x_fd + 1xmin = x_fdymax = y_fd + 1ymin = y_fdelse:xmax = max(xaxis)xmin = min(xaxis)ymax = max(yaxis)ymin = min(yaxis)# ymin,ymax=sort(yaxis)return ymax, ymin, xmax, xmindef detectFgPix(im, xmax):'''搜索区块起点'''h, w = im.shape[:2]for y_fd in range(xmax + 1, w):for x_fd in range(h):if im[x_fd, y_fd] == 0:return x_fd, y_fddef CFS(im):'''切割字符位置'''zoneL = []  # 各区块长度L列表zoneWB = []  # 各区块的X轴[起始,终点]列表zoneHB = []  # 各区块的Y轴[起始,终点]列表xmax = 0  # 上一区块结束黑点横坐标,这里是初始化for i in range(10):try:x_fd, y_fd = detectFgPix(im, xmax)# print(y_fd,x_fd)xmax, xmin, ymax, ymin = cfs(im, x_fd, y_fd)L = xmax - xminH = ymax - yminzoneL.append(L)zoneWB.append([xmin, xmax])zoneHB.append([ymin, ymax])except TypeError:return zoneL, zoneWB, zoneHBreturn zoneL, zoneWB, zoneHBdef cutting_img(im, im_position, img, xoffset=1, yoffset=1):filename = './out_img/' + img.split('.')[0]# 识别出的字符个数im_number = len(im_position[1])# 切割字符for i in range(im_number):im_start_X = im_position[1][i][0] - xoffsetim_end_X = im_position[1][i][1] + xoffsetim_start_Y = im_position[2][i][0] - yoffsetim_end_Y = im_position[2][i][1] + yoffsetcropped = im[im_start_Y:im_end_Y, im_start_X:im_end_X]cv2.imwrite(filename + '-cutting-' + str(i) + '.jpg', cropped)def main():filedir = '../download/'for file in os.listdir(filedir):if fnmatch(file, '*.jpg'):img_name = file# 自适应阈值二值化im = _get_dynamic_binary_image(filedir, img_name)# 去除边框im = clear_border(im, img_name)# 对图片进行干扰线降噪im = interference_line(im, img_name)im = interference_line(im, img_name)im = interference_line(im, img_name)# 对图片进行点降噪im = interference_point(im, img_name)# 切割的位置im_position = CFS(im)maxL = max(im_position[0])minL = min(im_position[0])# 如果有粘连字符,如果一个字符的长度过长就认为是粘连字符,并从中间进行切割if (maxL > minL + minL * 0.7):maxL_index = im_position[0].index(maxL)minL_index = im_position[0].index(minL)# 设置字符的宽度im_position[0][maxL_index] = maxL // 2im_position[0].insert(maxL_index + 1, maxL // 2)# 设置字符X轴[起始,终点]位置im_position[1][maxL_index][1] = im_position[1][maxL_index][0] + maxL // 2im_position[1].insert(maxL_index + 1, [im_position[1][maxL_index][1] + 1,im_position[1][maxL_index][1] + 1 + maxL // 2])# 设置字符的Y轴[起始,终点]位置im_position[2].insert(maxL_index + 1, im_position[2][maxL_index])# 切割字符,要想切得好就得配置参数,通常 1 or 2 就可以cutting_img(im, im_position, img_name, 1, 1)# 识别验证码cutting_img_num = 0for file in os.listdir('./out_img'):str_img = ''if fnmatch(file, '%s-cutting-*.jpg' % img_name.split('.')[0]):cutting_img_num += 1for i in range(cutting_img_num):try:file = './out_img/%s-cutting-%s.jpg' % (img_name.split('.')[0], i)# 识别验证码str_img = str_img + image_to_string(Image.open(file), lang='eng',config='--psm 10')  # 单个字符是10,一行文本是7except Exception as err:passprint('切图:%s' % cutting_img_num)print('识别为:%s' % str_img)if __name__ == '__main__':main()

这些验证码都有一个相同思路:

 

  • 灰度处理
  • 二值化
  • 降噪(其中最核心的就是降噪算法,通过对 周围点的判断来处理是否消除这个点,但是如果这个噪声点比较大会导致误判)
  • 切割字符或者倾斜度矫正(可以有)
  • 训练字体库(可以有)
  • 识别

参考:

.html

 

 

更多推荐

python验证码识别代码合集

本文发布于:2024-02-28 13:37:23,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1769982.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:验证码   合集   代码   python

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!