如何通过插座传输 ESP32-Cam 拍摄的图像?
How do I transfer an image taken by ESP32-Cam over sockets?
我有一个 ESP32-Cam,我想将它拍摄的图像保存到我的桌面。最终目标是在Android应用程序中显示图像,但那是另一回事。 为了做到这一点,我认为我必须使用套接字传输图像。 下面的代码显示了我的示例代码。我有一个非常简单的python程序,它连接到WifiServer并打印client.write((正在编写的任何内容。
但是,我不确定我应该如何以这种方式传输图像。这可能吗?因为我必须传输图像缓冲区(在本例中为 fb->buf(对吗?
但是,一旦我收到缓冲区,例如在我的 python 代码中,我将如何从中制作图像?
如果有人能帮助我运行这个,那就太好了,因为我以前从未使用过这个(图像/套接字(。
电除尘器代码
#include "esp_camera.h"
#include "Arduino.h"
#include "WiFi.h"
// Pin definition for CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
// Variables
camera_fb_t * fb = NULL;
WiFiServer wifiServer(5005);
const char* ssid = "ssid";
const char* password = "password";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi.");
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("nConnected!");
Serial.println(WiFi.localIP());
wifiServer.begin();
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
if (psramFound()) {
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
// Init Camera
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
}
void loop() {
WiFiClient client = wifiServer.available();
if (client) {
fb = esp_camera_fb_get();
if(!fb) {
Serial.println("Camera capture failed");
return;
} else {
Serial.println("Camera capture succesfull!");
}
while (client.connected()) {
// How do I transfer the image? What do I have to do?
client.write(fb->buf);
}
client.stop();
Serial.println("Client disconnected");
}
}
蟒蛇代码
import socket
sock = socket.socket()
host = "192.168.178.103" # esp ip
port = 5005 # esp port
sock.connect((host, port))
data = sock.recv(256)
print(data)
sock.close()
这是对我有用的Arduino代码(从循环函数开始(
//=======================================================================
// Main Program Loop
//=======================================================================
void loop() {
WiFiClient client;
if (!client.connect(host, port)) {
Serial.println("Connection to host failed");
delay(1000);
return;
}
Serial.println("Connected to server successful!");
// capture camera frame
camera_fb_t *fb = esp_camera_fb_get();
if(!fb) {
Serial.println("Camera capture failed");
return;
} else {
Serial.println("Camera capture successful!");
}
const char *data = (const char *)fb->buf;
// Image metadata. Yes it should be cleaned up to use printf if the function is available
Serial.print("Size of image:");
Serial.println(fb->len);
Serial.print("Shape->width:");
Serial.print(fb->width);
Serial.print("height:");
Serial.println(fb->height);
client.print("Shape->width:");
client.print(fb->width);
client.print("height:");
client.println(fb->height);
// Give the server a chance to receive the information before sending an acknowledgement.
delay(1000);
getResponse(client);
Serial.print(data);
client.write(data, fb->len);
esp_camera_fb_return(fb);
Serial.println("Disconnecting...");
client.stop();
delay(2000);
}
void getResponse(WiFiClient client) {
byte buffer[8] = { NULL };
while (client.available() > 0 || buffer[0] == NULL) {
int len = client.available();
Serial.println("Len" + len);
if (len > 8) len = 8;
client.read(buffer, len);
if (printReceivedData) {
Serial.write(buffer, len); // show in the serial monitor (slows some boards)
Serial.println("");
}
}
}
用于接收图像的 python 代码
import io
import socket
import time
import numpy as np
from PIL import Image
import connection_and_network_constants
serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# address '0.0.0.0' or '' work to allow connections from other machines. 'localhost' disallows external connections.
# see https://www.raspberrypi.org/forums/viewtopic.php?t=62108
serv.bind(('0.0.0.0', connection_and_network_constants.SOCKET_PORT))
serv.listen(5)
print("Ready to accept 5 connections")
def create_image_from_bytes(image_bytes) -> Image.Image:
stream = io.BytesIO(image_bytes)
return Image.open(stream)
while True:
conn, addr = serv.accept()
array_from_client = bytearray()
shape = None
chunks_received = 0
start = time.time()
shape_string = ''
while True:
# print('waiting for data')
# Try 4096 if unsure what buffer size to use. Large transfer chunk sizes (which require large buffers) can cause corrupted results
data = conn.recv(connection_and_network_constants.BUFFER_SIZE)
if not data or data == b'tx_complete':
break
elif shape is None:
shape_string += data.decode("utf-8")
# Find the end of the line. An index other than -1 will be returned if the end has been found because
# it has been received
if shape_string.find('rn') != -1:
width_index = shape_string.find('width:')
height_index = shape_string.find('height:')
width = int(shape_string[width_index + len('width:'): height_index])
height = int(shape_string[height_index + len('height:'): ])
shape = (width, height)
print("shape is {}".format(shape))
else:
chunks_received += 1
# print(chunks_received)
array_from_client.extend(data)
# print(array_from_client)
conn.sendall(b'ack')
# print("sent acknowledgement")
# TODO: need to check if sending acknowledgement of the number of chunks and the total length of the array is a good idea
print("chunks_received {}. Number of bytes {}".format(chunks_received, len(array_from_client)))
img: Image.Image = create_image_from_bytes(array_from_client)
img.show()
array_start_time = time.time()
image_array = np.asarray(img)
print('array conversion took {} s'.format(time.time() - array_start_time))
conn.close()
print('client disconnected')
相关文章:
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 平均图像时图像损坏
- 在C++中使用GDAL可以将图像的像素坐标转换为lat,long吗
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- Vulkan验证层不断在VkQueuePresentKHR()上抛出图像布局错误
- 使用FFMPEG将RGB图像序列保存到.mp4时出现问题
- 将RGB图像保存为PPM格式
- 将图像添加到资源文件夹UWP C++
- 彩色图像的卤化物处理平均值
- C++射线示踪剂ppm表示没有足够的数据来显示图像
- 重新定位图像时如何前进到下一个内存块
- 如何使用按钮更新GTK3图像以使用C++从相机捕获图片
- 为什么 BMP 图像上的 imwrite 会卡住/不返回?
- Gstreamer:每 5 秒使用多文件墨水保存图像/jpeg
- 如何使用CImg打开图像?
- 如何通过插座传输 ESP32-Cam 拍摄的图像?
- 捕获图像从IP /以太网摄像机(AXIS Cam)