|
|
# -*- coding: utf-8 -*-
|
|
|
import cv2
|
|
|
import numpy as np
|
|
|
|
|
|
MAX_WIDTH = 1000
|
|
|
Min_Area = 2000
|
|
|
SZ = 20
|
|
|
PROVINCE_START = 1000
|
|
|
"""
|
|
|
该文件包含读文件函数
|
|
|
取零值函数
|
|
|
矩阵校正函数
|
|
|
颜色判断函数
|
|
|
"""
|
|
|
|
|
|
|
|
|
def img_read(filename):
|
|
|
return cv2.imdecode(np.fromfile(filename, dtype=np.uint8), cv2.IMREAD_COLOR)
|
|
|
# 以uint8方式读取filename 放入imdecode中,cv2.IMREAD_COLOR读取彩色照片
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def point_limit(point):
|
|
|
if point[0] < 0:
|
|
|
point[0] = 0
|
|
|
if point[1] < 0:
|
|
|
point[1] = 0
|
|
|
|
|
|
|
|
|
def accurate_place(card_img_hsv, limit1, limit2, color):
|
|
|
row_num, col_num = card_img_hsv.shape[:2]
|
|
|
xl = col_num
|
|
|
xr = 0
|
|
|
yh = 0
|
|
|
yl = row_num
|
|
|
row_num_limit = 21
|
|
|
col_num_limit = col_num * 0.8 if color != "green" else col_num * 0.5 # 绿色有渐变
|
|
|
for i in range(row_num):
|
|
|
count = 0
|
|
|
for j in range(col_num):
|
|
|
H = card_img_hsv.item(i, j, 0)
|
|
|
S = card_img_hsv.item(i, j, 1)
|
|
|
V = card_img_hsv.item(i, j, 2)
|
|
|
if limit1 < H <= limit2 and 34 < S and 46 < V:
|
|
|
count += 1
|
|
|
if count > col_num_limit:
|
|
|
if yl > i:
|
|
|
yl = i
|
|
|
if yh < i:
|
|
|
yh = i
|
|
|
for j in range(col_num):
|
|
|
count = 0
|
|
|
for i in range(row_num):
|
|
|
H = card_img_hsv.item(i, j, 0)
|
|
|
S = card_img_hsv.item(i, j, 1)
|
|
|
V = card_img_hsv.item(i, j, 2)
|
|
|
if limit1 < H <= limit2 and 34 < S and 46 < V:
|
|
|
count += 1
|
|
|
if count > row_num - row_num_limit:
|
|
|
if xl > j:
|
|
|
xl = j
|
|
|
if xr < j:
|
|
|
xr = j
|
|
|
return xl, xr, yh, yl
|
|
|
|
|
|
|
|
|
def img_findContours(img_contours):
|
|
|
contours, hierarchy = cv2.findContours(img_contours, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
|
|
|
contours = [cnt for cnt in contours if cv2.contourArea(cnt) > Min_Area]
|
|
|
print("findContours len = ", len(contours))
|
|
|
# 排除面积最小的点
|
|
|
car_contours = []
|
|
|
for cnt in contours:
|
|
|
ant = cv2.minAreaRect(cnt)
|
|
|
width, height = ant[1]
|
|
|
if width < height:
|
|
|
width, height = height, width
|
|
|
ration = width / height
|
|
|
|
|
|
if 2 < ration < 5.5:
|
|
|
car_contours.append(ant)
|
|
|
box = cv2.boxPoints(ant)
|
|
|
|
|
|
return car_contours
|
|
|
|
|
|
#进行矩形矫正
|
|
|
def img_Transform(car_contours, oldimg, pic_width, pic_hight):
|
|
|
car_imgs = []
|
|
|
for car_rect in car_contours:
|
|
|
if -1 < car_rect[2] < 1:
|
|
|
angle = 1
|
|
|
# 对于角度为-1 1之间时,默认为1
|
|
|
else:
|
|
|
angle = car_rect[2]
|
|
|
car_rect = (car_rect[0], (car_rect[1][0] + 5, car_rect[1][1] + 5), angle)
|
|
|
box = cv2.boxPoints(car_rect)
|
|
|
|
|
|
heigth_point = right_point = [0, 0]
|
|
|
left_point = low_point = [pic_width, pic_hight]
|
|
|
for point in box:
|
|
|
if left_point[0] > point[0]:
|
|
|
left_point = point
|
|
|
if low_point[1] > point[1]:
|
|
|
low_point = point
|
|
|
if heigth_point[1] < point[1]:
|
|
|
heigth_point = point
|
|
|
if right_point[0] < point[0]:
|
|
|
right_point = point
|
|
|
|
|
|
if left_point[1] <= right_point[1]: # 正角度
|
|
|
new_right_point = [right_point[0], heigth_point[1]]
|
|
|
pts2 = np.float32([left_point, heigth_point, new_right_point]) # 字符只是高度需要改变
|
|
|
pts1 = np.float32([left_point, heigth_point, right_point])
|
|
|
M = cv2.getAffineTransform(pts1, pts2)
|
|
|
dst = cv2.warpAffine(oldimg, M, (pic_width, pic_hight))
|
|
|
point_limit(new_right_point)
|
|
|
point_limit(heigth_point)
|
|
|
point_limit(left_point)
|
|
|
car_img = dst[int(left_point[1]):int(heigth_point[1]), int(left_point[0]):int(new_right_point[0])]
|
|
|
car_imgs.append(car_img)
|
|
|
|
|
|
elif left_point[1] > right_point[1]: # 负角度
|
|
|
new_left_point = [left_point[0], heigth_point[1]]
|
|
|
pts2 = np.float32([new_left_point, heigth_point, right_point]) # 字符只是高度需要改变
|
|
|
pts1 = np.float32([left_point, heigth_point, right_point])
|
|
|
M = cv2.getAffineTransform(pts1, pts2)
|
|
|
dst = cv2.warpAffine(oldimg, M, (pic_width, pic_hight))
|
|
|
point_limit(right_point)
|
|
|
point_limit(heigth_point)
|
|
|
point_limit(new_left_point)
|
|
|
car_img = dst[int(right_point[1]):int(heigth_point[1]), int(new_left_point[0]):int(right_point[0])]
|
|
|
car_imgs.append(car_img)
|
|
|
|
|
|
return car_imgs
|
|
|
|
|
|
|
|
|
def img_color(card_imgs):
|
|
|
colors = []
|
|
|
for card_index, card_img in enumerate(card_imgs):
|
|
|
|
|
|
green = yello = blue = black = white = 0
|
|
|
card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)
|
|
|
# 有转换失败的可能,原因来自于上面矫正矩形出错
|
|
|
if card_img_hsv is None:
|
|
|
continue
|
|
|
row_num, col_num = card_img_hsv.shape[:2]
|
|
|
card_img_count = row_num * col_num
|
|
|
|
|
|
for i in range(row_num):
|
|
|
for j in range(col_num):
|
|
|
H = card_img_hsv.item(i, j, 0)
|
|
|
S = card_img_hsv.item(i, j, 1)
|
|
|
V = card_img_hsv.item(i, j, 2)
|
|
|
if 11 < H <= 34 and S > 34:
|
|
|
yello += 1
|
|
|
elif 35 < H <= 99 and S > 34:
|
|
|
green += 1
|
|
|
elif 99 < H <= 124 and S > 34:
|
|
|
blue += 1
|
|
|
|
|
|
if 0 < H < 180 and 0 < S < 255 and 0 < V < 46:
|
|
|
black += 1
|
|
|
elif 0 < H < 180 and 0 < S < 43 and 221 < V < 225:
|
|
|
white += 1
|
|
|
color = "no"
|
|
|
|
|
|
limit1 = limit2 = 0
|
|
|
if yello * 2 >= card_img_count:
|
|
|
color = "yello"
|
|
|
limit1 = 11
|
|
|
limit2 = 34 # 有的图片有色偏偏绿
|
|
|
elif green * 2 >= card_img_count:
|
|
|
color = "green"
|
|
|
limit1 = 35
|
|
|
limit2 = 99
|
|
|
elif blue * 2 >= card_img_count:
|
|
|
color = "blue"
|
|
|
limit1 = 100
|
|
|
limit2 = 124 # 有的图片有色偏偏紫
|
|
|
elif black + white >= card_img_count * 0.7:
|
|
|
color = "bw"
|
|
|
colors.append(color)
|
|
|
card_imgs[card_index] = card_img
|
|
|
|
|
|
if limit1 == 0:
|
|
|
continue
|
|
|
xl, xr, yh, yl = accurate_place(card_img_hsv, limit1, limit2, color)
|
|
|
if yl == yh and xl == xr:
|
|
|
continue
|
|
|
need_accurate = False
|
|
|
if yl >= yh:
|
|
|
yl = 0
|
|
|
yh = row_num
|
|
|
need_accurate = True
|
|
|
if xl >= xr:
|
|
|
xl = 0
|
|
|
xr = col_num
|
|
|
need_accurate = True
|
|
|
|
|
|
if color == "green":
|
|
|
card_imgs[card_index] = card_img
|
|
|
else:
|
|
|
card_imgs[card_index] = card_img[yl:yh, xl:xr] if color != "green" or yl < (yh - yl) // 4 else card_img[yl - (yh - yl) // 4:yh,xl:xr]
|
|
|
|
|
|
if need_accurate:
|
|
|
card_img = card_imgs[card_index]
|
|
|
card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)
|
|
|
xl, xr, yh, yl = accurate_place(card_img_hsv, limit1, limit2, color)
|
|
|
if yl == yh and xl == xr:
|
|
|
continue
|
|
|
if yl >= yh:
|
|
|
yl = 0
|
|
|
yh = row_num
|
|
|
if xl >= xr:
|
|
|
xl = 0
|
|
|
xr = col_num
|
|
|
if color == "green":
|
|
|
card_imgs[card_index] = card_img
|
|
|
else:
|
|
|
card_imgs[card_index] = card_img[yl:yh, xl:xr] if color != "green" or yl < (yh - yl) // 4 else card_img[yl - (yh - yl) // 4:yh,xl:xr]
|
|
|
|
|
|
return colors, card_imgs
|
|
|
|
|
|
|
|
|
# 根据设定的阈值和图片直方图,找出波峰,用于分隔字符
|
|
|
def find_waves(threshold, histogram):
|
|
|
up_point = -1 # 上升点
|
|
|
is_peak = False
|
|
|
if histogram[0] > threshold:
|
|
|
up_point = 0
|
|
|
is_peak = True
|
|
|
wave_peaks = []
|
|
|
for i, x in enumerate(histogram):
|
|
|
if is_peak and x < threshold:
|
|
|
if i - up_point > 2:
|
|
|
is_peak = False
|
|
|
wave_peaks.append((up_point, i))
|
|
|
elif not is_peak and x >= threshold:
|
|
|
is_peak = True
|
|
|
up_point = i
|
|
|
if is_peak and up_point != -1 and i - up_point > 4:
|
|
|
wave_peaks.append((up_point, i))
|
|
|
return wave_peaks
|
|
|
|
|
|
#分离车牌字符
|
|
|
def seperate_card(img, waves):
|
|
|
part_cards = []
|
|
|
for wave in waves:
|
|
|
part_cards.append(img[:, wave[0]:wave[1]])
|
|
|
|
|
|
return part_cards
|
|
|
|
|
|
|
|
|
def img_mser_color(card_imgs):
|
|
|
colors = []
|
|
|
for card_index, card_img in enumerate(card_imgs):
|
|
|
green = yello = blue = black = white = 0
|
|
|
card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)
|
|
|
if card_img_hsv is None:
|
|
|
continue
|
|
|
row_num, col_num = card_img_hsv.shape[:2]
|
|
|
card_img_count = row_num * col_num
|
|
|
for i in range(row_num):
|
|
|
for j in range(col_num):
|
|
|
H = card_img_hsv.item(i, j, 0)
|
|
|
S = card_img_hsv.item(i, j, 1)
|
|
|
V = card_img_hsv.item(i, j, 2)
|
|
|
if 11 < H <= 34 and S > 34:
|
|
|
yello += 1
|
|
|
elif 35 < H <= 99 and S > 34:
|
|
|
green += 1
|
|
|
elif 99 < H <= 124 and S > 34:
|
|
|
blue += 1
|
|
|
if 0 < H < 180 and 0 < S < 255 and 0 < V < 46:
|
|
|
black += 1
|
|
|
elif 0 < H < 180 and 0 < S < 43 and 221 < V < 225:
|
|
|
white += 1
|
|
|
color = "no"
|
|
|
if yello * 2 >= card_img_count:
|
|
|
color = "yello"
|
|
|
|
|
|
elif green * 2 >= card_img_count:
|
|
|
color = "green"
|
|
|
|
|
|
elif blue * 2 >= card_img_count:
|
|
|
color = "blue"
|
|
|
|
|
|
elif black + white >= card_img_count * 0.7:
|
|
|
color = "bw"
|
|
|
colors.append(color)
|
|
|
card_imgs[card_index] = card_img
|
|
|
return colors, card_imgs
|