def img_only_color(self, filename, oldimg, img_contours): """ :param filename: 图像文件 :param oldimg: 原图像文件 :return: 已经定位好的车牌 """ pic_hight, pic_width = img_contours.shape[:2] lower_blue = np.array([100, 110, 110]) upper_blue = np.array([130, 255, 255]) lower_yellow = np.array([15, 55, 55]) upper_yellow = np.array([50, 255, 255]) lower_green = np.array([50, 50, 50]) upper_green = np.array([100, 255, 255]) hsv = cv2.cvtColor(filename, cv2.COLOR_BGR2HSV) mask_blue = cv2.inRange(hsv, lower_blue, upper_blue) mask_yellow = cv2.inRange(hsv, lower_yellow, upper_yellow) mask_green = cv2.inRange(hsv, lower_yellow, upper_green) output = cv2.bitwise_and(hsv, hsv, mask=mask_blue + mask_yellow + mask_green) # 根据阈值找到对应颜色 output = cv2.cvtColor(output, cv2.COLOR_BGR2GRAY) Matrix = np.ones((20, 20), np.uint8) img_edge1 = cv2.morphologyEx(output, cv2.MORPH_CLOSE, Matrix) img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, Matrix) card_contours = img_math.img_findContours(img_edge2) card_imgs = img_math.img_Transform(card_contours, oldimg, pic_width, pic_hight) colors, car_imgs = img_math.img_color(card_imgs) predict_result = [] roi = None card_color = None for i, color in enumerate(colors): if color in ("blue", "yello", "green"): card_img = card_imgs[i] gray_img = cv2.cvtColor(card_img, cv2.COLOR_BGR2GRAY) # 黄、绿车牌字符比背景暗、与蓝车牌刚好相反,所以黄、绿车牌需要反向 if color == "green" or color == "yello": gray_img = cv2.bitwise_not(gray_img) ret, gray_img = cv2.threshold( gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) x_histogram = np.sum(gray_img, axis=1) x_min = np.min(x_histogram) x_average = np.sum(x_histogram) / x_histogram.shape[0] x_threshold = (x_min + x_average) / 2 wave_peaks = img_math.find_waves(x_threshold, x_histogram) if len(wave_peaks) == 0: print("peak less 0:") continue # 认为水平方向,最大的波峰为车牌区域 wave = max(wave_peaks, key=lambda x: x[1] - x[0]) gray_img = gray_img[wave[0]:wave[1]] # 查找垂直直方图波峰 row_num, col_num = gray_img.shape[:2] # 去掉车牌上下边缘1个像素,避免白边影响阈值判断 gray_img = gray_img[1:row_num - 1] y_histogram = np.sum(gray_img, axis=0) y_min = np.min(y_histogram) y_average = np.sum(y_histogram) / y_histogram.shape[0] y_threshold = (y_min + y_average) / 5 # U和0要求阈值偏小,否则U和0会被分成两半 wave_peaks = img_math.find_waves(y_threshold, y_histogram) if len(wave_peaks) < 6: print("peak less 1:", len(wave_peaks)) continue wave = max(wave_peaks, key=lambda x: x[1] - x[0]) max_wave_dis = wave[1] - wave[0] # 判断是否是左侧车牌边缘 if wave_peaks[0][1] - wave_peaks[0][ 0] < max_wave_dis / 3 and wave_peaks[0][0] == 0: wave_peaks.pop(0) # 组合分离汉字 cur_dis = 0 for i, wave in enumerate(wave_peaks): if wave[1] - wave[0] + cur_dis > max_wave_dis * 0.6: break else: cur_dis += wave[1] - wave[0] if i > 0: wave = (wave_peaks[0][0], wave_peaks[i][1]) wave_peaks = wave_peaks[i + 1:] wave_peaks.insert(0, wave) point = wave_peaks[2] point_img = gray_img[:, point[0]:point[1]] if np.mean(point_img) < 255 / 5: wave_peaks.pop(2) if len(wave_peaks) <= 6: print("peak less 2:", len(wave_peaks)) continue part_cards = img_math.seperate_card(gray_img, wave_peaks) for i, part_card in enumerate(part_cards): # 可能是固定车牌的铆钉 if np.mean(part_card) < 255 / 5: print("a point") continue part_card_old = part_card w = abs(part_card.shape[1] - SZ) // 2 part_card = cv2.copyMakeBorder(part_card, 0, 0, w, w, cv2.BORDER_CONSTANT, value=[0, 0, 0]) part_card = cv2.resize(part_card, (SZ, SZ), interpolation=cv2.INTER_AREA) part_card = img_recognition.preprocess_hog([part_card]) if i == 0: resp = self.modelchinese.predict(part_card) charactor = img_recognition.provinces[int(resp[0]) - PROVINCE_START] else: resp = self.model.predict(part_card) charactor = chr(resp[0]) # 判断最后一个数是否是车牌边缘,假设车牌边缘被认为是1 if charactor == "1" and i == len(part_cards) - 1: if part_card_old.shape[0] / part_card_old.shape[ 1] >= 7: # 1太细,认为是边缘 continue predict_result.append(charactor) roi = card_img card_color = color break return predict_result, roi, card_color # 识别到的字符、定位的车牌图像、车牌颜色
def img_only_color(self, filename, oldimg, img_contours): """ :param filename: 图像文件 :param oldimg: 原图像文件 :return: 已经定位好的车牌 """ # cv_show("a",filename) pic_hight, pic_width = img_contours.shape[:2] lower_blue = np.array([100, 110, 110]) upper_blue = np.array([130, 255, 255]) lower_yellow = np.array([15, 55, 55]) upper_yellow = np.array([50, 255, 255]) lower_green = np.array([60, 60, 60]) upper_green = np.array([108, 255, 255]) # 定义颜色的上下线范围 hsv = cv2.cvtColor(filename, cv2.COLOR_BGR2HSV) mask_blue = cv2.inRange(hsv, lower_blue, upper_blue) mask_yellow = cv2.inRange(hsv, lower_yellow, upper_yellow) mask_green = cv2.inRange(hsv, lower_green, upper_green) # cv2.inRange 1原图 2 上下限 当大于或者小于的时候就取零 其他取 255 output = cv2.bitwise_and(hsv, hsv, mask=mask_blue + mask_yellow + mask_green) # 对二进制数据进行“与”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“与”操作,1 & 1 = 1,1 & 0 = 0,0 & 1 = 0,0 & 0 = 0 # 根据阈值找到对应颜色 # cv_show("1",output) output = cv2.cvtColor(output, cv2.COLOR_BGR2GRAY) Matrix = np.ones((10, 10), np.uint8) img_edge1 = cv2.morphologyEx(output, cv2.MORPH_CLOSE, Matrix) # cv_show("1",img_edge1) img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, Matrix) # cv_show("1", img_edge2) # 先闭后开操作 一开始太大导致图片混为一起 card_contours = img_math.img_findContours(img_edge2) # 外接轮廓 card_imgs = img_math.img_Transform(card_contours, oldimg, pic_width, pic_hight) # 进行校正仿射 colors, car_imgs = img_math.img_color(card_imgs) # 车牌颜色判别 predict_result = [] # 字符 roi = None # 颜色图片 card_color = None # 颜色 for i, color in enumerate(colors): if color in ("blue", "yello", "green"): card_img = card_imgs[i] # cv_show("ss", card_img) gray_img = cv2.cvtColor(card_img, cv2.COLOR_BGR2GRAY) # 黄、绿车牌字符比背景暗、与蓝车牌刚好相反,所以黄、绿车牌需要反向 if color == "green" or color == "yello": gray_img = cv2.bitwise_not(gray_img) # cv_show("ss",gray_img) # .bitwise_not白色变黑色 ret, gray_img = cv2.threshold( gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # 自动计算阈值 # 查找水平波峰 x_histogram = np.sum(gray_img, axis=1) x_min = np.min(x_histogram) x_average = np.sum(x_histogram) / x_histogram.shape[0] x_threshold = (x_min + x_average) / 2 wave_peaks = img_math.find_waves(x_threshold, x_histogram) if len(wave_peaks) == 0: print("peak less 0:") continue # 认为水平方向,最大的波峰为车牌区域 wave = max(wave_peaks, key=lambda x: x[1] - x[0]) gray_img = gray_img[wave[0]:wave[1]] # cv_show('f-9', gray_img) # 查找垂直直方图波峰 row_num, col_num = gray_img.shape[:2] # 去掉车牌上下边缘1个像素,避免白边影响阈值判断 gray_img = gray_img[1:row_num - 1] # cv_show('f-9', gray_img) # 按比例缩小 y_histogram = np.sum(gray_img, axis=0) # 把列归到一起 y_min = np.min(y_histogram) y_average = np.sum(y_histogram) / y_histogram.shape[0] y_threshold = (y_min + y_average) / 5 # U和0要求阈值偏小,否则U和0会被分成两半 wave_peaks = img_math.find_waves(y_threshold, y_histogram) # 字符数应该大于6 if len(wave_peaks) < 6: print("peak less 1:", len(wave_peaks)) continue # print("wave_peak1", wave_peaks) wave = max(wave_peaks, key=lambda x: x[1] - x[0]) max_wave_dis = wave[1] - wave[0] # 判断是否是左侧车牌边缘 if wave_peaks[0][1] - wave_peaks[0][ 0] < max_wave_dis / 3 or wave_peaks[0][0] == 0: wave_peaks.pop(0) # 组合分离汉字 cur_dis = 0 for i, wave in enumerate(wave_peaks): if wave[1] - wave[0] + cur_dis > max_wave_dis * 0.6: break else: cur_dis += wave[1] - wave[0] if i > 0: wave = (wave_peaks[0][0], wave_peaks[i][1]) wave_peaks = wave_peaks[i + 1:] wave_peaks.insert(0, wave) # print("wave_peak1", wave_peaks) point = wave_peaks[2] point_img = gray_img[:, point[0]:point[1]] if np.mean(point_img) < 255 / 5: wave_peaks.pop(2) # 删除中间的圆点 # print("wave_peak", wave_peaks) if len(wave_peaks) <= 6: print("peak less 2:", len(wave_peaks)) continue # 分离车牌字符 part_cards = img_math.seperate_card(gray_img, wave_peaks) for i, part_card in enumerate(part_cards): # 可能是固定车牌的铆钉 if np.mean(part_card) < 255 / 5: print("a point") continue part_card_old = part_card w = abs(part_card.shape[1] - SZ) // 2 part_card = cv2.copyMakeBorder(part_card, 0, 0, w, w, cv2.BORDER_CONSTANT, value=[0, 0, 0]) # 添加边框 参数:1 要处理的原图 2 上下左右要扩展的像素 6 边框类型 通过给定的属性添加颜色边框 part_card = cv2.resize(part_card, (SZ, SZ), interpolation=cv2.INTER_AREA) # 图片缩小 part_card = img_recognition.preprocess_hog([part_card]) # 训练用 if i == 0: resp = self.modelchinese.predict(part_card) charactor = img_recognition.provinces[int(resp[0]) - PROVINCE_START] else: resp = self.model.predict(part_card) charactor = chr(resp[0]) # 判断最后一个数是否是车牌边缘,假设车牌边缘被认为是1 if charactor == "1" and i == len(part_cards) - 1: if part_card_old.shape[0] / part_card_old.shape[ 1] >= 9: # 1太细,认为是边缘 continue predict_result.append(charactor) roi = card_img card_color = color break return predict_result, roi, card_color # 识别到的字符、定位的车牌图像、车牌颜色
def img_color_contours(self, img_contours, oldimg): """ :param img_contours: 预处理好的图像 :param oldimg: 原图像 :return: 已经定位好的车牌 """ if img_contours.any(): #config.set_name(img_contours) cv2.imwrite("tmp/img_contours.jpg", img_contours) pic_hight, pic_width = img_contours.shape[:2] card_contours = img_math.img_findContours(img_contours) card_imgs = img_math.img_Transform(card_contours, oldimg, pic_width, pic_hight) colors, car_imgs = img_math.img_color(card_imgs) predict_result = [] predict_str = "" roi = None card_color = None for i, color in enumerate(colors): if color in ("blue", "yello", "green"): card_img = card_imgs[i] gray_img = cv2.cvtColor(card_img, cv2.COLOR_BGR2GRAY) # 黄、绿车牌字符比背景暗、与蓝车牌刚好相反,所以黄、绿车牌需要反向 if color == "green" or color == "yello": gray_img = cv2.bitwise_not(gray_img) ret, gray_img = cv2.threshold( gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) x_histogram = np.sum(gray_img, axis=1) x_min = np.min(x_histogram) x_average = np.sum(x_histogram) / x_histogram.shape[0] x_threshold = (x_min + x_average) / 2 wave_peaks = img_math.find_waves(x_threshold, x_histogram) if len(wave_peaks) == 0: print("peak less 0:") continue # 认为水平方向,最大的波峰为车牌区域 wave = max(wave_peaks, key=lambda x: x[1] - x[0]) gray_img = gray_img[wave[0]:wave[1]] # 查找垂直直方图波峰 row_num, col_num = gray_img.shape[:2] # 去掉车牌上下边缘1个像素,避免白边影响阈值判断 gray_img = gray_img[1:row_num - 1] y_histogram = np.sum(gray_img, axis=0) y_min = np.min(y_histogram) y_average = np.sum(y_histogram) / y_histogram.shape[0] y_threshold = (y_min + y_average) / 5 # U和0要求阈值偏小,否则U和0会被分成两半 wave_peaks = img_math.find_waves(y_threshold, y_histogram) if len(wave_peaks) <= 6: print("peak less 1:", len(wave_peaks)) continue wave = max(wave_peaks, key=lambda x: x[1] - x[0]) max_wave_dis = wave[1] - wave[0] # 判断是否是左侧车牌边缘 if wave_peaks[0][1] - wave_peaks[0][ 0] < max_wave_dis / 3 and wave_peaks[0][0] == 0: wave_peaks.pop(0) # 组合分离汉字 cur_dis = 0 for i, wave in enumerate(wave_peaks): if wave[1] - wave[0] + cur_dis > max_wave_dis * 0.6: break else: cur_dis += wave[1] - wave[0] if i > 0: wave = (wave_peaks[0][0], wave_peaks[i][1]) wave_peaks = wave_peaks[i + 1:] wave_peaks.insert(0, wave) point = wave_peaks[2] point_img = gray_img[:, point[0]:point[1]] if np.mean(point_img) < 255 / 5: wave_peaks.pop(2) if len(wave_peaks) <= 6: print("peak less 2:", len(wave_peaks)) continue part_cards = img_math.seperate_card(gray_img, wave_peaks) for i, part_card in enumerate(part_cards): # 可能是固定车牌的铆钉 if np.mean(part_card) < 255 / 5: print("a point") continue part_card_old = part_card w = abs(part_card.shape[1] - SZ) // 2 part_card = cv2.copyMakeBorder(part_card, 0, 0, w, w, cv2.BORDER_CONSTANT, value=[0, 0, 0]) part_card = cv2.resize(part_card, (SZ, SZ), interpolation=cv2.INTER_AREA) part_card = img_recognition.preprocess_hog([part_card]) if i == 0: resp = self.modelchinese.predict(part_card) charactor = img_recognition.provinces[int(resp[0]) - PROVINCE_START] else: resp = self.model.predict(part_card) charactor = chr(resp[0]) # 判断最后一个数是否是车牌边缘,假设车牌边缘被认为是1 if charactor == "1" and i == len(part_cards) - 1: if part_card_old.shape[0] / part_card_old.shape[ 1] >= 7: # 1太细,认为是边缘 continue predict_result.append(charactor) predict_str = "".join(predict_result) roi = card_img card_color = color break return predict_str, roi, card_color # 识别到的字符、定位的车牌图像、车牌颜色
def img_color_contours(self, img_contours, oldimg): """ :param img_contours: 预处理好的图像 :param oldimg: 原图像 :return: 已经定位好的车牌 """ # cv_show("s",img_contours) if img_contours.any(): config.set_name(img_contours) pic_hight, pic_width = img_contours.shape[:2] card_contours = img_math.img_findContours(img_contours) # 进行校正 仿射 card_imgs = img_math.img_Transform(card_contours, oldimg, pic_width, pic_hight) colors, car_imgs = img_math.img_color(card_imgs) predict_result = [] card_color = None # 通过波峰找到文字区 for index, color in enumerate(colors): if color in ("blue", "yello", "green"): card_img = card_imgs[index] gray_img = cv2.cvtColor(card_img, cv2.COLOR_BGR2GRAY) if color == "green" or color == "yello": gray_img = cv2.bitwise_not(gray_img) ret, gray_img = cv2.threshold( gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) x_histogram = np.sum(gray_img, axis=1) # axis=1列压缩 x_min = np.min(x_histogram) x_average = np.sum(x_histogram) / x_histogram.shape[0] x_threshold = (x_min + x_average) / 2 wave_peaks = img_math.find_waves(x_threshold, x_histogram) if len(wave_peaks) == 0: print("peak less 0:") continue # 认为水平方向,最大的波峰为车牌区域 wave = max(wave_peaks, key=lambda x: x[1] - x[0]) gray_img = gray_img[wave[0]:wave[1]] # cv_show('截取图片', gray_img) row_num, col_num = gray_img.shape[:2] gray_img = gray_img[1:row_num - 1] y_histogram = np.sum(gray_img, axis=0) y_min = np.min(y_histogram) y_average = np.sum(y_histogram) / y_histogram.shape[0] y_threshold = (y_min + y_average) / 5 # U和0要求阈值偏小,否则U和0会被分成两半 wave_peaks = img_math.find_waves(y_threshold, y_histogram) if len(wave_peaks) <= 6: print("peak less 1:", len(wave_peaks)) continue wave = max(wave_peaks, key=lambda x: x[1] - x[0]) max_wave_dis = wave[1] - wave[0] # 判断是否是左侧车牌边缘 if wave_peaks[0][1] - wave_peaks[0][ 0] < max_wave_dis / 3 or wave_peaks[0][0] == 0: wave_peaks.pop(0) # 组合分离汉字 cur_dis = 0 #分割距离 for index, wave in enumerate(wave_peaks): if wave[1] - wave[0] + cur_dis > max_wave_dis * 0.6: break else: cur_dis += wave[1] - wave[0] if index > 0: wave = (wave_peaks[0][0], wave_peaks[index][1]) wave_peaks = wave_peaks[index + 1:] wave_peaks.insert(0, wave) point = wave_peaks[2] # 车牌前两位 和后面之间的点 point_img = gray_img[:, point[0]:point[1]] # 截取一部分 if np.mean(point_img) < 255 / 5: wave_peaks.pop(2) # 去除圆点 # print("wave_peak", wave_peaks) if len(wave_peaks) <= 6: print("peak less 2:", len(wave_peaks)) continue if len(wave_peaks) > 8: wave_peaks.pop(len(wave_peaks) - 1) # 分离车牌字符 part_cards = img_math.seperate_card(gray_img, wave_peaks) for i, part_card in enumerate(part_cards): # enumerate 遍历数据对象组成索引序列 # 可能是固定车牌的铆钉 if np.mean(part_card) < 255 / 5: print("a point") continue part_card_old = part_card w = abs(part_card.shape[1] - SZ) // 2 # 训练图片长宽 part_card = cv2.copyMakeBorder(part_card, 0, 0, w, w, cv2.BORDER_CONSTANT, value=[0, 0, 0]) # 添加边框 参数:1 要处理的原图 2 上下左右要扩展的像素 6 边框类型 通过给定的属性添加颜色边框 part_card = cv2.resize(part_card, (SZ, SZ), interpolation=cv2.INTER_AREA) # 图片缩小的方式 part_card = img_recognition.preprocess_hog([part_card]) if i == 0: # 模型预测,输入测试集,输出预测结果 resp = self.modelchinese.predict(part_card) print("chinese", resp) charactor = img_recognition.provinces[int(resp[0]) - PROVINCE_START] print("汉字", charactor) else: resp = self.model.predict(part_card) charactor = chr(resp[0]) print("字母数字", charactor) # chr 返回对应字符 # 判断最后一个数是否是车牌边缘,假设车牌边缘被认为是1 if charactor == "1" and i == len(part_cards) - 1: if part_card_old.shape[0] / part_card_old.shape[ 1] >= 9: # 1太细,有可能认为是边缘 continue predict_result.append(charactor) # 车牌信息 roi = card_img # 车牌图片 card_color = color # 颜色 break return predict_result, roi, card_color # 识别到的字符、定位的车牌图像、车牌颜色