日本a√视频在线,久久青青亚洲国产,亚洲一区欧美二区,免费g片在线观看网站

        <style id="k3y6c"><u id="k3y6c"></u></style>
        <s id="k3y6c"></s>
        <mark id="k3y6c"></mark>
          
          

          <mark id="k3y6c"></mark>

          "); //-->

          博客專欄

          EEPW首頁 > 博客 > 征程 6 | 灰度圖部署鏈路介紹

          征程 6 | 灰度圖部署鏈路介紹

          發(fā)布人:地平線開發(fā)者 時(shí)間:2025-09-13 來源:工程師 發(fā)布文章
          一、為什么是灰度圖

          相較于 RGB 三通道圖像,灰度圖僅保留亮度信息(Y 分量),數(shù)據(jù)量減少 2/3,相比于常用的 NV12 圖像,數(shù)據(jù)量減少 1/3,內(nèi)存占用與計(jì)算負(fù)載顯著降低。對于下游網(wǎng)絡(luò)結(jié)構(gòu)而言,單通道網(wǎng)絡(luò)計(jì)算量/參數(shù)量也會更少,這對邊緣設(shè)備的實(shí)時(shí)處理至關(guān)重要。

          灰度圖部署有一個(gè)問題:如何將視頻流中的 NV12 數(shù)據(jù)高效轉(zhuǎn)換為模型所需的灰度輸入,并在工具鏈中實(shí)現(xiàn)標(biāo)準(zhǔn)化前處理流程。

          視頻通路傳輸?shù)脑紨?shù)據(jù)通常采用 NV12 格式,這是一種適用于 YUV 色彩空間的半平面格式:

          • 數(shù)據(jù)結(jié)構(gòu):NV12 包含一個(gè)平面的 Y 分量(亮度信息)和一個(gè)平面的 UV 分量(色度信息),其中 Y 分量分辨率為 W×H,UV 分量分辨率為 W×H/2。

          • 灰度圖提?。簩τ诨叶葓D部署,僅需使用 NV12 中的 Y 分量。以 1920×1080 分辨率為例,若 NV12 中 Y 與 UV 分量連續(xù)存儲,Y 分量占據(jù)前 1920×1080 字節(jié),后續(xù)部分為 UV 分量,可直接忽略或舍棄,若分開存儲,使用起來更簡單。

          二、灰度圖部署數(shù)據(jù)鏈路

          視頻通路過來的數(shù)據(jù)不能直接是灰度圖,而是 nv12 數(shù)據(jù),對于灰度圖部署,可以只使用其中的 y 分量。

          Description

          2.1 手動(dòng)插入前處理節(jié)點(diǎn)

          在工具鏈提供的絕大部分材料中,前處理節(jié)點(diǎn)多是對于 3 通道網(wǎng)絡(luò)、nv12 輸入進(jìn)行的,查看工具鏈用戶手冊《進(jìn)階內(nèi)容->HBDK Tool API Reference》中幾處 api 介紹,可以發(fā)現(xiàn)也是支持 gray 灰度圖的,具體內(nèi)容如下:

          • insert_image_convert(self, mode str = “nv12”)

          Insert image_convert op. Change input parameter type.
          
              Args:
                  * mode (str): Specify conversion mode, optional values are "nv12"(default) and "gray".
          
              Returns:
                  List of newly inserted function arguments which is also the inputs of inserted image convert op
          
              Raises:
                  ValueError when this argument is no longer valid
          
              Note:
                  To avoid the new insertion operator not running in some conversion passes, it is recommended to call the insert_xxx api before the convert stage
          
              Example:
                  module = load("model.bc")
                  func = module[0]
                  res = func.inputs[0].insert_image_convert("nv12")

          對于 batch 輸入,均值、標(biāo)準(zhǔn)化、歸一化等操作,可以在 insert_image_preprocess 中實(shí)現(xiàn):

          • insert_image_preprocess( self, mode str, divisor int, mean List[float], std List[float], is_signed bool = True)

          Insert image_convert op. Change input parameter type.
          
              Args:
                  * mode (str): Specify conversion mode, optional values are "skip"(default, same as None), "yuvbt601full2rgb", "yuvbt601full2bgr", "yuvbt601video2rgb" and "yuvbt601video2bgr".
          
              Returns:
                  List of newly inserted function arguments which is also the inputs of inserted image preprocess op
          
              Raises:
                  ValueError when this argument is no longer valid
          
              Note:
                  To avoid the new insertion operator not running in some conversion passes, it is recommended to call the insert_xxx api before the convert stage
          
              Example:
                  module = load("model.bc")
                  func = module[0]
                  res = func.inputs[0].insert_image_preprocess("yuvbt601full2rgb", 255, [0.485, 0.456, 0.406], [0.229, 0.224, 0.225], True)

          手動(dòng)插入前處理節(jié)點(diǎn)可參考:

          mean = [0.485]
          std = [0.229]
          func = qat_bc[0]
          
          for input in func.flatten_inputs[::-1]:
              split_inputs = input.insert_split(dim=0)
              for split_input in reversed(split_inputs):
                  node = split_input.insert_transpose([0, 3, 1, 2])
                  node = node.insert_image_preprocess(mode="skip",
                                          divisor=255,
                                          mean=mean,
                                          std=std,
                                          is_signed=True)
                  node.insert_image_convert(mode="gray")
          • mean = [0.485] 和 std = [0.229]:定義圖像歸一化時(shí)使用的均值和標(biāo)準(zhǔn)差

          • func = qat_bc[0]:獲取量化感知訓(xùn)練 (QAT) 模型中的第一個(gè)函數(shù) / 模塊作為處理入口。

          • for input in func.flatten_inputs[::-1]:逆序遍歷模型的所有扁平化輸入節(jié)點(diǎn)。

          • split_inputs = input.insert_split(dim=0):將輸入數(shù)據(jù)按批次維度 (dim=0) 分割,這是處理 batch 輸入必須要做的。

          • node = split_input.insert_transpose([0, 3, 1, 2]):將數(shù)據(jù)維度從[B, H, W, C](NHWC 格式) 轉(zhuǎn)換為[B, C, H, W](NCHW 格式),也是必須要做的。

          • node.insert_image_preprocess(…):執(zhí)行圖像預(yù)處理

          • node.insert_image_convert(mode=“gray”):插入單通道灰度圖

          三、全流程示例代碼
          import torch
          import torch.nn as nn
          import torch.nn.functional as F
          from horizon_plugin_pytorch import set_march, March
          set_march(March.NASH_M)
          from horizon_plugin_pytorch.quantization import prepare, set_fake_quantize, FakeQuantState
          from horizon_plugin_pytorch.quantization import QuantStub
          from horizon_plugin_pytorch.quantization.hbdk4 import export
          from horizon_plugin_pytorch.quantization.qconfig_template import calibration_8bit_weight_16bit_act_qconfig_setter, default_calibration_qconfig_setter
          from horizon_plugin_pytorch.quantization.qconfig import get_qconfig, MSEObserver, MinMaxObserver
          from horizon_plugin_pytorch.dtype import qint8, qint16
          from torch.quantization import DeQuantStub
          from hbdk4.compiler import statistics, save, load,visualize,compile,convert, hbm_perf
          
          class SimpleConvNet(nn.Module):
              def __init__(self):
                  super(SimpleConvNet, self).__init__()
                  # 第一個(gè)節(jié)點(diǎn):輸入通道 1,輸出通道 16,卷積核 3x3
                  self.conv1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=3, stride=1, padding=1)
                  # 后續(xù)添加一個(gè)池化層和一個(gè)全連接層
                  self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
                  self.fc = nn.Linear(16 * 14 * 14, 10)  # 假設(shè)輸入圖像為 28x28
                  self.quant = QuantStub()
                  self.dequant = DeQuantStub()
          
              def forward(self, x):
                  x = self.quant(x)
                  x = self.conv1(x)      # 卷積層
                  x = F.relu(x)          # 激活
                  x = self.pool(x)       # 池化
                  x = x.view(x.size(0), -1)  # Flatten
                  x = self.fc(x)         # 全連接層輸出
                  x = self.dequant(x)
                  return x
          
          # 構(gòu)造模型
          model = SimpleConvNet()
          
          # 構(gòu)造一個(gè)假輸入:batch_size=4,單通道,28x28 圖像
          example_input = torch.randn(4, 1, 28, 28)
          output = model(example_input)
          
          print("輸出 shape:", output.shape)  # torch.Size([4, 10])
          
          calib_model = prepare(model.eval(), example_input, 
                                qconfig_setter=(
                                    default_calibration_qconfig_setter,
                                    ),
                                )
          
          calib_model.eval()
          set_fake_quantize(calib_model, FakeQuantState.CALIBRATION)
          calib_model(example_input)
          
          calib_model.eval()                            
          set_fake_quantize(calib_model, FakeQuantState.VALIDATION)
          calib_out = calib_model(example_input)
          print("calib輸出數(shù)據(jù):", calib_out)
          
          qat_bc = export(calib_model, example_input)
          mean = [0.485]
          std = [0.229]
          func = qat_bc[0]
          
          for input in func.flatten_inputs[::-1]:
              split_inputs = input.insert_split(dim=0)
              for split_input in reversed(split_inputs):
                  node = split_input.insert_transpose([0, 3, 1, 2])
                  node = node.insert_image_preprocess(mode="skip",
                                          divisor=255,
                                          mean=mean,
                                          std=std,
                                          is_signed=True)
                  node.insert_image_convert(mode="gray")
          
          quantized_bc = convert(qat_bc, "nash-m")
          hbir_func = quantized_bc.functions[0]
          hbir_func.remove_io_op(op_types = ["Dequantize","Quantize"])
          visualize(quantized_bc, "model_result/quantized_batch4.onnx")
          statistics(quantized_bc)
          params = {'jobs': 64, 'balance': 100, 'progress_bar': True,
                    'opt': 2,'debug': True, "advice": 0.0}
          hbm_path="model_result/batch4-gray.hbm"
          print("start to compile")
          compile(quantized_bc, march="nash-m", path=hbm_path, **params)
          print("end to compile")
          ebug': True, "advice": 0.0}
          hbm_path="model_result/batch4-gray.hbm"
          print("start to compile")
          compile(quantized_bc, march="nash-m", path=hbm_path, **params)
          print("end to compile")


          *博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請聯(lián)系工作人員刪除。



          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉