在上一次分析中,提到了refineCrop函数,对裁剪下来含有车牌文字的图片区域进行了修剪,这次我们就分析一下具体是如何实现的。
这是refineCrop函数的全部代码:
def refineCrop(sections,width=16):
new_sections = []
for section in sections:
# cv2.imshow("section¡",section)
# cv2.blur(section,(3,3),3)
sec_center = np.array([section.shape[1]/2,section.shape[0]/2])
binary_niblack = nt.niBlackThreshold(section,17,-0.255)
imagex, contours, hierarchy = cv2.findContours(binary_niblack,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
boxs = []
for contour in contours:
x,y,w,h = cv2.boundingRect(contour)
ratio = w/float(h)
if ratio<1 and h>36*0.4 and y<16\
:
box = [x,y,w,h]
boxs.append([box,np.array([x+w/2,y+h/2])])
# cv2.rectangle(section,(x,y),(x+w,y+h),255,1)
# print boxs
dis_ = np.array([ ((one[1]-sec_center)**2).sum() for one in boxs])
if len(dis_)==0:
kernal = [0, 0, section.shape[1], section.shape[0]]
else:
kernal = boxs[dis_.argmin()][0]
center_c = (kernal[0]+kernal[2]/2,kernal[1]+kernal[3]/2)
w_2 = int(width/2)
h_2 = kernal[3]/2
if center_c[0] - w_2< 0:
w_2 = center_c[0]
new_box = [center_c[0] - w_2,kernal[1],width,kernal[3]]
# print new_box[2]/float(new_box[3])
if new_box[2]/float(new_box[3])>0.5:
# print "异常"
h = int((new_box[2]/0.35 )/2)
if h>35:
h = 35
new_box[1] = center_c[1]- h
if new_box[1]<0:
new_box[1] = 1
new_box[3] = h*2
section = section[int(new_box[1]):int(new_box[1]+new_box[3]), int(new_box[0]):int(new_box[0]+new_box[2])]
# cv2.imshow("section",section)
# cv2.waitKey(0)
new_sections.append(section)
# print new_box
return new_sections
传递的参数,就是之前剪裁出来的图片的部分。
sec_center = np.array([section.shape[1]/2,section.shape[0]/2])
binary_niblack = nt.niBlackThreshold(section,17,-0.255)
imagex, contours, hierarchy = cv2.findContours(binary_niblack,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
boxs = []
这里找出图片部分的中心,然后用niBlackThreshold进行了图像二值化,把前景(也就是文字)和背景分离开来,然后用findContours识别出边缘,边缘保存在contours中
for contour in contours:
x,y,w,h = cv2.boundingRect(contour)
ratio = w/float(h)
if ratio<1 and h>36*0.4 and y<16\
:
box = [x,y,w,h]
boxs.append([box,np.array([x+w/2,y+h/2])])
对于每个边缘,也就是文字的边缘,使用boundingRect函数,这个函数的作用就是画出能够包含目标图形的最小矩形,也就是能包含识别出的文字的最小矩形,这样就能裁剪出尽可能小的包含文字的区域,便于识别文字。将最小矩形的坐标信息和长宽信息存储在boxs列表里。
dis_ = np.array([ ((one[1]-sec_center)**2).sum() for one in boxs])
if len(dis_)==0:
kernal = [0, 0, section.shape[1], section.shape[0]]
else:
kernal = boxs[dis_.argmin()][0]
center_c = (kernal[0]+kernal[2]/2,kernal[1]+kernal[3]/2)
w_2 = int(width/2)
h_2 = kernal[3]/2
if center_c[0] - w_2< 0:
w_2 = center_c[0]
new_box = [center_c[0] - w_2,kernal[1],width,kernal[3]]
然后计算dis,这是识别出的最小矩形距离图形中心的距离,接下来算出kernel,kernel的值是距离中心最小的那个矩形,也就是最靠近中心的那个文字所在的最小矩形的长宽信息和位置信息。特别地,如果根本没有识别出任何边缘,也就没有任何最小矩形,kernel就被直接设定为图形中心点位置和图形的长宽。center_c是用kernel的信息计算出来的,最小矩形的中心坐标。
最后,根据以上计算得出的信息,最小矩形的位置坐标和长宽数值被保存在new_box中,这样接下来识别文字的时候,就可以根据new_box重新生成这个最小矩形。new_box也就是返回值。