tesseract安装。[安装教程] (https://blog.csdn.net/duanshao/article/details/79514051)
说明下,我完成了svm检测验证码的办法,效果不错,只有Z和S傻傻分不清楚。其他的没成功。但是都可以试试,svm的办法我也是参考别人的,自己没搞出来。具体见下文。最终代码等我了解下GITHUB再传- -。本文只做个人思路整合记录。
一堆处理方式来袭:
def readImg(im_fn):
im = cv.imread(im_fn)
if im is None:
print('{} cv2.imread failed'.format(im_fn))
tmp = imageio.mimread(im_fn)
if tmp is not None:
imt = np.array(tmp)
imt = imt[0]
im = imt[:, :, 0:3]
return im
path = r"D:\project\tenssact\data\CAPTCHA\1.gif"
src = readImg(path)
cv.namedWindow('input_image', cv.WINDOW_NORMAL) #设置为WINDOW_NORMAL可以任意缩放
cv.imshow('input_image', src)
code = pytesseract.image_to_string(src)
print(code)
#全局阈值
def threshold_demo(image):
gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY) #把输入图像灰度化
#直接阈值化是对输入的单通道矩阵逐像素进行阈值分割。
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE)
print("threshold value %s"%ret)
cv.namedWindow("binary0", cv.WINDOW_NORMAL)
cv.imshow("binary0", binary)
#局部阈值
def local_threshold(image):
gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY) #把输入图像灰度化
#自适应阈值化能够根据图像不同区域亮度分布,改变阈值
binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY, 25, 10)
cv.namedWindow("binary1", cv.WINDOW_NORMAL)
cv.imshow("binary1", binary)
#用户自己计算阈值
def custom_threshold(image):
gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY) #把输入图像灰度化
h, w =gray.shape[:2]
m = np.reshape(gray, [1,w*h])
mean = m.sum()/(w*h)
print("mean:",mean)
ret, binary = cv.threshold(gray, 190, 255, cv.THRESH_BINARY)
cv.namedWindow("binary2", cv.WINDOW_NORMAL)
cv.imshow("binary2", binary)
return binary
threshold_demo(src)
local_threshold(src)
img = custom_threshold(src)
cv.namedWindow("binary3", cv.WINDOW_NORMAL)
cv.imshow("binary3",img)
code = pytesseract.image_to_string(img)
print(code)
由于图片较小,kernel就选(2,2)大小,效果是不错的,但是还是不够用,再自定义个kernel。
kernel = np.ones((2,2),np.uint8)
kernel2 = np.ones((3,3),np.uint8)
kernel3 = array([[0,1,],[0,1]],np.uint8)
kernel4 = cv.getStructuringElement(cv.MORPH_RECT,(3, 3))
erosion = cv.erode(img,kernel,iterations = 1)
cv.namedWindow("binary4", cv.WINDOW_NORMAL)
cv.imshow("binary4",erosion)
dilation = cv.dilate(erosion,kernel,iterations = 1)
cv.namedWindow("binary5",cv.WINDOW_NORMAL)
cv.imshow("binary5",dilation)
cv.waitKey(0)
cv.destroyAllWindows()
code = pytesseract.image_to_string(dilation)
print(code)
gaos = cv.GaussianBlur(dilation, (3, 3), 0)
cv.imshow("binary6",gaos)
cv.waitKey(0)
cv.destroyAllWindows()
code = pytesseract.image_to_string(gaos)
print(code)
还是错误。还有好几种简单的方法,但是都只适用于简单的验证码检测,算了用神经网络玩玩。
[方法转自] (https://blog.csdn.net/tengxing007/article/details/78539213)
利用自己构建神经网络,并且用captcha生成大量验证码作为训练集,最后再进行测试。
20小时进行中。最后再看看效果,应该没问题。再看看captcha生成的验证码是怎么样的。
不玩了。最后一句话没有加绝对路径,白跑了 ,而且根本到不了百分之99,也就93左右是极限了,骗了我好几天。
[代码来自] (https://blog.csdn.net/sushiqian/article/details/78305340#)
再加26个大写字母
import sys
import os
import shutil
import random
import time
#captcha是用于生成验证码图片的库,可以 pip install captcha 来安装它
from captcha.image import ImageCaptcha
#用于生成验证码的字符集
CHAR_SET = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
#字符集的长度
CHAR_SET_LEN = 36
#验证码的长度,每个验证码由4个数字组成
CAPTCHA_LEN = 4
#验证码图片的存放路径
CAPTCHA_IMAGE_PATH = r'D:\project\tenssact\data\TEST_CAPTCHA\train'
#用于模型测试的验证码图片的存放路径,它里面的验证码图片作为测试集
TEST_IMAGE_PATH = r'D:\project\tenssact\data\TEST_CAPTCHA\test'
#用于模型测试的验证码图片的个数,从生成的验证码图片中取出来放入测试集中
TEST_IMAGE_NUMBER = 50
#生成验证码图片,4位的十进制数字可以有10000种验证码
def generate_captcha_image(charSet = CHAR_SET, charSetLen=CHAR_SET_LEN, captchaImgPath=CAPTCHA_IMAGE_PATH):
k = 0
total = 1
for i in range(CAPTCHA_LEN):
total *= charSetLen
for i in range(charSetLen):
for j in range(charSetLen):
for m in range(charSetLen):
for n in range(charSetLen):
captcha_text = charSet[i] + charSet[j] + charSet[m] + charSet[n]
image = ImageCaptcha()
image.write(captcha_text, captchaImgPath + captcha_text + '.jpg')
k += 1
sys.stdout.write("\rCreating %d/%d" % (k, total))
sys.stdout.flush()
#从验证码的图片集中取出一部分作为测试集,这些图片不参加训练,只用于模型的测试
def prepare_test_set():
fileNameList = []
for filePath in os.listdir(CAPTCHA_IMAGE_PATH):
captcha_name = filePath.split('/')[-1]
fileNameList.append(captcha_name)
random.seed(time.time())
random.shuffle(fileNameList)
for i in range(TEST_IMAGE_NUMBER):
name = fileNameList[i]
shutil.move(CAPTCHA_IMAGE_PATH + name, TEST_IMAGE_PATH + name)
if __name__ == '__main__':
generate_captcha_image(CHAR_SET, CHAR_SET_LEN, CAPTCHA_IMAGE_PATH)
prepare_test_set()
sys.stdout.write("\nFinished")
sys.stdout.flush()
36^4张图片各式各样~看看captcha到底按照什么机制产生的验证码。
1、固定位数
这种captcha是直接利用随机颜色、随机数字和随机字母进行组合,看起来非常简单,非常清晰。
2、固定位数+双线+模糊
在第一种captcha方法的基础上,增加了两条干扰斜线以及对整体captcha进行了模糊处理,难度增加。
3、固定位数+双线+扭曲+模糊
在第二种captcha的基础上,增加了对图片的扭曲(映射),难度进一步提升。
由于验证码图片大小基本很小,所以用暴力的滑动窗口检测并不需要多少时间,尤其是窗口大小很可能接近检测图片大小。首先爬取大量你自己想识别的验证码图片,找出数字123456789,或者加上字母,做分割。
由于我想解决的验证码是统一的位置,所以我就不需要滑动窗口检测这些操作了,固定位置斜体的不同字符。
首先批量的将GIF转换成PNG
import os
import cv2
import imageio
import numpy as np
import pytesseract
from PIL import Image
from numpy import *
import PIL.ImageOps
from scipy import misc, ndimage
import random
import math
def iter_frames(im):
try:
i= 0
while 1:
im.seek(i)
imframe = im.copy()
if i == 0:
palette = imframe.getpalette()
else:
imframe.putpalette(palette)
yield imframe
i += 1
except EOFError:
pass
def open_dir(dirpath, savepath):
i = 0
for root, dirs, filenames in os.walk(dirpath):
for file in filenames:
i += 1
img = Image.open(dirpath+"/"+ file)
for b, frame in enumerate(iter_frames(img)):
frame.save(savepath + f'{i}.png')
path = r"D:\project\tenssact\data\train_data"
save_path = r"D:\project\tenssact\data\train_data/"
open_dir(path,save_path)
import os
from PIL import Image
from numpy import *
def cutImg(img): #图像切割
s = 5
w = 11
h = 16
t = 3
cut_img = []
for i in range(4):
pic = img.crop((s + w * i+i, t, s + w * (i + 1)+i, h))
cut_img.append(pic)
return cut_img
def split_img(dirpath, savepath):
i = 0
for root, dirs, filenames in os.walk(dirpath):
for file in filenames:
img = Image.open(dirpath+"/"+file)
imgs = cutImg(img)
for im in imgs:
im.save(savepath+f'{i}.png')
i += 1
path = r"D:\project\tenssact\data\train_data"
savepath = r"D:\project\tenssact\data\split_train_data/"
split_img(path,savepath)
分割可以看一下 别人的 [博客](https://blog.csdn.net/HANNING563128766/article/details/79969339)
值得注意的是,切割完后的图片要放在对应的文件夹里,如数字3要放在命名为3的文件夹里。A的话文件夹最好设置为数字,暂时不知道设置A要怎么操作,所以把A设置为10,以此类推至Z。
[代码来自] (https://www.cnblogs.com/zyb993963526/p/8724621.html)
注意的是f.write写入的是个txt文件,用svm_read_problem(“train.txt”)返回,返回两个值,一个为标签,一个为特征。
from PIL import Image
import numpy as np
from svmutil import *
address =r'D:\project\tenssact\data\train\\'
f = open(r'D:\project\tenssact\data\train.txt', 'w')
def get_feature(dir, file):
f.write(dir)
im = Image.open(address + dir +'\\' + file)
imarr = np.array(im)
height, width = imarr.shape
for i in range(height):
for j in range(width):
gray = imarr[i,j]
if gray <= 240:
imarr[i, j] = 0
else:
imarr[i, j] = 255
im = Image.fromarray(imarr)
count = 0
width, height = im.size
for i in range(height):
c = 0
for j in range(width):
if im.getpixel((j, i)) == 255: c += 1
f.write(' %d:%d'%(count, c))
count += 1
for i in range(width):
c = 0
for j in range(height):
if im.getpixel((i, j)) == 255: c += 1
f.write(' %d:%d'%(count, c))
count += 1
f.write('\n')
def train_svm_model():
y, x = svm_read_problem('train.txt')
model = svm_train(y, x)
svm_save_model('model_file', model)
if __name__ == '__main__':
dirs = os.listdir(address)
for dir in dirs:
files = os.listdir(address + dir)
for file in files:
get_feature(dir, file)
train_svm_model()
第一次训练是以每行的白色像素个数作为特征进行训练,识别很差,所以要对原图进行一些操作,本文将它进行二值化。
import cv2 as cv
import os
import numpy as np
def custom_threshold(image):
path = r"D:\project\tenssact\data\test_1" + "/" + image
image = cv.imread(path)
gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY) #把输入图像灰度化
h, w =gray.shape[:2]
m = np.reshape(gray, [1,w*h])
mean = m.sum()/(w*h)
print("mean:",mean)
ret, binary = cv.threshold(gray, 240, 255, cv.THRESH_BINARY)
# cv.namedWindow("binary2", cv.WINDOW_NORMAL)
# cv.imshow("binary2", binary)
return binary
def png2thre(dirpath,savepath):
i = 0
for root,dirs,filenames in os.walk(dirpath):
for file in filenames:
i += 1
img = custom_threshold(file)
cv.imwrite(savepath+ f'{i}.png',img)
dirpath = r"D:\project\tenssact\data\test_1"
save_path = r"D:\project\tenssact\data\test_1/"
png2thre(dirpath,save_path)
可能path这块有点问题,自己仔细看代码,输入正确的path就行了。
接下来再传入svm进行训练,再对其进行检测。先挑取几张生成test.txt用上面的train中的get_future得到。
model = svm_load_model('model_file')
yt, xt = svm_read_problem('test.txt')
p_label, p_acc, p_val = svm_predict(yt, xt, model)
由于对libsvm了解太少,最终在尝试输入图片输出结果的地方迷失了。
[参考别人的博客](https://blog.csdn.net/u011337769/article/details/69808412)
别人的果然香一点,搞定。结合自己的特征。具体代码待我去了解下github更新。认真看看也能编出来。