训练CNN识别验证码时出现输入形状不兼容错误求助
我尝试用简单CNN识别验证码里的数字,但运行model.fit时出错:
ValueError: Input 0 of layer "sequential" is incompatible with the layer: expected shape=(None, 38, 321, 3), found shape=(None, 321, 38, 3)
代码文件(python.py)
IMAGEPATH = 'captcha' dirs = os.listdir(IMAGEPATH) images=[] test_images=[] train_labels=[] train_images, train_labels = [],[] test_labels=[] X=[] Y=[] w=38 h=321 i=0 for name in dirs: file_paths = glob.glob(path.join(IMAGEPATH+"/"+name, '*.*')) for path3 in file_paths: try: img = cv2.imread(path3) img = cv2.resize(img, (w, h)) im_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) ret, im_res = cv2.threshold(im_rgb,180,255,cv2.THRESH_BINARY) if img is not None: images.append(im_res) test_images.append(im_res) name=path3.split(os.path.sep)[-1] getdata=(name.split('.')[-2]) labels=getdata.split('-')[-1] train_labels.append(labels) #train_labels.append(i) i=i+1 except: print(os.path.join(file_paths,name),"error!") pass print(len(images),len(train_labels)) images=np.array(images) train_labels==np.array(train_labels) (X_train, X_test, Y_train, Y_test) = train_test_split(images, train_labels, test_size=0.2, random_state=0) X_train_normalize=X_train.reshape(X_train.shape).astype("float")/255.0 X_test_normalize=X_test.reshape(X_test.shape).astype("float")/255.0 lb = LabelBinarizer().fit(Y_train) Y_train_OneHot = lb.transform(Y_train) Y_test_OneHot = lb.transform(Y_test) model = tf.keras.models.Sequential() model.add(tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(w,h,3))) model.add(tf.keras.layers.MaxPooling2D((2, 2))) model.add(tf.keras.layers.Conv2D(64, (3, 3), activation='relu')) model.add(tf.keras.layers.MaxPooling2D((2, 2))) model.add(tf.keras.layers.Conv2D(64, (3, 3), activation='relu')) model.summary() model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy']) history = model.fit(X_train_normalize, epochs=10 )
验证码文件路径
captcha\0A3F0A\teacher-26.jpg captcha\1673A2\teacher-24.jpg captcha\1E82F1\teacher-25.jpg captcha\33C958\teacher-20.jpg captcha\33DC34\teacher-17.jpg captcha\3AF35E\teacher-14.jpg captcha\3B1C9E\teacher-12.jpg captcha\4207C9\teacher-9.jpg captcha\4B5AC4\teacher-21.jpg captcha\4DD685\teacher-3.jpg captcha\4E44F0\teacher-16.jpg captcha\6BEBFE\teacher-11.jpg captcha\6DCE49\teacher-15.jpg captcha\6E16E9\teacher-4.jpg captcha\c8BA540\teacher-8.jpg captcha\949BA9\teacher-23.jpg captcha\99F671\teacher-7.jpg captcha\A1564D\teacher-10.jpg captcha\A4B883\teacher-13.jpg captcha\D27153\teacher-6.jpg captcha\D36E65\teacher-19.jpg captcha\DC602A\teacher-22.jpg captcha\DDE328\teacher-18.jpg captcha\DED2FB\teacher-2.jpg
完整报错信息
d:\OpecvImage\lookthree.py:83: UserWarning: `Model.fit_generator` is deprecated and will be removed in a future version. Please use `Model.fit`, which supports generators. history = model.fit_generator(X_train_normalize, Traceback (most recent call last): File "d:\OpecvImage\lookthree.py", line 83, in <module> history = model.fit_generator(X_train_normalize, File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\keras\engine\training.py", line 2209, in fit_generator return self.fit( File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\keras\utils\traceback_utils.py", line 67, in error_handler raise e.with_traceback(filtered_tb) from None File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\tensorflow\python\framework\func_graph.py", line 1147, in autograph_handler raise e.ag_error_metadata.to_exception(e) ValueError: in user code: File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\keras\engine\training.py", line 1021, in train_function * return step_function(self, iterator) File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\keras\engine\training.py", line 1010, in step_function ** outputs = model.distribute_strategy.run(run_step, args=(data,)) File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\keras\engine\training.py", line 1000, in run_step ** outputs = model.train_step(data) File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\keras\engine\training.py", line 859, in train_step y_pred = self(x, training=True) File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\keras\utils\traceback_utils.py", line 67, in error_handler raise e.with_traceback(filtered_tb) from None File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\site-packages\keras\engine\input_spec.py", line 264, in assert_input_compatibility raise ValueError(f'Input {input_index} of layer "{layer_name}" is ' ValueError: Input 0 of layer "sequential" is incompatible with the layer: expected shape=(None, 38, 321, 3), found shape=(None, 321, 38, 3)
核心问题:图像宽高顺序不匹配
你定义了w=38,h=321,并在模型输入层指定input_shape=(w,h,3),也就是期望图像形状为**(38, 321, 3)(高度38,宽度321,3通道)。但OpenCV的resize函数参数顺序是(width, height),你调用cv2.resize(img, (w, h))实际把图像改成了宽38,高321**,对应数组形状为(321, 38, 3),和模型期望的顺序完全相反,导致形状不匹配。
修复步骤:
调整resize参数顺序:将
cv2.resize(img, (w, h))改为cv2.resize(img, (h, w)),确保输出图像的宽高对应模型要求的(h, w),最终数组形状为(38, 321, 3)。修正标签转换代码:
train_labels==np.array(train_labels)是无效的比较操作,改为train_labels = np.array(train_labels)才能将标签转换为NumPy数组。补充fit的标签参数:当前
model.fit只传了训练数据,缺少标签输入。结合你使用的SparseCategoricalCrossentropy损失函数,需要传入原始整数标签Y_train,而非独热编码的Y_train_OneHot。
修正后的关键代码片段:
# 修正resize参数顺序 img = cv2.resize(img, (h, w)) # 修正标签转换 train_labels = np.array(train_labels) # 修正model.fit调用 history = model.fit(X_train_normalize, Y_train, epochs=10)
内容的提问来源于stack exchange,提问作者Paul

