[Сделайте снимок Hololens в реальном времени и отправьте его на компьютер, чтобы получить его с помощью Python]

1. Введение

Среда разработки: Hololens2 + unity2020.3 +vs2019+python3.8.

Недавно я изучал, как обеспечить связь гололенов с компьютером.Изучив информацию, я обнаружил, что связь может быть достигнута с помощью Socket .

Разрешение хололенам взаимодействовать с компьютером на самом деле означает, что Unity может взаимодействовать с компьютером, а затем разрабатывать пользовательский интерфейс на стороне хололенов в соответствии с потребностями.
Процесс проекта примерно заключается в написании сценария C# на Unity для захвата и отправки изображений и использовании Python на компьютере для получения и сохранения изображений.
Что касается пользовательского интерфейса, создайте две кнопки Hololens для подключения двух методов: один управляет захватом фотографий, а другой — отправкой захваченных фотографий на сервер Python. Последующая работа заключается в использовании полученных изображений для обработки изображений и так далее.
Ниже приведено изображение проекта Unity.
Вставьте сюда описание изображения

2.Код проекта

Код клиента:

using UnityEngine;
using UnityEngine.UI;
using System.IO;
using System;
using System.Net.Sockets;
using System.Net;
using System.Collections.Generic;

using UnityEngine.Windows.WebCam;
using Microsoft.MixedReality.Toolkit.UI;




public class CaptureAndSend : MonoBehaviour
{
    
    

    // Hololens摄像头对象
    PhotoCapture photoCaptureObject = null;
    // 捕获的图片对象
    Texture2D targetTexture = null;
    // 图片的宽和高
    int width = 1280;
    int height = 720;

    // 用于控制图片捕获和发送的按钮
    public Interactable CaptureButton;
    public Interactable SendButton;
    // 服务器IP地址和端口号
    string serverIP = "172.22.90.152";
    int serverPort = 8888;
    private TcpClient client;

    // 图片数据的字节数组
    byte[] imageBytes = null;

    void Start()
    {
    
    
        client = new TcpClient(serverIP, serverPort);
        // 获取按钮组件并添加点击事件
        CaptureButton.OnClick.AddListener(CaptureImage);
        SendButton.OnClick.AddListener(SendImage);
    }

    void OnDestroy()
    {
    
    
        // 释放摄像头资源
        if (photoCaptureObject != null)
        {
    
    
            photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
            photoCaptureObject.Dispose();
            photoCaptureObject = null;
        }
    }

    void CaptureImage()
    {
    
    
        // 初始化PhotoCapture对象并设置参数
        PhotoCapture.CreateAsync(true, OnPhotoCaptureCreated);
    }

    
    void SendImage()
    {
    
    
        if (imageBytes != null)
        {
    
    
            try
            {
    
    
                // 创建TcpClient连接服务器
                

                // 获取网络流并发送图片数据
                NetworkStream stream = client.GetStream();
                stream.Write(imageBytes, 0, imageBytes.Length);
                Debug.Log("Image sent to server.");
                // 关闭网络流和TcpClient连接
                stream.Close();
                client.Close();
            }
            catch (Exception e)
            {
    
    
                Debug.Log(e.ToString());
            }
        }
        else
        {
    
    
            Debug.Log("imageBytes变量为空");
        }
    }
    

    void OnPhotoCaptureCreated(PhotoCapture captureObject)
    {
    
    
        // 将PhotoCapture对象赋值给成员变量
        photoCaptureObject = captureObject;
        // 创建CameraParameters对象
        CameraParameters camParameters = new CameraParameters();
        camParameters.hologramOpacity = 0.0f;
        camParameters.cameraResolutionWidth = width;
        camParameters.cameraResolutionHeight = height;
        camParameters.pixelFormat = CapturePixelFormat.PNG;
        // 捕获图片并保存到Texture2D对象中
        captureObject.StartPhotoModeAsync(camParameters, OnPhotoModeStarted);
    }

    void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
    {
    
    
        if (result.success)
        {
    
    
            targetTexture = new Texture2D(width, height, TextureFormat.RGB24, false);
            // 拍摄图像并保存到Texture2D对象中
            photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
        }
        else
        {
    
    
            Debug.LogError("Unable to start photo mode!");
        }
    }

    void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
    {
    
    
        if (result.success)
        {
    
    
            // 将图片数据转换为字节数组
            imageBytes = ConvertToByteArray(photoCaptureFrame);
            // 将图片数据显示到屏幕上
            targetTexture.LoadImage(imageBytes);
            //GetComponent<Renderer>().material.mainTexture = targetTexture;
            Debug.Log("Image captured.");
            
            
        }
        else
        {
    
    
            Debug.LogError("Failed to capture photo.");
        }
        // 停止PhotoCapture模式并释放资源
        photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
    }

    void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
    {
    
    
        // 释放PhotoCapture资源
        photoCaptureObject.Dispose();
        photoCaptureObject = null;
    }

    byte[] ConvertToByteArray(PhotoCaptureFrame photoCaptureFrame)
    {
    
    
        // 获取图像数据缓冲区
        List<byte> buffer = new List<byte>();
        photoCaptureFrame.CopyRawImageDataIntoBuffer(buffer);
        // 将List<byte>转换为byte[]
        byte[] bytes = buffer.ToArray();
        return bytes;
    }
    




}


Код на стороне сервера:

import socket
import cv2
import numpy as np
import os
from datetime import datetime

# 创建socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 获取本地主机名
host = '172.22.90.152'

# 设置一个端口
port = 8888

# 绑定端口号
server_socket.bind((host, port))

# 设置最大连接数,超过后排队
server_socket.listen(5)

print('等待客户端连接...')

# 接受客户端连接
client_socket, address = server_socket.accept()

print('连接地址:', address)

# 接收图片数据
data = b''
while True:
    packet = client_socket.recv(4096)
    if not packet:
        break
    data += packet

# 将接收到的字节数据转换为OpenCV格式的图片
img_data = np.frombuffer(data, dtype=np.uint8)

img = cv2.imdecode(img_data, cv2.IMREAD_COLOR)
print(img_data)
print('Received image size:', img.shape)


# 在窗口中显示接收到的图片
cv2.imshow('Received Image', img)

print("开始保存文件")
# 将接收到的图片保存到指定文件夹中
save_folder = './received_images'
if not os.path.exists(save_folder):
    os.makedirs(save_folder)
print("创建文件夹")
current_time = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
filename = os.path.join(save_folder, f'received_image_{current_time}.jpg')
cv2.imwrite(filename, img)

print(f'Saved received image to {filename}')
cv2.waitKey()
# 关闭连接
client_socket.close()
server_socket.close()

3. Процесс разработки

3.1 Клиент

Создайте проект Unity, преобразуйте его в платформу UWP , импортируйте в проект набор инструментов MRTK и добавьте сцену MR по умолчанию.
Вставьте сюда описание изображенияИмпортируйте XR Plug-in Management , создайте файл сценария C# в соответствии с приведенными ниже настройками
Вставьте сюда описание изображения
и скопируйте в него приведенный выше клиентский код. Строка serverIP в коде может быть установлена ​​на IP-адрес компьютера в той же локальной сети . При отладке в Unity сначала можно установить значение 127.0.0.1.
Создайте пустой узел с именем HololensCamera, чтобы смонтировать только что созданный скрипт.

Затем свяжите со сценарием две кнопки.

Откройте панель инструментов. В ней много кнопок Hololens. Я выбрал первую в разделе NearMenus. Вы
Вставьте сюда описание изображения
Вставьте сюда описание изображения
можете переименовать строку меню кнопок в Menu. Под узлом ButtonCollection находятся три кнопки. Поскольку используются только две кнопки, я удалил одну. Вы можете переименовать эти два узла кнопок в «Захват» и «Отправить», чтобы облегчить различие.

Значок можно установить в инспекторе кнопок, а отображаемый текст можно установить в IconAndText.
Вставьте сюда описание изображения
Перетащите две кнопки на две необходимые ссылки на кнопки сценария установки пустого узла.
Вставьте сюда описание изображения
Таким образом, будет создан единый проект.

3.2 Серверная часть

Создайте проект в pycharm, скопируйте в него код Python и импортируйте необходимые пакеты. IP-адрес также должен быть установлен на IP-адрес вашего собственного компьютера. Если вы отлаживаете этот компьютер, вы можете сначала установить номер порта 127.0.0.1 и синхронизировать его с C#.

4. Отладка

Сначала запустите код на стороне сервера, а затем запустите unity, чтобы запустить игровой режим. В это время в рабочем окне на стороне сервера будет выводиться информация о подсказке для подключения клиента. В Unity сначала нажмите кнопку захвата, а затем кнопку отправки. В это время компьютер получит изображение и сохранит его в папке полученное_изображение в той же папке проекта Python.
Если при отладке в Unity проблем не возникло, разверните его в Hololens.
Запустите сервер, откройте программу голо, нажмите кнопку захвата, а затем отправьте его, чтобы посмотреть, сохранилась ли картинка в папке.

Guess you like

Origin blog.csdn.net/weixin_44338714/article/details/130151205