TensorFlow 分割模型的转换和 OpenCV 的启动

本文介绍了如何将TensorFlow分类和分割模型转换为OpenCV的cv.dnn.Net形式,包括获取和优化冻结图、模型加载、输入处理、推理及评估的过程。以DeepLabV3MobileNetV2为例,详细展示了模型读取、预处理和性能测试的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

除了图优化阶段外,使用 OpenCV API 的 TensorFlow 分类和分割模型的转换管道中涉及的关键概念几乎相同。将 TensorFlow 模型转换为 cv.dnn.Net 的第一步是获取冻结的 TF 模型图。冻结图定义了模型图结构与所需变量(例如权重)的保留值的组合。通常冻结的图形保存在 protobuf () 文件中。要使用 cv.dnn.readNetFromTensorflow 读取生成的分割模型文件,需要使用 TF 图变换工具修改图.pb.pb

实践

在这一部分中,我们将介绍以下几点:

  1. 创建 TF 分类模型转换管道并提供推理
  2. 评估和测试 TF 分类模型

如果只想运行评估或测试模型管道,可以跳过“模型转换管道”教程部分。

模型转换管道

本子章中的代码位于模块中,可以使用以下行执行:dnn_model_runner

python -m dnn_model_runner.dnn_conversion.tf.segmentation.py_to_py_deeplab

TensorFlow 分割模型可以在 TensorFlow 研究模型部分找到,其中包含基于已发表研究论文的模型实现。我们将从以下链接使用预训练的 TF DeepLabV3 检索存档:

http://download.tensorflow.org/models/deeplabv3_mnv2_pascal_trainval_2018_01_29.tar.gz

完整的冻结图获取流水线如下所述:deeplab_retrievement.py

def get_deeplab_frozen_graph():
# 定义要下载的模型路径
models_url = 'http://download.tensorflow.org/models/'
mobilenetv2_voctrainval = 'deeplabv3_mnv2_pascal_trainval_2018_01_29.tar.gz'
# 构建模型链接下载
model_link = models_url + mobilenetv2_voctrainval
尝试:
urllib.request.urlretrieve(model_link, mobilenetv2_voctrainval)
例外情况除外:
print(“未检索到 TF DeepLabV3: {}”.format(model_link))
返回
tf_model_tar = tarfile.open(mobilenetv2_voctrainval)
# 迭代获取的模型存档
对于 tf_model_tar.getmembers() 中的model_tar_elem:
# 检查模型存档中是否包含冻结图
如果TF_FROZEN_GRAPH_NAME os.path.basename(model_tar_elem.name):
# 提取冻结图
tf_model_tar.extract(model_tar_elem, FROZEN_GRAPH_PATH)
tf_model_tar.关闭()

运行此脚本后:

python -m dnn_model_runner.dnn_conversion.tf.segmentation.deeplab_retrievement

我们会进去的.frozen_inference_graph.pbdeeplab/deeplabv3_mnv2_pascal_trainval

在使用 OpenCV 进行网络加载之前,需要优化提取的 .为了优化图形,我们使用带有默认参数的 TF:frozen_inference_graph.pbTransformGraph

DEFAULT_OPT_GRAPH_NAME = “optimized_frozen_inference_graph.pb”
DEFAULT_INPUTS = “sub_7”
DEFAULT_OUTPUTS = “ResizeBilinear_3”
DEFAULT_TRANSFORMS = “remove_nodes(op=Identity)” \
“merge_duplicate_nodes”\
“strip_unused_nodes”\
“ fold_constants(ignore_errors=true)” \
“fold_batch_norms”\
《fold_old_batch_norms》
def optimize_tf_graph(
in_graph,
out_graph=DEFAULT_OPT_GRAPH_NAME,
输入=DEFAULT_INPUTS,
输出=DEFAULT_OUTPUTS,
变换=DEFAULT_TRANSFORMS,
is_manual=真,
was_optimized=真
):
# ...
tf_opt_graph = TransformGraph(
tf_graph,
输入
输出
变换
)

要运行图形优化过程,请执行以下行:

python -m dnn_model_runner.dnn_conversion.tf.segmentation.tf_graph_optimizer --in_graph deeplab/deeplabv3_mnv2_pascal_trainval/frozen_inference_graph.pb

因此,目录将包含 .deeplab/deeplabv3_mnv2_pascal_trainvaloptimized_frozen_inference_graph.pb

获得模型图后,让我们检查下面列出的步骤:

  1. 读取 TF 图frozen_inference_graph.pb
  2. 使用 OpenCV API 读取优化的 TF 冻结图
  3. 准备输入数据
  4. 提供推理
  5. 从预测中获取彩色蒙版
  6. 可视化结果
# 从得到的冻结图中获取TF模型图
deeplab_graph = read_deeplab_frozen_graph(deeplab_frozen_graph_path)
# 使用 OpenCV API 读取 DeepLab 冻结图
opencv_net = cv2.dnn.readNetFromTensorflow(opt_deeplab_frozen_graph_path)
print(“OpenCV 模型已成功读取。模型层:\n“, opencv_net.getLayerNames())
# 获取处理后的图片
original_img_shape、tf_input_blob opencv_input_img = get_processed_imgs(“test_data/sem_segm/2007_000033.jpg”)
# 获取 OpenCV DNN 预测
opencv_prediction = get_opencv_dnn_prediction(opencv_net, opencv_input_img)
# 获取TF模型预测
tf_prediction = get_tf_dnn_prediction(deeplab_graph, tf_input_blob)
# 获取 PASCAL VOC 的等级和颜色
pascal_voc_classes,pascal_voc_colors = read_colors_info(“test_data/sem_segm/pascal-classes.txt”)
# 获取彩色分割掩码
opencv_colored_mask = get_colored_mask(original_img_shape、opencv_prediction、pascal_voc_colors)
tf_colored_mask = get_tf_colored_mask(original_img_shape, tf_prediction, pascal_voc_colors)
# 获取 PASCAL VOC 颜色的调色板
color_legend = get_legend(pascal_voc_classes,pascal_voc_colors)
cv2.imshow('TensorFlow 彩色遮罩', tf_colored_mask)
cv2.imshow('OpenCV DNN 彩色掩码', opencv_colored_mask)
cv2.imshow('颜色图例', color_legend)

对于 PASCAL VOC 颜色解码及其与预测掩码的映射,我们还需要文件,其中包含 PASCAL VOC 类别和相应颜色的完整列表。pascal-classes.txt

让我们以预训练的 TF DeepLabV3 MobileNetV2 为例,更深入地了解每个步骤:

  • 读取TF图:frozen_inference_graph.pb
# 初始化 DeepLab 模型图
model_graph = tf。图()
# 获取
将 tf.io.gfile.GFile(frozen_graph_path, 'rb') graph_file:
tf_model_graph = GraphDef()
tf_model_graph。ParseFromString(graph_file.read())
使用 model_graph.as_default():
tf.import_graph_def(tf_model_graph, name='')
  • 使用 OpenCV API 读取优化的 TF 冻结图:
# 使用 OpenCV API 读取 DeepLab 冻结图
opencv_net = cv2.dnn.readNetFromTensorflow(opt_deeplab_frozen_graph_path)
  • 使用 cv2.dnn.blobFromImage 函数准备输入数据:
# 读取镜像
input_img = cv2.imread(img_path, cv2.IMREAD_COLOR)
input_img = input_img.astype(np.float32)
# TF 模型输入的预处理图像
tf_preproc_img = cv2.resize(input_img, (513, 513))
tf_preproc_img = cv2.cvtColor(tf_preproc_img, cv2.COLOR_BGR2RGB)
# 定义 OpenCV DNN 的预处理参数
均值 = np.array([1.0, 1.0, 1.0]) * 127.5
比例 = 1 / 127.5
# 准备输入 blob 以适应模型输入:
# 1.减去平均值
# 2.缩放以设置从 0 到 1 的像素值
input_blob = cv2.dnn.blobFromImage(
image=input_img,
scalefactor=scale,
size=(513, 513), # img 目标大小
mean=平均值,
swapRB=True, # BGR -> RGB
crop=False # 居中裁剪
)

请注意函数中的预处理顺序。首先,减去平均值,然后将像素值乘以定义的刻度。因此,为了重现TF图像预处理流水线,我们乘以。另一个重要的点是TF DeepLab的图像预处理。为了将图像传递到 TF 模型中,我们只需要构造一个合适的形状,其余的图像预处理在 feature_extractor.py 中描述,并将自动调用。cv2.dnn.blobFromImagemean127.5

  • 提供 OpenCV 推理:cv.dnn_Net
# 设置 OpenCV DNN 输入
opencv_net.setInput(preproc_img)
# OpenCV DNN 推理
out = opencv_net.forward()
print(“OpenCV DNN 分段预测:\n”)
print(“* 形状: ”, out.shape)
# 获取预测类的 ID
out_predictions = np.argmax(out[0], 轴=0)

在上述代码执行后,我们将得到以下输出:

OpenCV DNN 分段预测:
* 形状:(1、21、513、513)

21 个预测通道中的每个通道(其中 21 表示 PASCAL VOC 类的数量)都包含概率,这些概率表示像素对应于 PASCAL VOC 类的可能性。

  • 提供TF模型推理:
preproc_img = np.expand_dims(preproc_img, 0)
# 初始化 TF 会话
tf_session = 会话(图形=model_graph)
input_tensor_name = “图像张量:0”,
output_tensor_name = “语义预测:0”
# 运行推理
out = tf_session.run(
output_tensor_name,
feed_dict={input_tensor_name:[preproc_img]}
)
print(“TF分割模型预测:\n”)
print(“* 形状: ”, out.shape)

TF 推理结果如下:

TF分割模型预测:
* 形状:(1、513、513)

TensorFlow 预测包含对应 PASCAL VOC 类的索引。

  • 将 OpenCV 预测转换为彩色掩码:
mask_height = segm_mask.shape[0]
mask_width = segm_mask.shape[1]
img_height = original_img_shape[0]
img_width = original_img_shape[1]
# 将掩码值转换为 PASCAL VOC 颜色
processed_mask = np.stack([colors[color_id] for color_id in segm_mask.flatten()])
# 将掩模重塑为 3 通道图像
processed_mask = processed_mask.reshape(mask_height, mask_width, 3)
processed_mask = cv2.resize(processed_mask, (img_width, img_height), 插值=cv2。INTER_NEAREST).astype(
np.uint8)
# 将彩色蒙版从BGR转换为RGB
processed_mask = cv2.cvtColor(processed_mask, cv2.COLOR_BGR2RGB)

  • 将 TF 预测转换为彩色掩码:
颜色 = np.array(colors)
processed_mask = 颜色[segm_mask[0]]
img_height = original_img_shape[0]
img_width = original_img_shape[1]
processed_mask = cv2.resize(processed_mask, (img_width, img_height), 插值=cv2。INTER_NEAREST).astype(
np.uint8)
# 将彩色蒙版从 BGR 转换为 RGB,以便与 PASCAL VOC 颜色兼容
processed_mask = cv2.cvtColor(processed_mask, cv2.COLOR_BGR2RGB)

模型评估

建议的模块允许在 PASCAL VOC 数据集上运行完整的评估管道,并测试执行 DeepLab MobileNet 模型。dnn/samplesdnn_model_runner

评估模式

下行表示模块在评估模式下的运行:

python -m dnn_model_runner.dnn_conversion.tf.segmentation.py_to_py_segm

该模型将被读入 OpenCV 对象。TF 和 OpenCV 模型的评估结果(像素精度、平均 IoU、推理时间)将写入日志文件。推理时间值也将在图表中描述,以概括获得的模型信息。cv.dnn_Net

必要的评估配置在test_config.py中定义:

@dataclass
类 TestSegmConfig:
frame_size:int = 500
img_root_dir:str = “./VOC2012”
img_dir:str = os.path.join(img_root_dir, “JPEGImages/”)
img_segm_gt_dir:str = os.path.join(img_root_dir, “SegmentationClass/”)
# 降低值:https://github.com/shelhamer/fcn.berkeleyvision.org/blob/master/data/pascal/seg11valid.txt
segm_val_file:str = os.path.join(img_root_dir, “ImageSets/Segmentation/seg11valid.txt”)
colour_file_cls: str = os.path.join(img_root_dir, “ImageSets/Segmentation/pascal-classes.txt”)

这些值可以根据所选的模型管道进行修改。

测试模式

以下行表示模块在测试模式下的运行,该模式提供了模型推理的步骤:

python -m dnn_model_runner.dnn_conversion.tf.segmentation.py_to_py_segm --test True --default_img_preprocess <True/False> --evaluate False

此处的 key 定义是要使用某些特定值参数化模型测试过程,还是使用默认值,例如 、 或 。default_img_preprocessscalemeanstd

测试配置在类test_config.py表示:TestSegmModuleConfig

@dataclass
类 TestSegmModuleConfig:
segm_test_data_dir:str = “test_data/sem_segm”
test_module_name: str = “segmentation”
test_module_path:str = “segmentation.py”
input_img:str = os.path.join(segm_test_data_dir, “2007_000033.jpg”)
型号: str = “”
frame_height:str = str(TestSegmConfig.frame_size)
frame_width:str = str(TestSegmConfig.frame_size)
比例:浮点数 = 1.0
均值:List[float] = field(default_factory=lambda: [0.0, 0.0, 0.0])
标准:列表[浮点] = 字段(default_factory=列表)
裁剪:bool = False
rgb:bool = 真
类:str = os.path.join(segm_test_data_dir, “pascal-classes.txt”)

默认图像预处理选项定义如下:default_preprocess_config.py

tf_segm_input_blob = {
“比例”:str(1 / 127.5),
“平均值”: [“127.5”, “127.5”, “127.5”],
“std”:[],
“crop”: “假”,
“rgb”: “真”
}

模型测试的基础如 所示。 可以使用 中提供的转换模型和填充的参数自主执行。samples/dnn/segmentation.pysegmentation.py--inputcv2.dnn.blobFromImage

要从头开始重现“模型转换管道”中描述的 OpenCV 步骤,请执行以下行:dnn_model_runner

python -m dnn_model_runner.dnn_conversion.tf.segmentation.py_to_py_segm --test True --default_img_preprocess True --evaluate False

   在线教程

有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓

请添加图片描述

人工智能书籍

第一阶段:零基础入门(3-6个月)

新手应首先通过少而精的学习,看到全景图,建立大局观。 通过完成小实验,建立信心,才能避免“从入门到放弃”的尴尬。因此,第一阶段只推荐4本最必要的书(而且这些书到了第二、三阶段也能继续用),入门以后,在后续学习中再“哪里不会补哪里”即可。

第二阶段:基础进阶(3-6个月)

熟读《机器学习算法的数学解析与Python实现》并动手实践后,你已经对机器学习有了基本的了解,不再是小白了。这时可以开始触类旁通,学习热门技术,加强实践水平。在深入学习的同时,也可以探索自己感兴趣的方向,为求职面试打好基础。

第三阶段:工作应用

这一阶段你已经不再需要引导,只需要一些推荐书目。如果你从入门时就确认了未来的工作方向,可以在第二阶段就提前阅读相关入门书籍(对应“商业落地五大方向”中的前两本),然后再“哪里不会补哪里”。

 有需要的小伙伴,可以点击下方链接免费领取或者V扫描下方二维码免费领取🆓

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值