Отправьте изображение по UDP в Unreal Engine и загрузите его туда

Я хочу отправить изображения по UDP из сценария Python в Unreal, загрузить их туда и на следующем этапе создать из них текстуру. В настоящее время я изо всех сил пытаюсь получить изображение.

Вот мой простой udp-скрипт на Python:

import cv2, imutils, socket
import numpy as np
import time
import base64

BUFF_SIZE = 65536
server_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF,BUFF_SIZE)
host_name = socket.gethostname()
host_ip = '127.0.0.1'#  socket.gethostbyname(host_name)
print(host_ip)
port = 54001
socket_address = (host_ip,port)
server_socket.bind(socket_address)
print('Listening at:',socket_address)

vid = cv2.VideoCapture(0) #  replace 'rocket.mp4' with 0 for webcam
fps,st,frames_to_count,cnt = (0,0,20,0)

while True:
    msg,client_addr = server_socket.recvfrom(BUFF_SIZE)
    print('GOT connection from ',client_addr)
    WIDTH=400
    while(vid.isOpened()):
        _,frame = vid.read()
        frame = imutils.resize(frame,width=WIDTH)
        encoded,buffer = cv2.imencode('.jpg',frame,[cv2.IMWRITE_JPEG_QUALITY,80])
        #message = base64.b64encode(buffer)
        server_socket.sendto(bytes(buffer),client_addr)
        frame = cv2.putText(frame,'FPS: '+str(fps),(10,40),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)
        cv2.imshow('TRANSMITTING VIDEO',frame)
        key = cv2.waitKey(1) & 0xFF
        if key == ord('q'):
            server_socket.close()
            break
        if cnt == frames_to_count:
            try:
                fps = round(frames_to_count/(time.time()-st))
                st=time.time()
                cnt=0
            except:
                pass
        cnt+=1

Поэтому я отправляю его как массив base64. Как мне загрузить его в Unreal? Я создал простой файл udp .cpp и .h со всем необходимым для запуска UDP-сокета:

void Audp_module::BeginPlay()
{
    Super::BeginPlay();
    SocketSubsystem = nullptr;
    if (SocketSubsystem == nullptr) SocketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM);

    SendSize = 2 * 1024 * 1024;
    BufferSize = 2 * 1024 * 1024;
    FIPv4Address iPAdress;
    FIPv4Address::Parse("127.0.0.1",iPAdress);
    LocalEndpoint = FIPv4Endpoint(iPAdress, LocalPort);

    FIPv4Address::Parse(IP, RemoteAddress);
    RemoteEndpoint = FIPv4Endpoint(RemoteAddress, RemotePort);

    Socket = nullptr;

    if (SocketSubsystem != nullptr)
    {
        if (Socket == nullptr)
        {
            Socket = FUdpSocketBuilder(SocketDescription)
                .AsNonBlocking()
                .AsReusable()
                .BoundToEndpoint(LocalEndpoint)
                .WithReceiveBufferSize(SendSize)
                .WithReceiveBufferSize(BufferSize)
                .WithBroadcast();
        }
    }
}

void Audp_module::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
    Super::EndPlay(EndPlayReason);
    SocketSubsystem->DestroySocket(Socket);
    Socket = nullptr;
    SocketSubsystem = nullptr;
}

void Audp_module::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    FString t = "Hello";
    sendMessage(t); // Send Message Test
    Listen(); // Listen for messages

    
}

void Audp_module::Listen()
{
    TSharedRef<FInternetAddr> targetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
    uint32 Size;
    if (Socket != nullptr)
    {
        while (Socket->HasPendingData(Size))
        {
            uint8* Recv = new uint8[Size];
            int32 BytesRead = 0;

            ReceivedData.SetNumUninitialized(FMath::Min(Size, 65507u));
            Recv = ReceivedData.GetData();
            Socket->RecvFrom(ReceivedData.GetData(), ReceivedData.Num(), BytesRead, *targetAddr);
            
            char ansiiData[1024];
            memcpy(ansiiData, ReceivedData.GetData(), BytesRead);
            ansiiData[BytesRead] = 0;
            
            FString data = ANSI_TO_TCHAR(ansiiData);
            //FString data = FString::FromInt(BytesRead);
            const auto encoded = FBase64::Encode(*data);
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, encoded);
            UE_LOG(LogTemp, Verbose, TEXT("Received: %s"), *encoded);
            //FString data = ANSI_TO_TCHAR(ansiiData);
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "Message by UDP: " + data);
        }
    }
    else
    {
        Socket = FUdpSocketBuilder(SocketDescription)
                .AsNonBlocking()
                .AsReusable()
                .BoundToEndpoint(LocalEndpoint)
                .WithReceiveBufferSize(SendSize)
                .WithReceiveBufferSize(BufferSize)
                .WithBroadcast();
    }
    
}

Часть после ansiiData не работает, и я предполагаю, что мне нужно выполнить преобразование полученных данных в base64 по-другому? Мой план был сделать что-то вроде описанного здесь

Как я могу это сделать?

К вашему сведению: UDP имеет максимальный размер пакета ~ 64 КБ. Также нет гарантии заказа и доставки. Также нет необходимости кодировать b64… буфер можно было бы отправить напрямую, если бы он не был слишком большим.

Mark Tolonen 07.03.2024 17:13

Примечание: не выделяйте хранилище, пока не поймете, что оно вам нужно. uint8* Recv = new uint8[Size]; выделяет массив, который теряется, когда Recv = ReceivedData.GetData(); указывает Recv на другое место. Похоже, что Recv после этого больше никогда не используется, поэтому, скорее всего, вы можете полностью удалить его.

user4581301 07.03.2024 20:22

UDP имеет максимальный размер полезной нагрузки 65507 и максимальный практический размер 534. Вероятно, это не будет работать, что бы вы ни исправили.

user207421 29.05.2024 00:37
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
3
209
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Возможно ли, что ansiiData слишком мал? Может быть, подогнать его по размеру вместо жесткого кодирования.

char ansiiData[BytesRead + 1];
memcpy(ansiiData, ReceivedData.GetData(), BytesRead);
ansiiData[BytesRead] = 0;

В этом и была проблема, спасибо! Теперь мне нужно найти способ преобразовать его обратно в изображение, а затем в текстуру в Unreal :)

potu1304 11.03.2024 08:21

Другие вопросы по теме

Похожие вопросы