def single_test_detect(): path = os.path.join(RESOURCE_PATH, 'test3') files = iu.get_imgs_from_path(path) image_array = [] text_array = [] for file_name in files: print("识别图片 %s" % file_name) file_path = os.path.join(path, file_name) if not os.path.isfile(file_path): continue img = iu.read_img(file_path, width=1000) try: contour_img, imgs, txts = td.detect(img, debug=True, save_folder=os.path.join( path, "middle_result")) except ServiceException as exp: print("识别出错 %s" % exp.message) image_array += imgs text_array += txts # 保存绿框结果 iu.write_middle_result(contour_img, file_name, "final_result") for img in image_array: cv2.cvtColor(img, cv2.COLOR_BGR2RGB) su.auto_subplt(image_array, 5, [plt.imshow], title=text_array)
def preprocess(gray, debug, save_folder): # 1. Sobel算子,x方向求梯度 sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 0, ksize=3) # 2. 二值化 # TODO 关于二值化阈值的选择,或者二值化阈值算法的选择THRESH_TRIANGLE/THRESH_OTSU留待之后进行试验。目前来看THRESH_OTSU算法更适合当前情况下的图片 ret, binary = cv2.threshold(sobel, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY) # binary = img_binary(gray) # 3. 膨胀和腐蚀操作的核函数 element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 9)) element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (24, 6)) # 4. 膨胀一次,让轮廓突出 dilation = cv2.dilate(binary, element2, iterations=1) # 5. 腐蚀一次,去掉细节,如表格线等。注意这里去掉的是竖直的线 erosion = cv2.erode(dilation, element1, iterations=1) # 6. 再次膨胀,让轮廓明显一些 dilation2 = cv2.dilate(erosion, element2, iterations=3) if debug: # 7. 存储中间图片 iu.write_middle_result(binary, "1_binary.png", save_folder) iu.write_middle_result(dilation, "2_dilation.png", save_folder) iu.write_middle_result(erosion, "3_erosion.png", save_folder) iu.write_middle_result(dilation2, "4_dilation2.png", save_folder) return dilation2
def detect(img, debug=False, save_folder="result"): # 1. 转化成灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 提取人脸区域 face_window = [x,y,w,h] face_window = fd.find_face(img) if face_window is None: raise ServiceException("未识别到人脸") # TODO 暂时松弛边界写为固定,之后可以先扣取身份证区域,根据身份证大小决定边界大小,或者将身份证区域处理成统一大小 shape = gray.shape gray = fd.remove_face(gray, face_window, relax_border=np.intp([shape[0] / 15, shape[1] / 12])) fd.draw_face_box(img, face_window) # 2. 形态学变换的预处理,得到可以查找矩形的图片 dilation = preprocess(gray, debug, save_folder) # 3. 查找和筛选文字区域 region = findTextRegion(dilation, debug, save_folder) # 识别文字 result_text = "" image_array = [] text_array = [] for box in region: # 识别框内文字 x_min, y_min = np.min(box, 0) x_max, y_max = np.max(box, 0) text_window = [x_min, y_min, x_max - x_min, y_max - y_min] if not region_filter(img, text_window, face_window): continue image_part, text = tr.ocr_result(img, text_window) result_text = text + "\n" + result_text image_array.append(image_part) text_array.append(text) print(result_text) print("-" * 10) # 4. 用绿线画出这些找到的轮廓 for box in region: cv2.drawContours(img, [box], 0, (0, 255, 0), 2) if debug: # 带轮廓的图片 iu.write_middle_result(img, "contours.png", save_folder) cv2.waitKey(0) return img, image_array, text_array
def group_test_detect(): path = os.path.join(RESOURCE_PATH, 'idcard_img') files = iu.get_imgs_from_path(path) image_array = [] text_array = [] for file_name in files: print("识别图片 %s" % file_name) file_path = os.path.join(path, file_name) if not os.path.isfile(file_path): continue img = iu.read_img(file_path, width=1000) try: contour_img, imgs, txts = td.detect(img) image_array += imgs text_array += txts # 保存绿框结果 iu.write_middle_result(contour_img, file_name, "final_result") except ServiceException as exp: print("识别出错 %s" % str(exp))
def get_card_area(img, debug=False, save_folder="result"): """ 剪裁出身份证文字区域 :param img: :param debug: :param save_folder: :return: """ gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 1, ksize=3) ret, binary = cv2.threshold(sobel, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY) # 3. 膨胀和腐蚀操作的核函数 element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 9)) element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (24, 6)) # 4. 膨胀一次,让轮廓突出 dilation = cv2.dilate(binary, element2, iterations=1) # 5. 腐蚀一次,去掉细节,如表格线等。注意这里去掉的是竖直的线 erosion = cv2.erode(dilation, element1, iterations=1) # 6. 再次膨胀,让轮廓明显一些 dilation2 = cv2.dilate(erosion, element2, iterations=3) # 查找和筛选文字区域 box = find_max_region(sobel) # 用绿线画出这些找到的轮廓 cv2.drawContours(img, [box], 0, (0, 255, 0), 2) if debug: # 存储中间图片 iu.write_middle_result(binary, "1_binary.png", save_folder) iu.write_middle_result(dilation, "2_dilation.png", save_folder) iu.write_middle_result(erosion, "3_erosion.png", save_folder) iu.write_middle_result(dilation2, "4_dilation2.png", save_folder) iu.write_middle_result(img, "contour.jpg", save_folder) cv2.waitKey()