ESP32串口传输uint16像素值至Python生成图像出现噪点问题排查
串口直接传输像素值到Python生成噪点的排查方案
首先明确:你不用纠结CuteCom的编码——ESP32代码里是通过sprintf("%u\r\n", pixel)把uint16像素值转成ASCII格式的十进制字符串发送的,CuteCom只是显示和复制这些纯文本数字,不存在特殊编码。问题根源不在编码,而是串口传输的数据完整性、顺序,或者Python图像生成逻辑的问题,以下是具体排查步骤:
1. 对比两种方式的原始数据
把CuteCom复制导出的CSV,和Python直接读取串口后保存的CSV做逐行对比:
- 检查总行数是否一致(比如OV7670输出320x240分辨率的话,应该有76800行)
- 随机抽取多组数据,看数字是否完全相同
- 查看是否存在连续数字粘连、空行、异常字符的情况
如果数据数量少了或顺序乱了,说明串口传输有丢包或同步问题。
2. 排查串口传输稳定性
ESP32端:如果发送速度过快,会导致Python串口缓冲区溢出丢数据。可以在发送语句后加微小延迟:
uart_write_bytes(UART_NUM,buffer,strlen(buffer)); vTaskDelay(1); // 增加1ms延迟,降低发送速率或者发送完一帧后添加结束标记,方便Python判断数据边界:
// 帧发送完成后发送结束信号 sprintf(buffer,"END\r\n"); uart_write_bytes(UART_NUM,buffer,strlen(buffer));Python端:优化读取逻辑,确保完整接收一帧数据,避免漏读:
import serial import numpy as np from PIL import Image serialPort = serial.Serial("COMx", 115200, timeout=1) # 替换为你的串口和波特率 pixel_list = [] frame_complete = False while not frame_complete: incoming = serialPort.readline().decode('ascii', 'ignore').rstrip() if not incoming: continue if incoming == "END": frame_complete = True break try: pixel = int(incoming) pixel_list.append(pixel) except ValueError: print(f"收到无效数据: {incoming}") # 验证像素数量是否符合分辨率 width, height = 320, 240 # 替换为你的OV7670实际分辨率 print(f"读取到像素数: {len(pixel_list)},预期: {width*height}")
3. 检查图像生成逻辑
如果数据完全一致但图像仍有噪点,问题出在像素格式转换或排列顺序:
- OV7670输出的uint16通常是RGB565格式,需要转成RGB888才能正常显示:
if len(pixel_list) == width * height: img_array = np.array(pixel_list, dtype=np.uint16).reshape((height, width)) # RGB565转RGB888 r = ((img_array >> 11) & 0x1F) << 3 g = ((img_array >> 5) & 0x3F) << 2 b = (img_array & 0x1F) << 3 rgb_array = np.stack([r, g, b], axis=-1).astype(np.uint8) img = Image.fromarray(rgb_array) img.save("output.png") - 确认像素排列顺序:ESP32发送的是帧buffer的原始顺序,要和Python图像的行列顺序匹配(比如是否是从上到下、从左到右,有没有把行和列颠倒)
内容的提问来源于stack exchange,提问作者Gaston Melo
相关产品推荐
相关产品推荐

