使⽤OpenCV-python实现⼿写数字识别
⽂章⽬录
安装mahotas库智能提取阈值
默认的conda环境是没有mahotas的,需要⾃⼰⼿动安装mahotas,注意不要使⽤pip install这种⽅式,可能会导致电脑死机
conda config --add channels conda-forge
conda install mahotas
# 查看⼀下是否已经安装好
conda list
⼀、加载必要的库和⼀些基本函数
import cv2
# als import joblib
import joblib
import mahotas
import numpy as np
from sklearn.svm import LinearSVC
from skimage import feature
# 定义⼀个缩放函数
def resize(image, width =None, height =None, inter = cv2.INTER_AREA):
dim =None
(h, w)= image.shape[:2]
if width is None and height is None:
return image
# ⾼度模式
if width is None:
r = height /float(h)
dim =(int(w * r), height)
# 宽度模式
else:
r = width /float(w)
dim =(width,int(h * r))
resized = size(image, dim, interpolation = inter)
return resized
# 从excel加载数字,把特征和标注分开
def load_digits(datasetPath):
data = np.genfromtxt(datasetPath, delimiter =",", dtype ="uint8")
target = data[:,0]
data = data[:,1:].reshape(data.shape[0],28,28)
return(data,target)
# 进⾏旋转变换
def deskew(image, width):
(h, w)= image.shape[:2]
moments = s(image)
skew = moments["mu11"]/ moments["mu02"]
M = np.float32([
[1, skew,-0.5* w * skew],
[0,1,0]])
image = cv2.warpAffine(image, M,(w, h),
flags = cv2.WARP_INVERSE_MAP | cv2.INTER_LINEAR)
image = resize(image, width = width)
return image
# 把数字缩放到图⽚中⼼
def center_extent(image, size):
(eW, eH)= size
(eW, eH)= size
# 如果宽度》⾼度
if image.shape[1]> image.shape[0]:
image = resize(image, width = eW)
else:
image = resize(image, height = eH)
extent = np.zeros((eH, eW), dtype ="uint8")
offsetX =(eW - image.shape[1])//2
offsetY =(eH - image.shape[0])//2
extent[offsetY:offsetY + image.shape[0], offsetX:offsetX + image.shape[1]]= image # 计算图⽚的质量中⼼
(cY, cX)= np._of_mass(extent)).astype("int32")
(dX, dY)=((size[0]//2)- cX,(size[1]//2)- cY)
M = np.float32([[1,0, dX],[0,1, dY]])
# 把质量中⼼移动到图⽚的中⼼
rectangle函数opencvextent = cv2.warpAffine(extent, M, size)
# return the extent of the image
return extent
⼆、定义hog算⼦来描述图⽚的特征
class HOG:
def__init__(self, orientations =9, pixelsPerCell =(8,8),
cellsPerBlock =(3,3), transform =False):
self.pixelsPerCell = pixelsPerCell
def describe(self, image):
hist = feature.hog(image, orientations = ienations,
pixels_per_cell = self.pixelsPerCell,
cells_per_block = llsPerBlock,
transform_sqrt = ansform)
return hist
三、根据已有数字类别标注的数据集来训练模型
# ⾸先加载需要训练的数据
datasetPath ="data/digits.csv"
(digits, target)= load_digits(datasetPath)
data =[]
# 初始化hog因⼦
hog = HOG(orientations =18, pixelsPerCell =(10,10), cellsPerBlock =(1,1), transform =True)
# 数据预处理
for image in digits:
# 旋转和中⼼化
image = deskew(image,20)
image = center_extent(image,(20,20))
# 使⽤hog算⼦描述图像特征
hist = hog.describe(image)
data.append(hist)
# 开始训练
model = LinearSVC(random_state=42)
model.fit(data,target)
myModel ="mysvm.cpickle"
joblib.dump(model,myModel)
四、利⽤训练好的模型进⾏数字识别
# 加载训练好的模型
model = joblib.load(myModel)
hog = HOG(orientations =18, pixelsPerCell =(10,10),
cellsPerBlock =(1,1), transform =True)
# 加载被分类的图⽚
imagePath ="images/cellphone.png"
image = cv2.imread(imagePath)
# 图⽚预处理
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray,(5,5),0)
edged = cv2.Canny(blurred,30,150)
# 根据轮廓对数字进⾏切分
(cnts, _)= cv2.py(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts =sorted([(c, cv2.boundingRect(c)[0])for c in cnts], key =lambda x: x[1])
for(c, _)in cnts:
(x, y, w, h)= cv2.boundingRect(c)
# 对于⼀定⼤⼩的数字才进⾏识别
if w >=7and h >=20:
# 提取ROI区域
roi = gray[y:y + h, x:x + w]
thresh = py()
# 智能识别阈值
T = su(roi)
thresh[thresh > T]=255
# 过滤掉颜⾊更亮的背景
thresh = cv2.bitwise_not(thresh)
# 图⽚旋转校正,并把数字放到中⼼
thresh = deskew(thresh,20)
thresh = center_extent(thresh,(20,20))
# 测试预处理效果
cv2.imshow("thresh", thresh)
# 计算hog算⼦
hist = hog.describe(thresh)
# 根据模型来预测输出
digit = model.predict([hist])[0]
print("I think that number is: {}".format(digit))
# 把识别出的数字⽤绿⾊框显⽰出来
# 在识别出来的框左上⾓标注数字
cv2.putText(image,str(digit),(x -10, y -10),
cv2.FONT_HERSHEY_SIMPLEX,1.2,(0,255,0),2)
cv2.imshow("image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
下⾯是⼏个识别的⽰例
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论