用 TensorFlow 1.x 快速找出两幅图的差异 —— 完整实战与逐行解析 -Python程序图片找不同
用 TensorFlow 1.x 快速找出两幅图的差异 —— 完整实战与逐行解析 -Python程序图片找不同
用 TensorFlow 1.x 快速找出两幅图的差异 —— 完整实战与逐行解析
适用于仍在使用 TensorFlow 1.15 或无法开启 Eager 的环境(阿里云 PAI-DSW、部分离线服务器等)。
![]() | ![]() |
一、背景与痛点
一、背景与痛点
- 场景:线上 Notebook 里只有 TF 1.x,默认 Graph 模式,
.numpy()
不可用。 - 问题:
- 两张图片尺寸不一致(本文示例中宽 459 vs 455)导致
InvalidArgumentError: Incompatible shapes
。 - 代码需要同时兼容 静态图 + 任意尺寸输入 + 可视化输出。
- 两张图片尺寸不一致(本文示例中宽 459 vs 455)导致
本文给出的 40 行脚本一次性解决上述痛点,并逐行拆解思路,方便读者即拷即用,也能二次开发。
二、最终效果
原始图 1 | 原始图 2 | 卷积后图 1 | 差异热力图 |
---|---|---|---|
![]() | |||
![]() | |||
![]() | |||
![]() | |||
三、完整代码(可直接运行)
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np# 1. 显式关闭 Eager(TF1.x 默认 Graph,防止误开)
tf.compat.v1.disable_eager_execution()# 2. 统一尺寸:可按需修改
TARGET_H, TARGET_W = 512, 512image_path1 = '1.png'
image_path2 = '2.png'# 3. 封装读取+resize
def load_and_resize(path, channels=1):img = tf.io.read_file(path)img = tf.image.decode_png(img, channels=channels)img = tf.image.resize(img, [TARGET_H, TARGET_W]) # 关键:保证同尺寸img = tf.cast(img, tf.float32) / 255.0 # 归一化img = tf.expand_dims(img, 0) # [1, H, W, C]return imgimg1 = load_and_resize(image_path1)
img2 = load_and_resize(image_path2)# 4. 定义卷积层
conv2d_layer = tf.keras.layers.Conv2D(filters=1, kernel_size=3, activation='relu', padding='same'
)output1 = conv2d_layer(img1)
output2 = conv2d_layer(img2)
diff = tf.abs(output1 - output2)# 5. 在 Session 中运行
with tf.compat.v1.Session() as sess:sess.run(tf.compat.v1.global_variables_initializer())img1_np, img2_np, out1_np, diff_np = sess.run([tf.squeeze(img1),tf.squeeze(img2),tf.squeeze(output1),tf.squeeze(diff)])# 6. 可视化
plt.figure(figsize=(10, 5))
plt.subplot(1, 4, 1)
plt.imshow(img1_np, cmap='gray')
plt.title('Image 1')
plt.axis('off')plt.subplot(1, 4, 2)
plt.imshow(img2_np, cmap='gray')
plt.title('Image 2')
plt.axis('off')plt.subplot(1, 4, 3)
plt.imshow(out1_np, cmap='gray')
plt.title('Conv2D Image 1')
plt.axis('off')plt.subplot(1, 4, 4)
plt.imshow(diff_np, cmap='gray')
plt.title('Difference')
plt.axis('off')plt.tight_layout()
plt.show()
四、逐行拆解与知识点
行号范围 | 关键代码 | 作用 & 要点 |
---|---|---|
1–3 | import ... | TF1.x 仍需手动 import tensorflow.compat.v1 ;Matplotlib 负责可视化。 |
6 | disable_eager_execution() | 防止某些环境默认开启 Eager,导致 Graph 与 Eager 混用。 |
9 | 统一尺寸 | 避免 InvalidArgumentError 的核心:任何输入图都会被拉伸/压缩到 [512,512] 。 |
11–12 | 路径 | 支持 PNG/JPEG;若有多张图,可改写为循环。 |
15–25 | load_and_resize | 重点函数 - tf.image.decode_png 指定 channels=1 直接变灰度- tf.image.resize 支持双线性(默认)或最近邻- 归一化到 [0,1] 可加速收敛、避免梯度爆炸 |
28–31 | 卷积层 | 使用 tf.keras.layers.Conv2D 在 Graph 中也能直接建图;padding='same' 保证输出尺寸与输入一致。 |
33 | tf.abs(output1 - output2) | 元素级绝对差,得到差异热力图。 |
35–40 | Session.run | TF1.x 必走流程;变量需先 global_variables_initializer 。 |
43–60 | 可视化 | 4 张子图并排,方便肉眼比对;cmap='gray' 更适合灰度图。 |
五、常见踩坑 FAQ
-
RuntimeWarning: divide by zero
归一化时若原图为纯黑(全 0),不会报错,但差异图可能全 0,属正常现象。 -
颜色通道不一致
若读入 RGB(channels=3
),请把cmap='gray'
改为cmap=None
,或转灰度:tf.image.rgb_to_grayscale
。 -
尺寸缩放导致细节失真
可把TARGET_H/W
设成两张图的最大高宽,再裁剪居中;或改用tf.image.resize_with_pad
保持比例。 -
TF2.x 用户
直接删掉tf.compat.v1.disable_eager_execution()
与Session
相关代码,用.numpy()
即可。
六、延伸玩法
- 批量比较:把路径换成
glob('*.png')
,循环输出差异 GIF。 - 阈值过滤:
diff_np = (diff_np > 0.1).astype(float)
高亮显著差异。 - 迁移到部署:把
diff
结果再送入二分类网络,做“缺陷检测”。
七、一句话总结
在 TF1.x 静态图 下,只要 提前统一尺寸 + 用 Session 取数 + Matplotlib 可视化,就能无痛完成“两图找茬”任务;
若环境允许,直接升级到 TF2.x 会更简洁。希望这篇博客能帮你少踩坑、多产出!
NotoBook在线编辑平台为开发者提供了一站式的云端编程环境,具备以下核心优势:
- 专业级IDE功能:
- 支持多种编程语言(Python、R、Java等)的语法高亮和自动补全
- 内置代码调试器和版本控制工具
- 支持多文件管理和项目结构导航
- 提供实时协作编辑功能,支持团队协同开发
- 强大的计算资源配置:
-
GPU资源:60小时/月的Tesla V100计算卡使用权
- 适用于深度学习训练、3D渲染等计算密集型任务
- 典型应用场景包括:
- 图像识别模型训练
- 自然语言处理任务
- 科学计算模拟
-
CPU资源:无限制使用
- 配备Intel Xeon处理器集群
- 适用于常规编程、数据处理等任务
- 支持长时间运行的批处理作业
- 特色功能:
- 预装主流数据科学工具包(TensorFlow、PyTorch等)
- 支持Jupyter Notebook交互式开发
- 提供数据可视化工具
- 内置常用数据集和模型库
- 使用场景:
- 高校教学与科研
- 企业原型开发
- 个人编程学习
- 算法竞赛准备
平台采用按需分配的资源管理机制,确保用户能够高效利用计算资源完成开发任务。NotoBook在线编辑, 为大家提供完备的IDE以及丰富的计算资源
GPU :60.0小时
CPU :不限