You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从海康威视摄像头事件流中正确解码图片数据?

解决海康威视事件流图片数据无法转换为可识别图像的问题

问题根源分析

你现有代码的核心问题出在multipart流的处理方式和图片数据截取逻辑上:

  1. 使用iter_lines()处理二进制图片流:JPG文件本身包含大量换行符对应的字节(0x0A),iter_lines()会按换行分割数据并默认去掉换行符,导致拼接后的图片字节结构被破坏。
  2. 图片截取逻辑错误:你写的b+8完全错误,JPG的结束标记\xff\xd9是2字节,应该用b+2,多截取的垃圾数据会直接导致PIL无法识别。
  3. 未正确跳过multipart头部:收集图片数据时可能混入了Content-Type等头部文本内容,污染了原始图片二进制。

修正后的代码实现

改用二进制数据流直接处理multipart分隔,精准提取图片和事件数据:

import requests
from requests.auth import HTTPDigestAuth
import re
from PIL import Image
from io import BytesIO

# 初始化请求
url = "你的事件流URL"
auth = HTTPDigestAuth("用户名", "密码")
headers = {"Accept": "multipart/mixed"}

with requests.get(url, auth=auth, headers=headers, stream=True) as response:
    # 从响应头获取multipart边界符
    content_type = response.headers.get("Content-Type")
    match = re.search(r'boundary=(.*)', content_type)
    if not match:
        raise ValueError("响应头中未找到multipart边界符")
    boundary = match.group(1).strip()
    delimiter = b'--' + boundary.encode('utf-8')

    buffer = b''
    in_image = False

    for chunk in response.iter_content(chunk_size=1024):
        if not chunk:
            continue
        buffer += chunk

        # 循环处理所有已接收到的multipart部分
        while delimiter in buffer:
            part, buffer = buffer.split(delimiter, 1)

            if in_image:
                # 提取图片数据:跳过头部的\r\n\r\n,去掉尾部的换行符
                header_end = part.find(b'\r\n\r\n')
                if header_end != -1:
                    image_data = part[header_end+4:].rstrip(b'\r\n')
                    # 保存并验证图片
                    with open("captured.jpg", "wb") as f:
                        f.write(image_data)
                    try:
                        img = Image.open(BytesIO(image_data))
                        img.verify()
                        print("图片解析成功")
                    except Exception as e:
                        print(f"图片解析失败: {str(e)}")
                in_image = False
            else:
                # 解析事件通知或判断是否进入图片部分
                part_str = part.decode('utf-8', errors='ignore')
                if 'Content-Type: image/jpeg' in part_str:
                    in_image = True
                elif '<EventNotificationAlert' in part_str:
                    # 提取ANPR事件XML
                    xml_start = part_str.find('<EventNotificationAlert')
                    xml_end = part_str.find('</EventNotificationAlert>') + len('</EventNotificationAlert>')
                    if xml_start != -1 and xml_end != -1:
                        notification_alert = part_str[xml_start:xml_end]
                        event_type = re.search(r'<eventType>(.*?)</eventType>', notification_alert).group(1)
                        if event_type == 'ANPR':
                            with open('test.xml', 'a') as f:
                                f.write(notification_alert + '\n')
                        else:
                            print('非ANPR事件')

关键改进点

  • 用iter_content()直接处理二进制流,避免破坏JPG的字节结构。
  • 从响应头自动提取multipart边界符,精准分割每个数据部分。
  • 严格区分multipart的头部和内容,确保只提取纯图片二进制数据。
  • 验证图片完整性,确保提取的数据是合法的JPG文件。

内容的提问来源于stack exchange,提问作者Danish Ajaib

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 03:16:08