位置: IT常识 - 正文

【Keras+计算机视觉+Tensorflow】OCR文字识别实战(附源码和数据集 超详细必看)(计算机视觉:一种现代方法)

编辑:rootadmin
【Keras+计算机视觉+Tensorflow】OCR文字识别实战(附源码和数据集 超详细必看)

推荐整理分享【Keras+计算机视觉+Tensorflow】OCR文字识别实战(附源码和数据集 超详细必看)(计算机视觉:一种现代方法),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:计算机的视频,计算机视觉:一种现代方法,计算机视频解释,计算机的视频,计算机视觉 视频处理,计算机视频解释,计算机视觉百度百科,计算机视觉:一种现代方法,内容如对您有帮助,希望把文章链接给更多的朋友!

需要源码和数据集请点赞关注收藏后评论区留言私信~~~

一、OCR文字识别简介

利用计算机自动识别字符的技术,是模式识别应用的一个重要领域。人们在生产和生活中,要处理大量的文字、报表和文本。为了减轻人们的劳动,提高处理效率,从上世纪50年代起就开始探讨文字识别方法,并研制出光学字符识别器。

OCR(Optical Character Recognition)图像文字识别是人工智能的重要分支,赋予计算机人眼的功能,使其可以看图识字,图像文字识别系统流程一般分为图像采集、文字检测、文字识别以及结果输出四部分。

 二、OCR文字识别项目实战1:数据集简介

MSRA-TD500该数据集共包含500 张自然场景图像,其分辨率在1296 ´ 864至920 ´ 1280 之间,涵盖了室内商场、标识牌、室外街道、广告牌等大多数场,文本包含中文和英文,有着不同的字体、大小和倾斜方向,部分数据集图像如下图所示。

 数据集项目结构如下 分为训练集和测试集

2:项目结构【Keras+计算机视觉+Tensorflow】OCR文字识别实战(附源码和数据集 超详细必看)(计算机视觉:一种现代方法)

整体项目结构如下 上面是一些算法和模型比如CRAFT CRNN的定义,下面是测试代码

 CRAFT算法实现文本行的检测如图下图所示。首先将完整的文字区域输入CRAFT文字检测网络,得到字符级的文字得分结果热图(Text Score)和字符级文本连接得分热图(Link Score),最后根据连通域得到每个文本行的位置

3:效果展示 

开始运行代码

输出运行结果 可以放入不同图片进行测试 

 

 

 

 

三、代码 

部分代码如下 需要全部代码和数据集请点赞关注收藏后评论区留言私信~~~  

"""This script demonstrates how to train the modelon the SynthText90 using multiple GPUs."""# pylint: disable=invalid-nameimport datetimeimport argparseimport mathimport randomimport stringimport functoolsimport itertoolsimport osimport tarfileimport urllib.requestimport numpy as npimport cv2import imgaugimport tqdmimport tensorflow as tfimport keras_ocr# pylint: disable=redefined-outer-namedef get_filepaths(data_path, split): """Get the list of filepaths for a given split (train, val, or test).""" with open(os.path.join(data_path, f'mnt/ramdisk/max/90kDICT32px/annotation_{split}.txt'), 'r') as text_file: filepaths = [ os.path.join(data_path, 'mnt/ramdisk/max/90kDICT32px', line.split(' ')[0][2:]) for line in text_file.readlines() ] return filepaths# pylint: disable=redefined-outer-namedef download_extract_and_process_dataset(data_path): """Download and extract the synthtext90 dataset.""" archive_filepath = os.path.join(data_path, 'mjsynth.tar.gz') extraction_directory = os.path.join(data_path, 'mnt') if not os.path.isfile(archive_filepath) and not os.path.isdir(extraction_directory): print('Downloading the dataset.') urllib.request.urlretrieve("https://www.robots.ox.ac.uk/~vgg/data/text/mjsynth.tar.gz", archive_filepath) if not os.path.isdir(extraction_directory): print('Extracting files.') with tarfile.open(os.path.join(data_path, 'mjsynth.tar.gz')) as tfile: tfile.extractall(data_path)def get_image_generator(filepaths, augmenter, width, height): """Get an image generator for a list of SynthText90 filepaths.""" filepaths = filepaths.copy() for filepath in itertools.cycle(filepaths): text = filepath.split(os.sep)[-1].split('_')[1].lower() image = cv2.imread(filepath) if image is None: print(f'An error occurred reading: {filepath}') image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) image = keras_ocr.tools.fit(image, width=width, height=height, cval=np.random.randint(low=0, high=255, size=3).astype('uint8')) if augmenter is not None: image = augmenter.augment_image(image) if filepath == filepaths[-1]: random.shuffle(filepaths) yield image, textif __name__ == '__main__': parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument('--model_id', default='recognizer', help='The name to use for saving model checkpoints.') parser.add_argument( '--data_path', default='.', help='The path to the directory containing the dataset and where we will put our logs.') parser.add_argument( '--logs_path', default='./logs', help=( 'The path to where logs and checkpoints should be stored. ' 'If a checkpoint matching "model_id" is found, training will resume from that point.')) parser.add_argument('--batch_size', default=16, help='The training batch size to use.') parser.add_argument('--no-file-verification', dest='verify_files', action='store_false') parser.set_defaults(verify_files=True) args = parser.parse_args() weights_path = os.path.join(args.logs_path, args.model_id + '.h5') csv_path = os.path.join(args.logs_path, args.model_id + '.csv') download_extract_and_process_dataset(args.data_path) with tf.distribute.MirroredStrategy().scope(): recognizer = keras_ocr.recognition.Recognizer(alphabet=string.digits + string.ascii_lowercase, height=31, width=200, stn=False, optimizer=tf.keras.optimizers.RMSprop(), weights=None) if os.path.isfile(weights_path): print('Loading saved weights and creating new version.') dt_string = datetime.datetime.now().isoformat() weights_path = os.path.join(args.logs_path, args.model_id + '_' + dt_string + '.h5') csv_path = os.path.join(args.logs_path, args.model_id + '_' + dt_string + '.csv') recognizer.model.load_weights(weights_path) augmenter = imgaug.augmenters.Sequential([ imgaug.augmenters.Multiply((0.9, 1.1)), imgaug.augmenters.GammaContrast(gamma=(0.5, 3.0)), imgaug.augmenters.Invert(0.25, per_channel=0.5) ]) os.makedirs(args.logs_path, exist_ok=True) training_filepaths, validation_filepaths = [ get_filepaths(data_path=args.data_path, split=split) for split in ['train', 'val'] ] if args.verify_files: assert all( os.path.isfile(filepath) for filepath in tqdm.tqdm(training_filepaths + validation_filepaths, desc='Checking filepaths.')), 'Some files appear to be missing.' (training_image_generator, training_steps), (validation_image_generator, validation_steps) = [ (get_image_generator( filepaths=filepaths, augmenter=augmenter, width=recognizer.model.input_shape[2], height=recognizer.model.input_shape[1], ), math.ceil(len(filepaths) / args.batch_size)) for filepaths, augmenter in [(training_filepaths, augmenter), (validation_filepaths, None)] ] training_generator, validation_generator = [ tf.data.Dataset.from_generator( functools.partial(recognizer.get_batch_generator, image_generator=image_generator, batch_size=args.batch_size), output_types=((tf.float32, tf.int64, tf.float64, tf.int64), tf.float64), output_shapes=((tf.TensorShape([None, 31, 200, 1]), tf.TensorShape([None, recognizer.training_model.input_shape[1][1]]), tf.TensorShape([None, 1]), tf.TensorShape([None, 1])), tf.TensorShape([None, 1]))) for image_generator in [training_image_generator, validation_image_generator] ] callbacks = [ tf.keras.callbacks.EarlyStopping(monitor='val_loss', min_delta=0, patience=10, restore_best_weights=False), tf.keras.callbacks.ModelCheckpoint(weights_path, monitor='val_loss', save_best_only=True), tf.keras.callbacks.CSVLogger(csv_path) ] recognizer.training_model.fit( x=training_generator, steps_per_epoch=training_steps, validation_steps=validation_steps, validation_data=validation_generator, callbacks=callbacks, epochs=1000, )"""This script is what was used to generate thebackgrounds.zip and fonts.zip files."""# pylint: disable=invalid-name,redefined-outer-nameimport jsonimport urllib.requestimport urllib.parseimport concurrentimport shutilimport zipfileimport globimport osimport numpy as npimport tqdmimport cv2import keras_ocrif __name__ == '__main__': fonts_commit = 'a0726002eab4639ee96056a38cd35f6188011a81' fonts_sha256 = 'e447d23d24a5bbe8488200a058cd5b75b2acde525421c2e74dbfb90ceafce7bf' fonts_source_zip_filepath = keras_ocr.tools.download_and_verify( url=f'https://github.com/google/fonts/archive/{fonts_commit}.zip', cache_dir='.', sha256=fonts_sha256) shutil.rmtree('fonts-raw', ignore_errors=True) with zipfile.ZipFile(fonts_source_zip_filepath) as zfile: zfile.extractall(path='fonts-raw') retained_fonts = [] sha256s = [] basenames = [] # The blacklist includes fonts that, at least for the English alphabet, were found # to be illegible (e.g., thin fonts) or render in unexpected ways (e.g., mathematics # fonts). blacklist = [ 'AlmendraDisplay-Regular.ttf', 'RedactedScript-Bold.ttf', 'RedactedScript-Regular.ttf', 'Sevillana-Regular.ttf', 'Mplus1p-Thin.ttf', 'Stalemate-Regular.ttf', 'jsMath-cmsy10.ttf', 'Codystar-Regular.ttf', 'AdventPro-Thin.ttf', 'RoundedMplus1c-Thin.ttf', 'EncodeSans-Thin.ttf', 'AlegreyaSans-ThinItalic.ttf', 'AlegreyaSans-Thin.ttf', 'FiraSans-Thin.ttf', 'FiraSans-ThinItalic.ttf', 'WorkSans-Thin.ttf', 'Tomorrow-ThinItalic.ttf', 'Tomorrow-Thin.ttf', 'Italianno-Regular.ttf', 'IBMPlexSansCondensed-Thin.ttf', 'IBMPlexSansCondensed-ThinItalic.ttf', 'Lato-ExtraLightItalic.ttf', 'LibreBarcode128Text-Regular.ttf', 'LibreBarcode39-Regular.ttf', 'LibreBarcode39ExtendedText-Regular.ttf', 'EncodeSansExpanded-ExtraLight.ttf', 'Exo-Thin.ttf', 'Exo-ThinItalic.ttf', 'DrSugiyama-Regular.ttf', 'Taviraj-ThinItalic.ttf', 'SixCaps.ttf', 'IBMPlexSans-Thin.ttf', 'IBMPlexSans-ThinItalic.ttf', 'AdobeBlank-Regular.ttf', 'FiraSansExtraCondensed-ThinItalic.ttf', 'HeptaSlab[wght].ttf', 'Karla-Italic[wght].ttf', 'Karla[wght].ttf', 'RalewayDots-Regular.ttf', 'FiraSansCondensed-ThinItalic.ttf', 'jsMath-cmex10.ttf', 'LibreBarcode39Text-Regular.ttf', 'LibreBarcode39Extended-Regular.ttf', 'EricaOne-Regular.ttf', 'ArimaMadurai-Thin.ttf', 'IBMPlexSerif-ExtraLight.ttf', 'IBMPlexSerif-ExtraLightItalic.ttf', 'IBMPlexSerif-ThinItalic.ttf', 'IBMPlexSerif-Thin.ttf', 'Exo2-Thin.ttf', 'Exo2-ThinItalic.ttf', 'BungeeOutline-Regular.ttf', 'Redacted-Regular.ttf', 'JosefinSlab-ThinItalic.ttf', 'GothicA1-Thin.ttf', 'Kanit-ThinItalic.ttf', 'Kanit-Thin.ttf', 'AlegreyaSansSC-ThinItalic.ttf', 'AlegreyaSansSC-Thin.ttf', 'Chathura-Thin.ttf', 'Blinker-Thin.ttf', 'Italiana-Regular.ttf', 'Miama-Regular.ttf', 'Grenze-ThinItalic.ttf', 'LeagueScript-Regular.ttf', 'BigShouldersDisplay-Thin.ttf', 'YanoneKaffeesatz[wght].ttf', 'BungeeHairline-Regular.ttf', 'JosefinSans-Thin.ttf', 'JosefinSans-ThinItalic.ttf', 'Monofett.ttf', 'Raleway-ThinItalic.ttf', 'Raleway-Thin.ttf', 'JosefinSansStd-Light.ttf', 'LibreBarcode128-Regular.ttf' ] for filepath in tqdm.tqdm(sorted(glob.glob('fonts-raw/**/**/**/*.ttf')), desc='Filtering fonts.'): sha256 = keras_ocr.tools.sha256sum(filepath) basename = os.path.basename(filepath) # We check the sha256 and filenames because some of the fonts # in the repository are duplicated (see TRIVIA.md). if sha256 in sha256s or basename in basenames or basename in blacklist: continue sha256s.append(sha256) basenames.append(basename) retained_fonts.append(filepath) retained_font_families = set([filepath.split(os.sep)[-2] for filepath in retained_fonts]) added = [] with zipfile.ZipFile(file='fonts.zip', mode='w') as zfile: for font_family in tqdm.tqdm(retained_font_families, desc='Saving ZIP file.'): # We want to keep all the metadata files plus # the retained font files. And we don't want # to add the same file twice. files = [ input_filepath for input_filepath in glob.glob(f'fonts-raw/**/**/{font_family}/*') if input_filepath not in added and (input_filepath in retained_fonts or os.path.splitext(input_filepath)[1] != '.ttf') ] added.extend(files) for input_filepath in files: zfile.write(filename=input_filepath, arcname=os.path.join(*input_filepath.split(os.sep)[-2:])) print('Finished saving fonts file.') # pylint: disable=line-too-long url = ( 'https://commons.wikimedia.org/w/api.php?action=query&generator=categorymembers&gcmtype=file&format=json' '&gcmtitle=Category:Featured_pictures_on_Wikimedia_Commons&prop=imageinfo&gcmlimit=50&iiprop=url&iiurlwidth=1024' ) gcmcontinue = None max_responses = 300 responses = [] for responseCount in tqdm.tqdm(range(max_responses)): current_url = url if gcmcontinue is not None: current_url += f'&continue=gcmcontinue||&gcmcontinue={gcmcontinue}' with urllib.request.urlopen(url=current_url) as response: current = json.loads(response.read()) responses.append(current) gcmcontinue = None if 'continue' not in current else current['continue']['gcmcontinue'] if gcmcontinue is None: break print('Finished getting list of images.') # We want to avoid animated images as well as icon files. image_urls = [] for response in responses: image_urls.extend( [page['imageinfo'][0]['thumburl'] for page in response['query']['pages'].values()]) image_urls = [url for url in image_urls if url.lower().endswith('.jpg')] shutil.rmtree('backgrounds', ignore_errors=True) os.makedirs('backgrounds') assert len(image_urls) == len(set(image_urls)), 'Duplicates found!' with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor: futures = [ executor.submit(keras_ocr.tools.download_and_verify, url=url, cache_dir='./backgrounds', verbose=False) for url in image_urls ] for _ in tqdm.tqdm(concurrent.futures.as_completed(futures), total=len(futures)): pass for filepath in glob.glob('backgrounds/*.JPG'): os.rename(filepath, filepath.lower()) print('Filtering images by aspect ratio and maximum contiguous contour.') image_paths = np.array(sorted(glob.glob('backgrounds/*.jpg'))) def compute_metrics(filepath): image = keras_ocr.tools.read(filepath) aspect_ratio = image.shape[0] / image.shape[1] contour, _ = keras_ocr.tools.get_maximum_uniform_contour(image, fontsize=40) area = cv2.contourArea(contour) if contour is not None else 0 return aspect_ratio, area metrics = np.array([compute_metrics(filepath) for filepath in tqdm.tqdm(image_paths)]) filtered_paths = image_paths[(metrics[:, 0] < 3 / 2) & (metrics[:, 0] > 2 / 3) & (metrics[:, 1] > 1e6)] detector = keras_ocr.detection.Detector() paths_with_text = [ filepath for filepath in tqdm.tqdm(filtered_paths) if len( detector.detect( images=[keras_ocr.tools.read_and_fit(filepath, width=640, height=640)])[0]) > 0 ] filtered_paths = np.array([path for path in filtered_paths if path not in paths_with_text]) filtered_basenames = list(map(os.path.basename, filtered_paths)) basename_to_url = { os.path.basename(urllib.parse.urlparse(url).path).lower(): url for url in image_urls } filtered_urls = [basename_to_url[basename.lower()] for basename in filtered_basenames] assert len(filtered_urls) == len(filtered_paths) removed_paths = [filepath for filepath in image_paths if filepath not in filtered_paths] for filepath in removed_paths: os.remove(filepath) with open('backgrounds/urls.txt', 'w') as f: f.write('\n'.join(filtered_urls)) with zipfile.ZipFile(file='backgrounds.zip', mode='w') as zfile: for filepath in tqdm.tqdm(filtered_paths.tolist() + ['backgrounds/urls.txt'], desc='Saving ZIP file.'): zfile.write(filename=filepath, arcname=os.path.basename(filepath.lower()))

创作不易 觉得有帮助请点赞关注收藏~~~

本文链接地址:https://www.jiuchutong.com/zhishi/295982.html 转载请保留说明!

上一篇:Vue的路由配置(Vue2和Vue3的路由配置)(vue路由的几种方式)

下一篇:圣米歇尔山,法国诺曼底 (© DaLiu/Getty Images)(圣米歇尔山法语介)

  • 腾讯会议开悬浮窗会被发现吗(腾讯会议开悬浮窗摄像头会黑屏吗)

    腾讯会议开悬浮窗会被发现吗(腾讯会议开悬浮窗摄像头会黑屏吗)

  • 红米k30如何设置呼吸灯(红米k30如何设置永不锁屏)

    红米k30如何设置呼吸灯(红米k30如何设置永不锁屏)

  • 华为手机微信屏幕黑色是怎么回事(华为手机微信屏幕)

    华为手机微信屏幕黑色是怎么回事(华为手机微信屏幕)

  • 苹果电脑mac突然巨卡(苹果电脑mac突然没有声音)

    苹果电脑mac突然巨卡(苹果电脑mac突然没有声音)

  • 华为mate30pro丢了怎么找回(华为mate30pro丢了能找回来吗)

    华为mate30pro丢了怎么找回(华为mate30pro丢了能找回来吗)

  • 抖音无关注别人之后又消失了(抖音没关注别人关注列表里有他)

    抖音无关注别人之后又消失了(抖音没关注别人关注列表里有他)

  • 苹果隔多久可以二退(苹果多久可以吃苹果)

    苹果隔多久可以二退(苹果多久可以吃苹果)

  • 手机号码注销后绑定的软件怎么办(手机号码注销后还能查到通话记录吗)

    手机号码注销后绑定的软件怎么办(手机号码注销后还能查到通话记录吗)

  • 笔记本集显是什么意思(笔记本集显型号)

    笔记本集显是什么意思(笔记本集显型号)

  • cpu速度是指什么(cpu的速度用什么单位)

    cpu速度是指什么(cpu的速度用什么单位)

  • 笔记本电脑如何复制粘贴文字(笔记本电脑如何录屏)

    笔记本电脑如何复制粘贴文字(笔记本电脑如何录屏)

  • 抖音怎么拍别人同款特效(抖音怎么拍别人的特效)

    抖音怎么拍别人同款特效(抖音怎么拍别人的特效)

  • ppt怎么调兼容模式(如何设置ppt兼容)

    ppt怎么调兼容模式(如何设置ppt兼容)

  • keyshot怎么打光(keyshot怎么打光让阴影完整)

    keyshot怎么打光(keyshot怎么打光让阴影完整)

  • 手机怎么连接路由器呢(手机怎么连接路虎屏幕)

    手机怎么连接路由器呢(手机怎么连接路虎屏幕)

  • 小米8怎么看使用记录(小米怎么看使用时间时长)

    小米8怎么看使用记录(小米怎么看使用时间时长)

  • 怎样查询ip地址精确位置(怎样查询ip地址归属地)

    怎样查询ip地址精确位置(怎样查询ip地址归属地)

  • 苹果手机怎么修改日期和时间(苹果手机怎么修改id名字)

    苹果手机怎么修改日期和时间(苹果手机怎么修改id名字)

  • airpods大小尺寸(airpods大小尺寸一样吗)

    airpods大小尺寸(airpods大小尺寸一样吗)

  • 快手卡点视频怎么做(快手卡点视频教程)

    快手卡点视频怎么做(快手卡点视频教程)

  • 苹果手机碎屏怎么修(苹果手机碎屏怎么关机)

    苹果手机碎屏怎么修(苹果手机碎屏怎么关机)

  • 零成本打造苹果系统安装U盘 U盘重装苹果系统图文教程(iphone制造成本)

    零成本打造苹果系统安装U盘 U盘重装苹果系统图文教程(iphone制造成本)

  • iphone6s掉水里怎么办?iphone6s掉入水中的处理方法(iphone6s掉水里怎么办)

    iphone6s掉水里怎么办?iphone6s掉入水中的处理方法(iphone6s掉水里怎么办)

  • Win11升级反馈:可使用Win7兼容性模式运行升级助手绕过系统兼容性测试(win10升级win11报错)

    Win11升级反馈:可使用Win7兼容性模式运行升级助手绕过系统兼容性测试(win10升级win11报错)

  • dedecms如何设置首页滚动显示?(dedecms配置)

    dedecms如何设置首页滚动显示?(dedecms配置)

  • 出口退税超期未缴税
  • 普通发票可以抵税点吗
  • 工资记借方还是贷方
  • 缺少订单停工费用如何做账
  • 税盘抵扣的会计分录
  • 外贸企业出口怎么写
  • 没收逾期未退包装物押金收益,应计入( )科目
  • 增值税专票未认证丢失怎么办
  • 开票给子公司的利息收入怎么做账?
  • 收到的扶贫工作经费会计分录
  • 应交税费里的应交企业所得税意思是交了吗
  • 公司法人要交什么税
  • 国税注销了地税没注销现在经营异常
  • 发票二维码压线可以用吗
  • 什么称为非正数
  • 小规模纳税人可以开9%专票吗
  • 期末未分配利润大于期初未分配利润+期末净利润
  • 审计报告的二维码扫出来是什么
  • 以前年度损益在借方
  • 合作保证金规定
  • 固定资产盘亏盘盈账务处理
  • 支付测量费的补贴费用怎么记账
  • 办理税务迁移
  • 业务招待费是什么科目
  • windows11不显示桌面
  • 笔记本电池保养注意事项
  • 报纸公示具有什么法律效应
  • 其他债权投资的交易费用计入什么科目
  • win10电脑文件夹打不开
  • 营业外支出与营业收入之比应小于1%的说明
  • 电脑找不到u盘怎么解决
  • 企业网管出路
  • 个人销售住房是否免征土地增值税
  • 增值税专用发票上注明的价款含税吗
  • 单位管理费用核算范围包括
  • php怎么传递参数
  • php如何实现分页功能
  • php安装oci8
  • python中的查找函数
  • 模型论文是什么类型
  • 知识图谱的构建方法有两种
  • 利息收入怎么做账务处理
  • 业务招待费进项转出报表怎么填
  • 产权转移书据是什么印花税
  • 固定资产属于有形还是无形资产
  • 工资走公账和私账哪个好
  • 质保金 销售费用
  • 汽油发票怎么开专票
  • 增值税普票没有发票章可以吗
  • 坏账准备的核销的分录怎么做
  • 冲减当期利润
  • 个人工资税收怎么计算年收入
  • 异地预缴怎么填写申报表
  • 小规模纳税人差旅费可以抵扣吗
  • 普票丢失可以以照片入账么
  • 认缴出资额承担责任怎么算
  • 小额零星支出是什么意思
  • 支付水电费取得专用发票上注明税金0.68万元
  • 药品进销差价的计算公式是什么
  • 对公帐户发票金额是什么
  • 给客户的促销费用怎么入账
  • 禁用windows键快捷键
  • win7怎么退出域环境
  • windows8 enterprise
  • linuxvim编辑器的用法
  • gnuradio编写模块
  • win10关机快捷键
  • 苹果Mac OS X通知中心提示音怎么修改 OS X通知中心提示音更换方法图解
  • win8修改锁屏壁纸
  • win1021年更新
  • 360安全卫士检测出来高危漏洞需要修复吗
  • cocos2dx框架
  • 用简洁的语言推荐一本书
  • IE6,IE7和firefox对DIV的支持区别
  • div+css网页布局实例
  • python ntlk
  • 税务局上下班路上能穿制服吗
  • 怎么打印纳税申报清单
  • 慈善组织可能会出现哪些问题
  • 税务人员服务态度恶劣怎么办
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设