def ocr(self, job_id): all_config = recognize.getConfig() job_data = tools.loadJobData(job_id) logging.debug('Load job data: %s' % str(job_data)) cur_config = all_config[job_data['type']] logging.debug('Load recognize config: %s' % str(cur_config)) img = cv2.imread(job_data['file'], cv2.IMREAD_UNCHANGED) res_orc = [] for roi_name in cur_config['roi']: roi_config = cur_config['roi'][roi_name] if roi_config.get('hide', False): logging.info('Ignore roi [%s] because it is hidden' % roi_name) continue roi_orc_data = { 'name': roi_name, 'value': None, } if roi_config.get('ocr', True): roi_value_type = roi_config.get('type', 'text') if roi_value_type not in tools.OCR_TYPE_MAPPING: logging.error('ROI Type %s not exist, skipped' % roi_value_type) continue roi_img, roi_path = tools.createRoi2(img, roi_name, roi_config, job_id + '/step3') roi_orc_data['value'] = tools.callOcr(roi_img, job_id + '/step3', roi_config) logging.info('OCR for roi [%s, type=%s] = %s' % (roi_name, roi_value_type, roi_orc_data['value'])) res_orc.append(roi_orc_data) return res_orc
def extractImage(self, job_id): all_config = recognize.getConfig() job_data = tools.loadJobData(job_id) logging.debug('Load job data: %s' % str(job_data)) cur_config = all_config[job_data['type']] logging.debug('Load recognize config: %s' % str(cur_config)) img = cv2.imread(job_data['file'], cv2.IMREAD_UNCHANGED) img_roi_draw = img.copy() res_images = [] for roi_name in cur_config['roi']: roi_config = cur_config['roi'][roi_name] if roi_config.get('hide', False): logging.info('Ignore roi [%s] because it is hidden' % roi_name) continue logging.info('Create roi [%s] = %s' % (roi_name, str(roi_config))) roi_img, roi_path = tools.createRoi2(img, roi_name, roi_config, job_id + '/step2') tools.drawRoi(img_roi_draw, roi_config) res_images.append({ 'name': roi_name, 'x': roi_config['x'], 'y': roi_config['y'], 'w': roi_config['w'], 'h': roi_config['h'], 'file': roi_path, }) tools.writeImageJob(img_roi_draw, job_id + '/step2', '1 draw roi') return {'images': res_images}
app = Flask(__name__) @app.route('/health') def heath_check(): return 'OK' api = Api(app) api.add_resource(DetectType2.DetectType2Api, '/api/detect_invoice') api.add_resource(ExtractImage2.ExtractImage2Api, '/api/extract_image') api.add_resource(Ocr2.OCR2Api, '/api/ocr') api.add_resource(CompressImage.CompressImageApi, '/api/compress_image') logging.debug('Load Recongize Config: %s' % str(recognize.getConfig())) def getVaildImgFileList(): rootDir = r"/home/hello/work/OCRServer/inv_img/" lstValidImgFile = [] bExitLoop = False for parent, dirnames, filenames in os.walk(rootDir): for filename in filenames: if filename.endswith(".jpg"): imgFile = os.path.join(parent,filename) lstValidImgFile.append(imgFile) #if len(lstValidImgFile) > 50: # bExitLoop = True; # break; if bExitLoop: break;
def detectType(self, image, job_id): config = recognize.getConfig() ############################################ # 1. find matched type and config ############################################ grey = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) logging.info("Start match...") # if multi-type is matched, using highest match rate as the matched one. # TODO: highest match rate is not preciseness, should be improved here cur_match_type_name = None cur_match_rate = -1 cur_match_M = None cur_polygons = None logging.debug("Start match feature") sift = cv2.xfeatures2d.SIFT_create() ori_kp, ori_des = sift.detectAndCompute(grey, None) #logging.debug("config is %s" % str(config)) for type_name in config: match_rate, detect_img, perspective_M, polygons = self.matchAndImageCut(sift, grey, ori_kp, ori_des, type_name, config[type_name]['feature'], config[type_name]['image'], job_id) if match_rate > 0: logging.info("[%s] is matched, rate = %s" % (type_name, match_rate)) tools.writeImageJob(detect_img, str(job_id) + '/step1', '1 match [%s] detect' % type_name) # tools.writeImageJob(cut_img, job_id + '/step1', '1 match [%s] cut' % type_name) if match_rate > cur_match_rate: cur_match_rate = match_rate cur_match_type_name = type_name cur_match_M = perspective_M cur_polygons = polygons else: logging.info("[%s] is not matched" % type_name) logging.debug("End match feature") print("cur_polygons =>", polygons) if not cur_match_type_name: logging.info("No feature matched") return self.make_error_response(image) logging.info("Match [%s] at %.2f%%, M=%s" % (cur_match_type_name, cur_match_rate, cur_match_M)) ############################################ # 2. rotate the image # TODO: should support different kinds of rotate/perspective way. ############################################ cur_config = config[cur_match_type_name] perspective_img = None if cur_config['rotate'] == 'perspective': #print("image shape =>", image.shape) #print("cur_config[image_w] =>", cur_config['image']['w'], #"cur_config[image_h] =>", cur_config['image']['h']) perspective_img = cv2.warpPerspective(image, cur_match_M, (cur_config['image']['w'], cur_config['image']['h']), flags=cv2.INTER_LANCZOS4) #print("perspective_img.shape =>", perspective_img.shape) tools.writeImageJob(perspective_img, str(job_id) + '/step1', '2 perspective-%s' % cur_match_type_name) else: logging.error('rotate %s is not supported' % cur_config['rotate']) return self.make_error_response(image) # draw all roi in img perspective_draw_img = perspective_img.copy() for roiName in cur_config['roi']: tools.drawRoi(perspective_draw_img, cur_config['roi'][roiName], (0, 0, 255)) tools.writeImageJob(perspective_draw_img, str(job_id) + '/step1', '3 mark roi') ############################################ # 3. extract the validate area ############################################ validate_roi_names = cur_config['validate']['roi'] for validate_roi_name in validate_roi_names: validate_roi_config = cur_config['roi'].get(validate_roi_name, None) if not validate_roi_config: logging.error('Validate ROI[%s] not exist in roi section' % validate_roi_name) validate_roi, validate_roi_path = tools.createRoi2(perspective_img, validate_roi_name, validate_roi_config, str(job_id) + '/step1') #ocr_result = tools.callOcr(validate_roi, job_id + '/step1', validate_roi_config) #logging.info('Validate ROI OCR result = %s' % ocr_result) return ############################################ # 4. create compress jpg image ############################################ compress_path = tools.writeImageJob(perspective_img, str(job_id) + '/step1', 'compressd', quality='compress') normlize_path = tools.writeImageJob(perspective_img, str(job_id) + '/step1', 'normlized', quality='lossless') ############################################ # 5. write to yaml ############################################ data = { 'file': normlize_path, 'type': cur_match_type_name } tools.saveJobData(data, str(job_id)) logging.info('Save to data.yaml: %s' % str(data)) return { 'ori_image': { # ori_w, ori_h is the origin image without any change (uploaded by wechat) 'w': image.shape[1], 'h': image.shape[0], }, 'normalize_image': { # w, h, file: normalized image (roate,resize, perspective) 'w': int(perspective_img.shape[1]) if perspective_img is not None else None, 'h': int(perspective_img.shape[0]) if perspective_img is not None else None, 'file': compress_path, 'extract_polygon': cur_polygons, }, # the detected image type and its value based, the roi is based on normalized image # if not match, set None 'type': { 'name': cur_match_type_name, 'desc': cur_config.get('name', cur_match_type_name), 'value': orc_result, 'roi': { 'x': validate_roi_config['x'], 'y': validate_roi_config['y'], 'w': validate_roi_config['w'], 'h': validate_roi_config['h'], 'file': validate_roi_path } } }