首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >简历:在SSH x11上显示太慢了。其他选择?

简历:在SSH x11上显示太慢了。其他选择?
EN

Stack Overflow用户
提问于 2019-09-10 18:45:49
回答 1查看 3.7K关注 0票数 1

我有一个应用程序处理实时帧从相机,然后喷出结果帧与imshow。在本地机器上运行时,所有操作都很顺利。

但是,我需要通过SSH调用这个应用程序,并以某种方式查看视频(不需要通过ssh)。目前,该应用程序只工作于X11转发,但是帧速率很差,并且存在很大的延迟。

是否有更好的方法来减少延迟和延迟?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-09-12 15:35:33

我尝试了几种方法来提高OpenCV的imshow()ssh连接上的性能。我使用一个Mac作为我的本地dekstop和一个覆盆子Pi4作为远程机器,我ssh进入并正在生成图像显示在我的Mac上。

禁用ssh连接上的压缩

我试着用:

代码语言:javascript
复制
ssh -o 'Compression no' pi4

这导致了大约6%-8%的吞吐量改善,因此很难做到这一点。

使用重量较轻的加密密码

我读到arcfour使用较少的资源,并允许您获得更高的吞吐量。不幸的是,我尝试过,而且它在Raspbian上是不可用的,似乎也没有任何其他轻量级密码。我使用这个命令来检查Raspberry Pi上可用的密码:

代码语言:javascript
复制
ssh -Q cipher

在X11隧道外运行ssh显示

由于未能找到提高ssh吞吐量的方法,我决定不加密地发送X11,而不是通过ssh隧道发送。这意味着我在Mac上运行了以下命令,允许X服务器侦听直接连接,并告诉它允许远程主机使用它:

代码语言:javascript
复制
defaults write org.macosforge.xquartz.X11 nolisten_tcp -bool false
xhost +

然后,我使用sshssh -Y进入Raspberry Pi 而不使用,然后运行:

代码语言:javascript
复制
export DISPLAY=<MAC_IP_ADDRESS>:0
./opencvScript

这导致了一些更好的表现,但它仍然不是突破性的。

然后,我决定使用Redis,这是一个非常高性能的内存数据结构服务器。在Mac或任何其他机器上安装都很简单。它允许您通过网络在任意数量的客户端之间共享原子整数、字符串、列表、散列、队列、集合和有序集。因此,我只是简单地JPEG编码和发送从Raspberry Pi到Redis的每一帧视频,然后尽可能快地在我的Mac上拾取这些帧并显示它们。它工作顺滑,做256帧640x480彩色视频在大约3秒,所以80 fps。

这是我在Mac上运行的DisplayServer。它只是尽可能快地抓取最新的图像并显示出来:

代码语言:javascript
复制
#!/usr/bin/env python3

import ImageTransferService
import numpy as np
import cv2

if __name__ == "__main__":

    host = '0.0.0.0'
    src = ImageTransferService.ImageTransferService(host)

    # Check Redis is running 
    print(src.ping())

    while True:
        im = src.receiveImage()
        cv2.imshow('Image',im)
        cv2.waitKey(1)

下面是我在发送图像的Raspberry Pi上运行的代码:

代码语言:javascript
复制
#!/usr/local/bin/python3

import numpy as np
import ImageTransferService

if __name__ == "__main__":

    host = '192.168.0.8'
    RemoteDisplay = ImageTransferService.ImageTransferService(host)

    # Check remote display is up
    print(RemoteDisplay.ping())

    # Create BGR image
    w, h = 640, 480
    im = np.zeros((h,w,3),dtype=np.uint8)

    for c in range(256):
        im[:,:,0] = c
        RemoteDisplay.sendImage(im)

下面是隐藏Redis并提供发送、接收和缓冲图像的方法的胶水代码:

代码语言:javascript
复制
#!/usr/bin/env python3

import redis
import cv2
import numpy as np

class ImageTransferService:
    def __init__(self, host='localhost', port=6379):
        self.port = port
        self.host = host
        self.conn = redis.Redis(host,port)
        self.frameNum = 0

    def ping(self):
        return self.conn.ping()

    def sendImage(self,im, name='latest', Q=75):
        _, JPEG = cv2.imencode(".JPG", im, [int(cv2.IMWRITE_JPEG_QUALITY), Q])
        myDict = { 'frameNum': self.frameNum, 'Data':JPEG.tobytes() }
        self.conn.hmset(name, myDict)
        self.frameNum += 1

    def receiveImage(self,name='latest'):
        myDict  = self.conn.hgetall(name)
        Data = myDict.get(b'Data')
        im = cv2.imdecode(np.frombuffer(Data,dtype=np.uint8), cv2.IMREAD_COLOR)
        return im

由于Redis有许多绑定,您可以访问数据帧,查看Redis,或者从PHP、Python、C/C++、PHP甚至命令行将内容写入Redis。因此,当在shell中运行时,下面的行将获取视频的最新帧,例如:

代码语言:javascript
复制
redis-cli hgetall latest

下面是代码的一个小视频,它简单地将蓝色通道从0增加到255,从而产生255帧。正如您所看到的,它在大约3s内从Raspberry Pi (在下终端窗口)到Mac (在运行DisplayServer代码的高端终端窗口中)。

我还做了一个使用套接字传输JPEG编码的图像的版本,这个版本速度几乎一样快,但有点丑陋,而且也不那么灵活,没有缓冲,也不像Redis那样可以从外部控制或调试。

关键词:覆盆子Pi,OpenCV,显示,远程显示,X11,隧道,ssh,显示,Redis,缓冲区,图像,图像处理,性能,XQuartz,侦听,传入,连接。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57876639

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档