开发环境:Ubuntu16.04
ESP32:Arduino
PC图传:Python3.6.9
首先上python代码
import socket
import cv2
import numpy as np
img = cv2.imread('./picture.jpg') #读取图像
# 检测图片的象素大小
sp = img.shape
print(sp[0], sp[1], sp[2]) # sp[0] height sp[1] width
height = img.shape[0]
width = img.shape[1]
if (sp[0] != 128)&(sp[1] != 128):
img = cv2.resize(img, (int(128), int(128))) # 修改象素大小为128*128
# cv2.imshow("pic", img)
print(img.shape)
image_arr = [0 for i in range(128*128)]
image_R = [0 for i in range(128*128)]
image_G = [0 for i in range(128*128)]
image_B = [0 for i in range(128*128)]
# print(img[0][0]) # 顺序是BGR ,img[y][x]
# 取模,RGB888 变为 RGB565 RGB都取高位
for i in range(128):
for j in range(128):
image_R[i * 128 + j] = img[i][j][2] >> 3
image_G[i * 128 + j] = img[i][j][1] >> 2
image_B[i * 128 + j] = img[i][j][0] >> 3
for i in range(128*128):
image_arr[i] = (image_R[i] << 11) | (image_G[i] << 5) | (image_B[i])
# 创建socket对象
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # AF_INET ipv4协议 SOCK_DGRAM udp模式
host = socket.gethostname() # 获取本地计算机名
ip = '192.168.2.109'
port = 9000 # 设置端口号
s.bind((ip, port)) # 绑定本地ip和端口
print("udp配置完成")
print("udp ip ", ip, " port", port)
value = 1
for i in range(128*128):
s.sendto(int(image_arr[i]).to_bytes(2, 'big'), ('192.168.2.105', 9000))
print(int(image_arr[i]).to_bytes(2, 'big'))
while True:
data = s.recv(1024)
if data == value.to_bytes(1,'big'):
break
s.close()
该Python代码的主要功能就是把图片改为128*128大小的565象素格式的图片,能进行UDP通讯,本人是Python小白,有些地方我感觉可以在改进的,尤其是通过udp,每一次只能传送两个字节。下面的代码由于PC发送的太快导致ESP32接收不过来,所以我采用应答的方式保证每个象素点的值能被ESP32接收。如果能改善的话,我感觉可以实现视频传输了。
注:
在888象素格式转化565格式的时候,一定要注意,是用RGB高5位和高6位
在python opencv中读出的图像数组顺序是BGR!!
下面是esp32代码
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#define TFT_CS 5
#define TFT_RST 16
#define TFT_DC 17
#define TFT_SCLK 18
#define TFT_MOSI 23
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
float p = 3.1415926;
// WiFi network name and password:
const char * networkName = "xxxxx";
const char * networkPswd = "xxxxx";
const char * udpAddress = "192.168.2.109";
const int udpPort = 9000;
//Are we currently connected?
boolean connected = false;
//The udp library class
WiFiUDP udp;
uint8_t frame[128];
uint8_t udp_frame[32768];
uint16_t image_frame[16384];
int framesize = 0;
int size = 0;
uint8_t response[2] = {1,2};
void draw_picture(uint16_t* buff)
{
int i =0;
int j = 0;
for(i=0;i<128;i++)
for(j=0;j<128;j++)
tft.drawPixel(j,i,buff[j+128*i]);
}
void connectToWiFi(const char * ssid, const char * pwd){
Serial.println("Connecting to WiFi network: " + String(ssid));
// delete old config
WiFi.disconnect(true);
//register event handler
WiFi.onEvent(WiFiEvent);
//Initiate connection
WiFi.begin(ssid, pwd);
Serial.println("Waiting for WIFI connection...");
}
//wifi event handler
void WiFiEvent(WiFiEvent_t event){
switch(event) {
case SYSTEM_EVENT_STA_GOT_IP:
//When connected set
Serial.print("WiFi connected! IP address: ");
Serial.println(WiFi.localIP());
//initializes the UDP state
//This initializes the transfer buffer
udp.begin(WiFi.localIP(),udpPort);
connected = true;
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
Serial.println("WiFi lost connection");
connected = false;
break;
default: break;
}
}
void setup(){
Serial.begin(115200);
tft.initR(INITR_144GREENTAB); // initialize a ST7735S chip, black tab
//Connect to the WiFi network
connectToWiFi(networkName, networkPswd);
}
void loop(){
int i = 0;
if(connected){
int num = udp.parsePacket();
if(udp.read(frame,128)){
for(i=0;i<num;i++){
udp_frame[i+framesize] = frame[i];
}
framesize += 2;
udp.beginPacket(udpAddress,udpPort);
udp.write(response,1);
udp.endPacket();
}
else if(framesize == 32768)
{
for(i=0;i<32768;i++)
{
image_frame[size] = (udp_frame[i]<<8) | (udp_frame[i+1]);
Serial.println(image_frame[size]);
size++;
i++;
}
draw_picture(image_frame);
framesize = 0;
size = 0;
}
}
}
最后展示一下结果:
使用的话代码直接用,把任意一个大于128×128的图片放在Python工程,设置好端口和ip就可以实现了。