python图形差分传输实现windows桌面监视

python图形差分传输实现windows桌面监视

图像的差分传输(Differential Transmission of Images)是指通过传输图像的差分信息而不是原始图像数据来实现更高效的数据传输。这种方法在图像压缩和传输中非常有用,因为它可以显著减少需要传输的数据量,从而提高传输效率和速度。

以下是图像差分传输的基本原理和步骤:

  1. 当前图像和参考图像:在差分传输中,通常会有一个参考图像(可能是之前传输过的图像或接收方已经拥有的图像)和一个需要传输的当前图像。参考图像和当前图像之间可能存在一定的差异。
  2. 计算差分图像:差分传输的核心是计算当前图像和参考图像之间的差异,即差分图像。差分图像的每个像素值表示当前图像和参考图像对应像素值的差异。例如,如果当前图像的像素值为A,参考图像的像素值为B,那么差分图像的像素值就是A - B。
  3. 传输差分数据:将压缩后的差分图像数据通过网络传输到接收端。由于差分图像的数据量较小,这一步通常比传输完整的原始图像更高效。
  4. 重建图像:接收端接收到差分图像后,会利用参考图像和差分图像重建出当前图像。重建过程是将参考图像和差分图像进行逆操作,即对每个像素值进行相加(如果差分图像的像素值为A - B,那么重建时的操作是B + (A - B) = A)。

远程桌面监控效果展示

当前图像和参考图像

在图形差分传输下,参考图像通常是上一帧图,当前图像是当前帧图,以下给出两张图用作案例演示:

在这里插入图片描述 在这里插入图片描述
上一帧 当前帧

计算差分图像

使用Python计算差分图像可以通过一些图像处理库来实现,例如OpenCV或Pillow。以下是使用OpenCV实现差分图像计算的一个简单示例,将上述两个图像进行比较,并标记差异区域:

  • 注意
    1. 当图像文件路径存在中文时,使用cv2.imreadcv2.imwrite读取和保存图像时会报错,需要使用cv2.imdecodecv2.imencode替换
    2. OpenCV进行差异比较时需要先将图像转换成灰度图像
    3. 通过cv2.threshold修改差异阈值可以提高差异识别灵敏度,以找到更细微的差异,或者降低灵敏度,以提高执行效率
    4. 使用pyautogui获取当前屏幕分辨率,根据比例使用cv2.resize调整展示的图像尺寸
import cv2
import numpy as np
import pyautogui

with 
open(
    r"D:/图像传输/prev.png", "rb"
) as prev, 
open(
    r"D:/图像传输/current.png", "rb"
) as current:

    # 加载上一帧图
    previous_frame = cv2.imdecode(
        np.frombuffer(prev.read(), np.uint8), cv2.IMREAD_GRAYSCALE
    )

    # 加载当前帧图
    current_frame = cv2.imdecode(
        np.frombuffer(current.read(), np.uint8), cv2.IMREAD_GRAYSCALE
    )

    # 计算两帧之间的差异
    diff = cv2.absdiff(current_frame, previous_frame)

    # 设置差异阈值
    _, thresholded_diff = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY)

    # 找到变化区域的轮廓
    contours, _ = cv2.findContours(
        thresholded_diff, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
    )

    # 在当前帧上标记变化区域
    marked_image = cv2.cvtColor(current_frame, cv2.COLOR_GRAY2BGR)
    for contour in contours:
        x, y, w, h = cv2.boundingRect(contour)
        cv2.rectangle(marked_image, (x, y), (x + w, y + h), (0, 255, 0), 2)

    # 保存结果
    cv2.imencode(".png", marked_image)[1].tofile(
        r"D:/图像传输/comp.png"
    )

    # 显示结果
    screen_width, screen_height = pyautogui.size()
    scale = screen_height / marked_image.shape[0] - 0.1
    marked_image = cv2.resize(marked_image, None, fx=scale, fy=scale)
    cv2.imshow("Marked Image", marked_image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
  • 结果图
    在这里插入图片描述

传输差分数据

由上节可知,差分数据存储在contours中,但是我们不需要将这个对象的全部数据传输过去,我们只需要传输差异图像、图像尺寸以及图像的坐标信息就可以支持后续的重建。

  • 本节需要注意的点:
    1. 要传输原图数据,而不是差分计算用到的灰度图像。因此需要使用差分数据对原图进行切片,代码片段如下:
    for contour in contours:
            x, y, w, h = cv2.boundingRect(contour)
            # 原图切片
            slice = original[y : y + h, x : x + w]
    
    1. 当存在多个差异点时,将差异数据合并传输,可以提高传输效率。但是合并传输需要规定数据包的结构和格式,本例使用以下规定:
    包结构:{<信息头><图像描述><图像内容>}
    信息头:{<身份标识><切片数量>}
    身份标识:16字节
    切片数量:4字节,0则表示替换整个图像,>=0则差分更新上一帧
    图像描述:{<切片信息><切片信息>...}
    切片信息:{<切片大小><切片高度><切片宽度><X轴坐标><Y轴坐标>}
    切片大小:4字节,int
    切片高度:4字节,int
    切片宽度:4字节,int
    X轴坐标:4字节,int
    Y轴坐标:4字节,int
    图像内容:切片有序排列组合,大小=所有切片大小之和
    
    1. 参考上述规定,差分数据的发送代码段如下:
    # 发送变化区域图像数据
    body = b""
    header = b""
    desc = b""
    # 添加切片数量
    header = id.bytes + len(contours).to_bytes(4, byteorder="big")
    for contour in contours:
        x, y, w, h = cv2.boundingRect(contour)
        # 原图切片
        slice = mat[y : y + h, x : x + w]
        # 将切片图像转换为字节流
        _, slice_encoded = cv2.imencode(".png", slice)
        slice_bytes = slice_encoded.tobytes()
        # 图像大小、尺寸、位置信息
        size = len(slice_bytes)
        slice_info = (
            size.to_bytes(4, byteorder="big")
            + h.to_bytes(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值