海康 MV 相机几种Bayer RG像素格式的处理

海康 MV 相机输出的像素格式为以下几种:

Bayer RG8 格式数据的解析见:

https://blog.csdn.net/xulibo5828/article/details/148781170


一、Bayer RG10 数据格式解析

1. 核心概念
  • Bayer 格式:工业相机常用的原始图像格式,像素按特定规律排列(RG10 表示排列顺序为 R-G/B-G,即第一行是 R、G、R、G...,第二行是 G、B、G、B...)。
  • RG10
    • RG:Bayer 排列方式(也叫 BGGR 的镜像,核心是 R/G/B 的位置);
    • 10:每个像素占10 位(bit),而常规的 8 位图像(RGB8)每个像素占 8 位,因此 RG10 需要先做位深转换。
  • 数据存储 :RG10 数据通常以16 位无符号整数(uint16) 存储(因为 10 位无法用 8 位存储),有效数据是低 10 位,高 6 位为 0,取值范围是 0~1023(2^10-1)。
2. 数据结构

假设相机输出分辨率为 width × height

  • RG10 原始数据总字节数 = width × height × 2(每个 uint16 占 2 字节);

  • 像素排列示例(RG10):

    R(10bit) G(10bit) R(10bit) G(10bit) ...
    G(10bit) B(10bit) G(10bit) B(10bit) ...
    R(10bit) G(10bit) R(10bit) G(10bit) ...
3. OpenCV 转换为 RGB8 :
复制代码
import cv2
import numpy as np

def rg10_to_rgb8(rg10_data: bytes, width: int, height: int) -> np.ndarray:
    """
    将海康MV相机的Bayer RG10数据转换为RGB8格式图像
    :param rg10_data: 相机输出的RG10原始字节数据
    :param width: 图像宽度(像素)
    :param height: 图像高度(像素)
    :return: RGB8格式的numpy数组(uint8)
    """
    # 步骤1:将字节数据转换为uint16数组(RG10原始数据)
    # 注意:海康相机RG10数据通常为小端存储(little-endian)
    rg10_array = np.frombuffer(rg10_data, dtype=np.uint16).reshape(height, width)
    
    # 步骤2:10位数据归一化到8位(0~1023 → 0~255)
    # 方法:除以 4(1023/4≈255.75,取整后为0~255),或使用cv2.normalize
    rg8_array = (rg10_array // 4).astype(np.uint8)
    
    # 步骤3:Bayer RG10(对应OpenCV的BAYER_RGGB格式)转RGB8
    # OpenCV的cvtColor支持直接转换Bayer格式,注意匹配排列方式:
    # RG10的排列 = BAYER_RGGB → 对应cv2.COLOR_BAYER_RG2RGB
    rgb8_image = cv2.cvtColor(rg8_array, cv2.COLOR_BAYER_RG2RGB)
    
    return rgb8_image

# ------------------- 测试示例 -------------------
if __name__ == "__main__":
    # 模拟获取海康相机RG10数据(实际使用时替换为相机SDK读取的数据)
    # 假设图像分辨率为1920×1080,生成随机RG10测试数据
    width, height = 1920, 1080
    test_rg10_data = np.random.randint(0, 1024, size=height*width, dtype=np.uint16).tobytes()
    
    # 转换为RGB8
    rgb_image = rg10_to_rgb8(test_rg10_data, width, height)
    
    # 验证结果
    print(f"RGB图像形状: {rgb_image.shape}")  # 输出 (1080, 1920, 3)
    print(f"数据类型: {rgb_image.dtype}")     # 输出 uint8
    
    # 显示图像(可选)
    cv2.imshow("RGB8 Image", rgb_image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    # 保存图像(可选)
    cv2.imwrite("rgb8_output.jpg", rgb_image)
4. 关键细节说明
  • Bayer 格式匹配 :海康 RG10 对应的是 OpenCV 的COLOR_BAYER_RG2RGB,如果转换后颜色异常,可尝试:

    • cv2.COLOR_BAYER_BG2RGB(BGGR 排列);
    • cv2.COLOR_BAYER_GR2RGB(GRBG 排列);
    • cv2.COLOR_BAYER_GB2RGB(GBRG 排列)。
  • 位深转换优化 :如果需要更精准的归一化,可替换步骤 2 为:

    复制代码
    rg8_array = cv2.normalize(rg10_array, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)
5. RG10 处理的常见问题与解决方案
1). 位深转换的两种正确方式

除了之前的//4,还有更精准的归一化方式,适合对画质要求高的场景:

复制代码
# 方式1:整数运算(速度快,无精度损失)
rg8_array = (rg10_array >> 2).astype(np.uint8)  # 右移2位 ≈ 除以4,等价于//4

# 方式2:浮点归一化(更精准,适合动态范围要求高的场景)
rg8_array = np.clip((rg10_array / 1023) * 255, 0, 255).astype(np.uint8)
2). 海康相机 RG10 的端序问题

海康 MV 相机的 RG10 数据默认是小端(little-endian) 存储,若直接用np.frombuffer解析异常,需显式指定端序:

复制代码
# 显式指定小端解析(兼容不同相机配置)
rg10_array = np.frombuffer(
    rg10_data, 
    dtype=np.dtype('<u2')  # < 表示小端,u2表示uint16
).reshape(height, width)
3). 实战:从海康 MVS SDK 读取 RG10 并验证

用海康官方 MVS SDK,读取 RG10 的真实代码片段(基于 C++/Python 封装):

复制代码
import cv2
import numpy as np
from MvImport.MvCameraControl_class import *


def decoding_char(c_ubyte_value):
    c_char_p_value = ctypes.cast(c_ubyte_value, ctypes.c_char_p)
    try:
        decode_str = c_char_p_value.value.decode('gbk')  # Chinese characters
    except UnicodeDecodeError:
        decode_str = str(c_char_p_value.value)
    return decode_str

# 转为16进制字符串
def To_hex_str(num):
    chaDic = {10: 'a', 11: 'b', 12: 'c', 13: 'd', 14: 'e', 15: 'f'}
    hexStr = ""
    if num < 0:
        num = num + 2 ** 32
    while num >= 16:
        digit = num % 16
        hexStr = chaDic.get(digit, str(digit)) + hexStr
        num //= 16
    hexStr = chaDic.get(num, str(num)) + hexStr
    return hexStr

def rg10_to_rgb8(rg10_data: bytes, width: int, height: int) -> np.ndarray:
    """
    将海康MV相机的Bayer RG10数据转换为RGB8格式图像
    :param rg10_data: 相机输出的RG10原始字节数据
    :param width: 图像宽度(像素)
    :param height: 图像高度(像素)
    :return: RGB8格式的numpy数组(uint8)
    """
    # 步骤1:将字节数据转换为uint16数组(RG10原始数据)
    # 注意:海康相机RG10数据通常为小端存储(little-endian)
    rg10_array = np.frombuffer(rg10_data, dtype=np.uint16).reshape(height, width)

    # 步骤2:10位数据归一化到8位(0~1023 → 0~255)
    # 方法:除以 4(1023/4≈255.75,取整后为0~255),或使用cv2.normalize
    rg8_array = (rg10_array // 4).astype(np.uint8)

    # 步骤3:Bayer RG10(对应OpenCV的BAYER_RGGB格式)转RGB8
    # OpenCV的cvtColor支持直接转换Bayer格式,注意匹配排列方式:
    # RG10的排列 = BAYER_RGGB → 对应cv2.COLOR_BAYER_RG2RGB
    rgb8_image = cv2.cvtColor(rg8_array, cv2.COLOR_BAYER_RG2RGB)

    return rgb8_image

def read_hik_rg10():
    # 1. 枚举设备并打开相机
    deviceList = MV_CC_DEVICE_INFO_LIST()
    ret = MvCamera.MV_CC_EnumDevices(MV_GIGE_DEVICE, deviceList)
    if ret != 0:
        print("查找设备失败。 错误码[0x%x]" % ret)
        return -1
    if deviceList.nDeviceNum == 0:  # 在线设备数量
        print("未发现设备!")
        return -1
    mvcc_dev_info = cast(deviceList.pDeviceInfo[0], POINTER(MV_CC_DEVICE_INFO)).contents
    cam = MvCamera()
    ret = cam.MV_CC_CreateHandle(mvcc_dev_info)  # 创建设备句柄
    if ret != 0:
        cam.MV_CC_DestroyHandle()  # 销毁设备句柄
        print("创建设备句柄失败。 错误码[0x%x]" % ret)
    else:
        cam.user_defined_name = decoding_char(
            mvcc_dev_info.SpecialInfo.stGigEInfo.chUserDefinedName)  # 设备的用户定义名称(支持中文名称)
        cam.model_name = decoding_char(mvcc_dev_info.SpecialInfo.stGigEInfo.chModelName)  # 相机的型号
        print("user_defined_name:", cam.user_defined_name)
        print("model_name:", cam.model_name)
    cam.MV_CC_OpenDevice()

    ret = cam.MV_CC_StartGrabbing()  # 开始取流
    if ret != 0:
        print(f"start grabbing fail! ret = {To_hex_str(ret)}")
        cam.MV_CC_DestroyHandle()  # 销毁设备句柄
        return ret
    pFrameBuffer = MV_FRAME_OUT()  # 相机的输出图像帧对象
    frame_info = MV_FRAME_OUT_INFO_EX()  # 相机的输出图像帧信息对象
    memset(byref(pFrameBuffer), 0, sizeof(pFrameBuffer))  # 初始化输出图像帧对象的内存区

    ret = cam.MV_CC_GetImageBuffer(pFrameBuffer, 1000)  # 超时1000ms
    if ret != 0:
        print(f"get image buffer fail! ret = {To_hex_str(ret)}")
        cam.MV_CC_DestroyHandle()  # 销毁设备句柄
        return ret

    memmove(byref(frame_info), byref(pFrameBuffer.stFrameInfo), sizeof(MV_FRAME_OUT_INFO_EX))  # 拷贝图像帧信息
    l = frame_info.nFrameLen  # 图像的帧长度
    pixelType = frame_info.enPixelType  # 图像的像素格式,enum的类型在PixelType_header.py内定义
    nFrameNum = frame_info.nFrameNum  # 图像的帧号

    buf_bytes = (c_ubyte * l)()  # 开辟存储字节流的缓存空间
    # cdll.msvcrt.memcpy(byref(buf_bytes), stOutFrame.pBufAddr, l)  # 拷贝图像帧的字节流数据
    memmove(byref(buf_bytes), pFrameBuffer.pBufAddr, l)  # 拷贝图像帧的字节流数据

    # 4. 解析RG10数据(pFrameBuffer.pBuf是字节数据)
    width = frame_info.nWidth
    height = frame_info.nHeight

    print(f"获取到图像帧,帧号: {nFrameNum}, 帧长度: {l}, pixelType: {pixelType}, width: {width}, height: {height}")

    # 5. 释放资源
    cam.MV_CC_FreeImageBuffer(pFrameBuffer)
    cam.MV_CC_StopGrabbing()
    cam.MV_CC_CloseDevice()
    cam.MV_CC_DestroyHandle()

    return buf_bytes, width, height

rg10_data, w, h = read_hik_rg10()
rgb8_img = rg10_to_rgb8(rg10_data, w, h)
cv2.imshow("rgb8_img", rgb8_img)
cv2.waitKey(0)
总结
  1. RG10 核心特征:10bit 有效数据(0~1023),以 uint16 存储,Bayer 排列为 RGGB,小端存储;
  2. 转换关键步骤:uint16 数组转换 → 10bit 归一化到 8bit → OpenCV 的 BAYER_RG2RGB 转换;
  3. 避坑点:确认 Bayer 排列(颜色异常时换 OpenCV 的 Bayer 转换枚举)、端序(小端)、分辨率匹配。

如果 RG10 数据转换后出现颜色偏色、画面乱码等问题,优先核对 Bayer 排列方式(换COLOR_BAYER_BG2RGB/COLOR_BAYER_GR2RGB试试),其次检查数据长度是否和宽高匹配(width×height×2 字节)。

二、RG12 格式

RG12 中的 12 就是指 12 位有效位深,和 RG10 的命名规则完全一致,是工业相机中另一类常用的 Bayer 原始格式,海康 MV 相机也广泛支持该格式。

1. 和 RG10 对标
特征 RG12 RG10
有效位深 12bit 10bit
取值范围 0 ~ 4095(2¹²-1) 0 ~ 1023(2¹⁰-1)
存储方式 封装为uint16(2 字节) 封装为uint16(2 字节)
无效位分布 高 4 位为 0,低 12 位为有效数据 高 6 位为 0,低 10 位为有效数据
Bayer 排列 同 RG10,为RGGB(R-G/R-G,G-B/G-B) RGGB
存储端序 海康相机默认小端(little-endian) 小端

RG12 的 16bit 存储结构

bit15 bit14 bit13 bit12 bit11 ~ bit0
0 0 0 0 有效 12bit 数据
2. 核心差异

核心差异仅在12bit→8bit 的位深归一化步骤,其余解析、Bayer 转换逻辑完全一致,直接复用 RG10 的流程即可,优化后通用代码如下:

复制代码
import cv2
import numpy as np

def bayer_rgxx_to_rgb8(raw_data: bytes, width: int, height: int, bit_depth: int = 10) -> np.ndarray:
    """
    通用海康RG10/RG12转RGB8函数
    :param raw_data: 相机原始字节数据
    :param width/height: 图像分辨率
    :param bit_depth: 位深(10/RG10,12/RG12)
    :return: RGB8格式numpy数组
    """
    # 1. 小端解析为uint16数组(海康默认)
    rgxx_array = np.frombuffer(raw_data, dtype=np.dtype('<u2')).reshape(height, width)
    # 2. 不同位深归一化到8bit(0~255)
    if bit_depth == 10:
        rg8_array = (rgxx_array >> 2).astype(np.uint8)  # 右移2位=除以4,1023→255
    elif bit_depth == 12:
        rg8_array = (rgxx_array >> 4).astype(np.uint8)  # 右移4位=除以16,4095→255
    else:
        raise ValueError("仅支持10/12位深,对应RG10/RG12")
    # 3. RGGB排列转RGB8(和RG10完全一致)
    rgb8_image = cv2.cvtColor(rg8_array, cv2.COLOR_BAYER_RG2RGB)
    return rgb8_image

# ------------------- 调用示例 -------------------
# RG12调用:指定bit_depth=12
# width, height = 相机实际分辨率
# rg12_data = 海康相机读取的RG12原始字节数据
# rgb8_img = bayer_rgxx_to_rgb8(rg12_data, width, height, bit_depth=12)
3. RG12 更精准的归一化方式(画质优先场景)

如果对图像动态范围要求高,不建议直接右移整数运算 (会丢失低阶细节),可使用浮点归一化 + 限幅,适配 RG12 的代码:

复制代码
# RG12精准归一化(替代右移4位)
rg8_array = np.clip((rg12_array / 4095) * 255, 0, 255).astype(np.uint8)

✅ 优点:保留 12bit 的完整动态范围,暗部 / 亮部细节更丰富;

❌ 缺点:浮点运算比整数右移稍慢,对实时性要求极高的场景(如帧率 > 30fps)建议用整数运算。

总结
  1. RG12 的12即 12 位有效位深,命名、排列、存储规则和 RG10 完全统一,仅有效数据位宽不同;
  2. 转 RGB8 的唯一差异是归一化步骤:RG12 右移 4 位,RG10 右移 2 位;
  3. 海康相机 RG10/RG12 的 Bayer 排列均为RGGB ,均用cv2.COLOR_BAYER_RG2RGB转换,无需修改。

三、RG10 packed

RG10 Packed(紧凑式 RG10) 是海康等工业相机对 10bit Bayer RGGB 的高密度存储格式 ,和之前讲的RG10 Unpacked(非紧凑,也叫 RG10 Planar) 核心区别是存储方式 :Unpacked 是 10bit 数据用 2 字节(uint16)存储(高 6 位补 0,存在空间浪费),而Packed 是 5 个字节存储 4 个 10bit 像素 ,无冗余位,能节省37.5% 的带宽 / 存储空间 ,是工业相机高帧率采集的常用格式,命名中带 Packed/Compact 均指此格式

先明确核心结论:

  1. RG10 Packed 仍为RGGB 的 Bayer 排列,仅像素数据的字节封装规则不同;
  2. 处理核心是解包:将 5 字节 4 像素的紧凑格式,还原为每个像素 10bit 的原始数据,再按常规 RG10 流程转 RGB8;
  3. 海康 MV 相机中,RG10 Packed 的像素格式枚举值为PixelType_Gvsp_RG10_Packed(需和普通 RG10 区分)。
1. RG10 Packed 存储规则(核心重点)

10bit 的像素,4 个像素总数据量为 4×10bit = 40bit = 5字节,这是 RG10 Packed 的封装基础,无任何位浪费 。设 4 个连续的 RGGB Bayer 像素为P0(P09~P00)、P1(P19~P10)、P2(P29~P20)、P3(P39~P30)(每个像素 10 位,高位为 bit9,低位为 bit0),这 4 个像素被封装到5 个连续字节 B0~B4中,封装规则如下:

字节位 B0[7:0] B1[7:0] B2[7:0] B3[7:0] B4[7:0]
封装的像素位 P0[7:0] P0[9:8]+P1[5:0] P1[9:6]+P2[3:0] P2[9:4]+P3[1:0] P3[9:2]

拆解理解(从字节还原单像素 10bit 数据)

  • P0(第 1 个像素) :低 8 位 = B0 全 8 位,高 2 位 = B1 的 bit7~bit6 → P0 = (B1 >> 6) << 8 | B0
  • P1(第 2 个像素) :低 6 位 = B1 的 bit5~bit0,高 4 位 = B2 的 bit7~bit4 → P1 = (B2 >>4) <<6 | (B1 & 0x3F)
  • P2(第 3 个像素) :低 4 位 = B2 的 bit3~bit0,高 6 位 = B3 的 bit7~bit2 → P2 = (B3 >>2) <<4 | (B2 & 0x0F)
  • P3(第 4 个像素) :低 2 位 = B3 的 bit1~bit0,高 8 位 = B4 全 8 位 → P3 = B4 <<2 | (B3 & 0x03)

关键前提 :4 个像素为连续的 RGGB 排列,和普通 RG10 的 Bayer 顺序完全一致,解包后无需调整像素顺序。

2. RG10 Packed 图像总字节数计算

普通 RG10(Unpacked)总字节数 = 宽 × 高 ×2;RG10 Packed 总字节数 = (宽 × 高 × 10) / 8 = 宽 × 高 × 1.25 (必须为整数,相机输出分辨率会保证此条件)。示例:1920×1080 的 RG10 Packed 图像,总字节数 = 1920×1080×10/8=2592000 字节(普通 RG10 为 4147200 字节,节省约 1.5M / 帧)。

3. RG10 Packed 解包 + 转 RGB8 完整实现(Python+NumPy/OpenCV)

处理流程:读取 Packed 字节数据 → 按 5 字节 4 像素规则解包为 10bit uint16 数组 → 10bit 转 8bit → OpenCV Bayer RGGB 转 RGB8 。NumPy 实现解包是最优选择(比纯 Python 循环快 100 + 倍,满足实时采集需求),以下是可直接运行的通用代码,适配海康相机输出的 RG10 Packed 数据。

完整代码(解包 + 转 RGB8)

复制代码
import cv2
import numpy as np

def rg10_packed_to_rgb8(packed_data: bytes, width: int, height: int) -> np.ndarray:
    """
    海康MV相机RG10 Packed格式转RGB8
    :param packed_data: 相机读取的RG10 Packed原始字节数据
    :param width: 图像宽度(像素)
    :param height: 图像高度(像素)
    :return: RGB8格式numpy数组 (height, width, 3) uint8
    """
    # 步骤1:校验数据长度(必须严格匹配宽高计算的字节数)
    expected_bytes = width * height * 10 // 8
    if len(packed_data) != expected_bytes:
        raise ValueError(f"RG10 Packed数据长度异常,预期{expected_bytes}字节,实际{len(packed_data)}字节")
    
    # 步骤2:将字节数据转为uint8数组,方便按位操作
    b = np.frombuffer(packed_data, dtype=np.uint8)
    # 步骤3:按5字节为一组,拆分出B0-B4(核心解包步骤,NumPy向量化操作,无循环)
    # 总像素数=w*h,总组数=总像素数//4;不足4的部分相机会补全,无需处理
    num_pixels = width * height
    num_groups = num_pixels // 4
    b0 = b[0:5*num_groups:5]
    b1 = b[1:5*num_groups:5]
    b2 = b[2:5*num_groups:5]
    b3 = b[3:5*num_groups:5]
    b4 = b[4:5*num_groups:5]

    # 步骤4:按封装规则还原4个10bit像素(P0-P3),转为uint16(避免位溢出)
    p0 = ((b1 >> 6) & 0x03).astype(np.uint16) << 8 | b0.astype(np.uint16)  # 10bit
    p1 = ((b2 >> 4) & 0x0F).astype(np.uint16) << 6 | (b1 & 0x3F).astype(np.uint16)  # 10bit
    p2 = ((b3 >> 2) & 0x3F).astype(np.uint16) << 4 | (b2 & 0x0F).astype(np.uint16)  # 10bit
    p3 = b4.astype(np.uint16) << 2 | (b3 & 0x03).astype(np.uint16)  # 10bit

    # 步骤5:拼接P0-P3为一维uint16数组,再重塑为宽高的二维图像(RGGB排列)
    rg10_unpacked = np.hstack([p0, p1, p2, p3]).reshape(height, width)
    # 步骤6:10bit转8bit(和普通RG10一致,右移2位或归一化,二选一)
    # 方式1:整数右移(速度快,实时采集推荐)
    rg8 = (rg10_unpacked >> 2).astype(np.uint8)
    # 方式2:浮点归一化(画质更优,暗部细节丰富,稍慢)
    # rg8 = np.clip((rg10_unpacked / 1023) * 255, 0, 255).astype(np.uint8)

    # 步骤7:Bayer RGGB转RGB8(和普通RG10完全一致,用cv2.COLOR_BAYER_RG2RGB)
    rgb8 = cv2.cvtColor(rg8, cv2.COLOR_BAYER_RG2RGB)
    
    return rgb8

# ------------------- 测试示例 -------------------
if __name__ == "__main__":
    # 模拟海康RG10 Packed数据(1920×1080,生成随机测试数据)
    W, H = 1920, 1080
    test_packed = np.random.randint(0, 256, size=W*H*10//8, dtype=np.uint8).tobytes()
    # 转换为RGB8
    rgb_img = rg10_packed_to_rgb8(test_packed, W, H)
    # 验证结果
    print(f"RGB8图像形状: {rgb_img.shape},数据类型: {rgb_img.dtype}")
    # 显示/保存(可选)
    cv2.imshow("RG10 Packed -> RGB8", rgb_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    cv2.imwrite("rg10_packed_rgb8.jpg", rgb_img)
4. 关键优化点与避坑指南
1). 解包速度优化:用 NumPy 向量化替代 Python 循环

如果用for循环逐 5 字节解包,1920×1080 的图像会耗时几十毫秒 ,无法满足实时采集(如 30/60fps);而上述代码的NumPy 向量化操作 ,解包耗时仅0.1~1 毫秒,完全适配工业相机实时需求。

2). 颜色偏色 / 画面乱码的排查步骤

如果转换后颜色异常或画面乱码,按以下顺序排查(99% 的问题都出在这里):

  1. 校验数据长度 :确保读取的字节数 =宽×高×10/8,相机返回的nFrameLen会直接给出正确值,不要手动计算;
  2. 确认 Bayer 排列 :海康 RG10 Packed 仍为RGGB ,必须用cv2.COLOR_BAYER_RG2RGB,切勿用 BG/GR/GB 系列;
  3. 解包位操作校验 :检查位运算的& 掩码(如 0x03/0x3F/0x0F)是否正确,掩码错误会导致像素数据错位;
  4. 相机参数复位:若以上都正确,复位相机参数后重新设置 RG10 Packed,避免格式混叠。
5. 10bit 转 8bit 的两种方式对比
方式 代码 优点 缺点 适用场景
整数右移 2 位 rg8 = (rg10 >> 2).astype(np.uint8) 速度极快,无浮点运算 丢失最低 2 位细节 实时采集、高帧率场景
浮点归一化 + 限幅 np.clip((rg10/1023)*255,0,255) 保留 10bit 完整动态范围 浮点运算稍慢 画质优先、低帧率场景
6. RG10 Packed vs 普通 RG10 核心对比
特性 RG10 Packed(紧凑) RG10 Unpacked(非紧凑)
存储方式 5 字节 4 像素,无冗余位 2 字节 1 像素,高 6 位补 0
总字节数 宽 × 高 ×1.25 宽 × 高 ×2
空间利用率 100%(无浪费) 62.5%(浪费 37.5%)
处理步骤 需先解包,再转 RGB8 直接解析,无需解包
带宽 / 存储占用 低(适合高帧率 / 大分辨率) 高(适合简单处理)
海康枚举值 PixelType_Gvsp_RG10_Packed PixelType_Gvsp_RG10
Bayer 排列 均为 RGGB 均为 RGGB
转 RGB8 核心差异 多一步解包 无解压步骤

四、扩展:RG12 Packed 格式(举一反三)

海康相机也支持RG12 Packed ,其封装规则为3 字节存储 2 个 12bit 像素(2×12bit=24bit=3 字节),和 RG10 Packed 的设计思路完全一致,仅封装 / 解包的位运算规则不同,可基于本文代码快速修改实现。

最终总结

RG10 Packed 的处理核心是 **「解包」,只要掌握 5 字节 4 像素的封装规则,用 NumPy 实现向量化解包,就能高效转换为普通 RG10 格式,后续的 10bit 转 8bit、Bayer 转 RGB8 流程和普通 RG10 完全复用。该格式是海康 MV 相机高帧率、大分辨率采集 ** 的最优选择,能大幅降低网络 / 存储带宽,唯一的代价是增加了一步解包操作(但耗时可忽略)。

相关推荐
点点开心1 小时前
攻防世界WEB(新手模式)2-5-web2
前端·学习·安全·web安全·网络安全
不吃橘子的橘猫1 小时前
Verilog HDL基础(概念+模块)
开发语言·学习·算法·fpga开发·verilog
少年强则国强1 小时前
anaconda安装配置pycharm
ide·python·pycharm
m0_561359671 小时前
自动化与脚本
jvm·数据库·python
盐真卿1 小时前
python第五部分:文件操作
前端·数据库·python
wdfk_prog1 小时前
[Linux]学习笔记系列 -- [drivers][dma]dma-buf
linux·笔记·学习
晚霞的不甘2 小时前
Flutter for OpenHarmony《智慧字典》英语学习模块代码深度解析:从数据模型到交互体验
前端·学习·flutter·搜索引擎·前端框架·交互
三水不滴2 小时前
从原理、场景、解决方案深度分析Redis分布式Session
数据库·经验分享·redis·笔记·分布式·后端·性能优化
多打代码2 小时前
2026.1.29 复原ip地址 & 子集 & 子集2
开发语言·python