【问题标题】:Stream continuous data from a python script to NodeJS将连续数据从 python 脚本流式传输到 NodeJS
【发布时间】:2020-10-18 17:05:38
【问题描述】:

我有一个多线程 python 脚本,可以将图像转换为 NumPy 数组(占用网格)。然后,python 脚本会不断更改数组的值以模拟地图中的点移动。使用 Pillow 将该数组转换回图像,然后编码为 base64。 NodeJS 部分有一个快速服务器正在运行,它也有一个与移动应用程序的 SocketIO 连接。

我想做的是: 将编码图像从服务器发送到移动应用程序,因此想到的选项是从 nodeJs 运行 python 脚本,并且当 python 脚本传输编码图像时,服务器会将其重定向到移动应用程序。

我正在寻找的是:

  • 将python脚本输出流式传输到nodeJS而不停止(直到模拟停止)
  • 或使用更好的解决方案将数据从 python 获取到手机

提前致谢!

要运行的python脚本:

import matplotlib.pyplot as plt
import cv2
import threading
import base64
from PIL import Image
temp = 0
global im_bw
pixel = 0

def update_image():
    global im_bw
    im2 = Image.fromarray(im_bw)
    image64 = base64.b64encode(im2.tobytes())
    # print the base64 encoded image to javascript
    print(image64)
    threading.Timer(1, update_image).start()

print("initialization")
im_gray = cv2.imread(r'gridMapBlue.JPG', cv2.IMREAD_GRAYSCALE)
(thresh, im_bw) = cv2.threshold(im_gray, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
thresh = 127
im_bw = cv2.threshold(im_gray, thresh, 255, cv2.THRESH_BINARY)[1]



# noinspection PyBroadException
try:
    update_image()
except Exception as e:
    print(e.with_traceback())
    pass

# simulate the dot moving by modifying the 
while True:
    if pixel == 200:
        break
    temp = im_bw[150,pixel]
    im_bw[150, pixel] = 127
    pixel += 1


Javascript 代码:

const express = require("express");
const app = express();
const io = require("./api/services/SocketIoService")
const spawn = require('child_process').spawn;


const socketIO = new io(app);
socketIO.server.listen(6969, () => console.log("server started"))


py = spawn('python',["E:\\QU\\Senior\\robot_positioning\\robot_position_map.py"])

py.stdout.on('data', (data)=>console.log(data));

py.stderr.on("error", err =>console.log(err))

image used

编辑:添加了创建占用网格的代码和我尝试过的javascript代码(但没有用)

【问题讨论】:

  • 棘手,您可以/应该从节点生成 python 进程,然后您可以使用child_process stdio 流。但我不确定客户端是否检测到图像已更改并重新渲染它
  • 我试图生成 python 进程,但是我遇到了几个问题,python 脚本在 PyCharm 上运行良好,但是从服务器运行它时,python 脚本会抛出错误
  • 你能为我添加一个简约的设置吗?听起来很有趣,我想尝试让它发挥作用
  • @Marc 我现在就添加它
  • @naif-mazan 您能否添加一个完整简约设置,包括。设置脚本/依赖项

标签: python node.js python-3.x socket.io


【解决方案1】:

如愿以偿,不是他想要的 100% 解决方案,而是一个可行的适应概念。

主文件是index.js:

const { spawn } = require("child_process");
const WebSocket = require("ws");

// create websocket server
// open "client.html" in a browser and see how the images flaps between two
const wss = new WebSocket.Server({
    port: 8080
});


// feedback
wss.on("connection", function connection(ws) {
    console.log("Client conneted to websocket");
});


// spawn python child process
const py = spawn("python", ["image.py"]);

console.log("Python image manipulating process has pid:", py.pid)

// listen for the new image
py.stdout.on("data", (data) => {

    // broadcast the new binary image to all clients
    wss.clients.forEach((client) => {
        if (client.readyState === WebSocket.OPEN) {
            client.send(data);
        }
    });

});


py.stderr.on("data", (data) => {
    console.error(data.toString());
});

这在图像处理image.py 和客户端之间进行通信(通过 WebSockets,如果需要,应该很容易将其更改为 socket.io):

import time
import sys

toogle = True

while True:

    if(toogle):
        f = open("image1.jpg", "r")
    else:
        f = open("image2.jpg", "r")

    toogle = not toogle

    sys.stdout.write(f.read())
    sys.stdout.flush()
    time.sleep(2)

该文件创建/操作图像并将图像二进制文件通过标准输出推送到父index.js。出于演示目的,我们在发送到客户端的 2 个图像之间切换:“image1.jpg”和“image2.jpg”(如果您还需要在 html 客户端中设置其他 mimetypes/extensions 主题,请使用您想要的任何 jpg 图像)。

作为客户,我使用了一个简单的 html 文档client.html: 当您打开文件时,它只显示一个白色/空白页面,因为没有初始加载图像。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <canvas id="image">unsupported browser</canvas>

    <script>
        var ws = new WebSocket('ws://localhost:8080');

        ws.onopen = () => {
            console.log("Connected")
        };

        ws.onmessage = (evt) => {

            // re-create(?) blob data from websocket
            var blob = new Blob([evt.data], {
                type: 'image/jpg' // -> MIME TYPES OF IMAGES GOES HERE
            });

            // create blob url
            var url = URL.createObjectURL(blob);

            var image = document.getElementById("image");
            var img = new Image(0, 0);

            img.onload = () => {

                // get canvas context
                let ctx = image.getContext("2d");

                ctx.clearRect(0, 0, image.width, image.height);
                ctx.drawImage(img, 0, 0);

            };

            img.src = url;

        };

    </script>

</body>

</html>

如果python脚本“这样说”,客户端会在页面上呈现接收到的图像缓冲区并刷新/重绘它。

安装唯一需要的依赖:npm install ws

要启动所有内容,请键入:node index.js 并在您选择的网络浏览器中打开客户端(在 ubuntu 18.04 LTS 上使用 firefox 测试)

您应该会看到图像每秒都在变化。通过该工作,您可以开始编写“动画”移动像素的 Python 脚本 :)

脚本在这里被内联编辑:也许它不是在第一次点击时运行的。 我通过“复制和粘贴”尝试并修复发现的问题(拼写错误、错误名称等)

如果您需要任何帮助或更改,请立即告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多