You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于ResNet的边缘检测模型运行时出现图像维度不兼容错误

基于ResNet的边缘检测模型构建报错:输入形状不兼容

问题现象

运行基于ResNet的边缘检测代码时,尽管输入图像符合模型要求的(256,256,1)维度,仍触发以下报错:

ValueError: Inputs have incompatible shapes. Received shapes (64, 64, 128) and (32, 32, 128)

报错回溯

ValueError                                Traceback (most recent call last)
<ipython-input-19-f1e611b087b1> in <cell line: 59>()
     57 
     58 # Build the ResNet model
---&gt; 59 model = build_resnet_model()
     60 
     61 # Load pre-trained weights if available

3 frames
/usr/local/lib/python3.10/dist-packages/keras/src/layers/merging/base_merge.py in _compute_elemwise_op_output_shape(self, shape1, shape2)
     72             else:
     73                 if i != j:
---&gt; 74                     raise ValueError(
     75                         "Inputs have incompatible shapes. "
     76                         f"Received shapes {shape1} and {shape2}"

ValueError: Inputs have incompatible shapes. Received shapes (64, 64, 128) and (32, 32, 128)

原代码

import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras import layers, models
from tensorflow.keras.optimizers import Adam

# Define the Residual Block
def residual_block(x, filters, kernel_size=3, stride=1):
    y = layers.Conv2D(filters, kernel_size, strides=stride, padding='same')(x)
    y = layers.BatchNormalization()(y)
    y = layers.Activation('relu')(y)

    y = layers.Conv2D(filters, kernel_size, strides=stride, padding='same')(y)
    y = layers.BatchNormalization()(y)

    # Skip connection
    if stride != 1 or x.shape[-1] != filters:
        x = layers.Conv2D(filters, kernel_size=1, strides=stride, padding='same')(x)

    out = layers.Add()([x, y])
    out = layers.Activation('relu')(out)

    return out

# Build the ResNet model for edge detection
def build_resnet_model(input_shape=(256, 256,1)):
    inputs = layers.Input(shape=input_shape)

    # Initial Convolutional Layer
    x = layers.Conv2D(64, 7, strides=2, activation='relu', padding='same')(inputs)
    x = layers.BatchNormalization()(x)

    # Residual Blocks
    x = residual_block(x, filters=64)
    x = residual_block(x, filters=64)

    x = residual_block(x, filters=128, stride=2)
    x = residual_block(x, filters=128)

    x = residual_block(x, filters=256, stride=2)
    x = residual_block(x, filters=256)

    # Output layer
    outputs = layers.Conv2D(1, 1, activation='sigmoid', padding='same')(x)

    model = models.Model(inputs=inputs, outputs=outputs, name='resnet_edge_detection')
    return model

# Load a test image
test_image_path = '/content/grayscale-image.jpg'
test_image = cv2.imread(test_image_path, cv2.IMREAD_GRAYSCALE)
test_image = np.expand_dims(test_image, axis=-1)  # Add channel dimension
test_image = cv2.resize(test_image, (256, 256))

test_image = np.expand_dims(test_image, axis=0)  # Add batch dimension

# Build the ResNet model
model = build_resnet_model()

# Load pre-trained weights if available
# model.load_weights('path/to/your/weights.h5')

# Compile the model
model.compile(optimizer=Adam(), loss='mse', metrics=['mae'])

# Make predictions on the test image
prediction = model.predict(test_image)[0, ..., 0]

# Plot the original image and the predicted edge map
plt.figure(figsize=(12, 6))

plt.subplot(1, 2, 1)
plt.imshow(test_image[0, ..., 0], cmap='gray')
plt.title('Original Image')

plt.subplot(1, 2, 2)
plt.imshow(prediction, cmap='gray')
plt.title('Predicted Edge Map')

plt.show()

问题原因

报错核心是残差块内的特征图尺寸不匹配:
当调用residual_block(x, filters=128, stride=2)时:

  • 捷径路径(x分支):仅通过1x1卷积做一次stride=2的下采样,特征图尺寸从(128,128,64)变为(64,64,128)
  • 残差路径(y分支):连续两次使用stride=2的3x3卷积,第一次下采样到(64,64,128),第二次再次下采样到(32,32,128)
    最终两者空间维度(64x64 vs 32x32)不一致,无法执行layers.Add()操作。

标准ResNet残差块的设计是:仅在残差路径的第一个卷积层使用stride调整尺寸,第二个卷积层保持stride=1,确保残差路径和捷径路径的输出尺寸一致。

修复方案

修改residual_block函数,将残差路径的第二个卷积层的strides改为1:

修复后的完整代码

import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras import layers, models
from tensorflow.keras.optimizers import Adam

# Define the Residual Block
def residual_block(x, filters, kernel_size=3, stride=1):
    y = layers.Conv2D(filters, kernel_size, strides=stride, padding='same')(x)
    y = layers.BatchNormalization()(y)
    y = layers.Activation('relu')(y)

    # 第二个卷积层改为strides=1,仅第一个卷积做下采样
    y = layers.Conv2D(filters, kernel_size, strides=1, padding='same')(y)
    y = layers.BatchNormalization()(y)

    # Skip connection
    if stride != 1 or x.shape[-1] != filters:
        x = layers.Conv2D(filters, kernel_size=1, strides=stride, padding='same')(x)

    out = layers.Add()([x, y])
    out = layers.Activation('relu')(out)

    return out

# Build the ResNet model for edge detection
def build_resnet_model(input_shape=(256, 256,1)):
    inputs = layers.Input(shape=input_shape)

    # Initial Convolutional Layer
    x = layers.Conv2D(64, 7, strides=2, activation='relu', padding='same')(inputs)
    x = layers.BatchNormalization()(x)

    # Residual Blocks
    x = residual_block(x, filters=64)
    x = residual_block(x, filters=64)

    x = residual_block(x, filters=128, stride=2)
    x = residual_block(x, filters=128)

    x = residual_block(x, filters=256, stride=2)
    x = residual_block(x, filters=256)

    # Output layer
    outputs = layers.Conv2D(1, 1, activation='sigmoid', padding='same')(x)

    model = models.Model(inputs=inputs, outputs=outputs, name='resnet_edge_detection')
    return model

# Load a test image
test_image_path = '/content/grayscale-image.jpg'
test_image = cv2.imread(test_image_path, cv2.IMREAD_GRAYSCALE)
test_image = np.expand_dims(test_image, axis=-1)  # Add channel dimension
test_image = cv2.resize(test_image, (256, 256))

test_image = np.expand_dims(test_image, axis=0)  # Add batch dimension

# Build the ResNet model
model = build_resnet_model()

# Load pre-trained weights if available
# model.load_weights('path/to/your/weights.h5')

# Compile the model
model.compile(optimizer=Adam(), loss='mse', metrics=['mae'])

# Make predictions on the test image
prediction = model.predict(test_image)[0, ..., 0]

# Plot the original image and the predicted edge map
plt.figure(figsize=(12, 6))

plt.subplot(1, 2, 1)
plt.imshow(test_image[0, ..., 0], cmap='gray')
plt.title('Original Image')

plt.subplot(1, 2, 2)
plt.imshow(prediction, cmap='gray')
plt.title('Predicted Edge Map')

plt.show()

内容的提问来源于stack exchange,提问作者Ali Abosinnee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 09:20:00