色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于OpenVINO在英特爾開發套件上實現眼部追蹤

英特爾物聯網 ? 來源:英特爾物聯網 ? 2023-09-18 10:11 ? 次閱讀

作者:汕頭大學 22級電子信息工程 羅毅成

本文將以訓練一個眼部追蹤 AI 小模型為背景,介紹從 Pytorch 自定義網絡模型,到使用 OpenVINO NNCF 量化工具優化模型,并部署到英特爾開發套件愛克斯開發板 AIxBoard 的流程。

本項目已開源:RedWhiteLuo/HeadEyeTrack (github.com)

開發環境:Windows 11 + Pycharm。模型訓練平臺為 12700H,部署平臺為 AIxBoard愛克斯板。

AIxBoard愛克斯板開發者套介紹

此開發人員套件采用英特爾 賽揚 處理器 N 系列,已通過 Ubuntu* Desktop 和 OpenVINO 工具套件的預驗證,有助于在教育方面取得更多成績。這一組合為學生提供了在 AI、視覺處理和物聯網領域培養編程技能和設計解決方案原型所需的性能。

開始的開始當然是開箱啦~~

01確定整體的流程

在 V1.0 版本中,我將眼部圖片直接用來訓練神經網絡,發現結果并不理想,經過檢查后發現由于頭部的朝向會朝著目光方向偏轉,導致訓練集中的樣本分布差異很小,由此導致結果并不理想,于是在 V1.5 版本中采用了復合的模型結構,以此引入頭部的位置信息:

02模型結構

以網絡上已有的項目 “lookie-lookie” 為參考,通過查看其源碼可以得知該項目所使用的網絡結構, 我們可以以此為基礎進行修改。

因此,在 Pytroch 中我們可以繼承 nn.Module 并定義如下的模型:

class EyeImageModel(nn.Module):
  def __init__(self):
    super(EyeImageModel, self).__init__()
    self.model = Sequential(
      # in-> [N, 3, 32, 128]
      BatchNorm2d(3),
      Conv2d(3, 2, kernel_size=(5, 5), padding=2),
      LeakyReLU(),
      MaxPool2d(kernel_size=(2, 2), stride=(2, 2)),
      Conv2d(2, 20, kernel_size=(5, 5), padding=2),
      ELU(),
      Conv2d(20, 10, kernel_size=(5, 5), padding=2),
      Tanh(),
      Flatten(1, 3),
      Dropout(0.01),
      Linear(10240, 1024),
      Softplus(),
      Linear(1024, 2),
    )


  def forward(self, x):
    return self.model(x)




class PositionOffset(nn.Module):
  def __init__(self):
    super(PositionOffset, self).__init__()
    self.model = Sequential(
      Conv2d(1, 32, kernel_size=(2, 2), padding=0),
      Softplus(),
      Conv2d(32, 64, kernel_size=(2, 2), padding=1),
      Conv2d(64, 64, kernel_size=(2, 2), padding=0),
      ELU(),
      Conv2d(64, 128, kernel_size=(2, 2), padding=0),
      Tanh(),
      Flatten(1, 3),
      Dropout(0.01),
      Linear(128, 32),
      Sigmoid(),
      Linear(32, 2),
    )


  def forward(self, x):
    return self.model(x)




class EyeTrackModel(nn.Module):
  def __init__(self):
    super(EyeTrackModel, self).__init__()
    self.eye_img_model = EyeImageModel()
    self.position_offset = PositionOffset()


  def forward(self, x):
    eye_img_result = self.eye_img_model(x[0])
    end = torch.cat((eye_img_result, x[1]), dim=1)
    end = torch.reshape(end, (-1, 1, 3, 3))
    end = self.position_offset(end)
    return end

向右滑動查看完整代碼

由兩個小模型組成一個復合模型,EyeImageModel 負責將眼部圖片轉換成兩個參數,在 EyeTrackModel 中與頭部位置信息組成一個 N*1*3*3 的矩陣,在 PositionOffset 中進行卷積操作,并將結果返回。

03訓練數據集的獲取

定義好了網絡結構后,我們需要去獲取足夠的數據集,通過 Peppa_Pig_Face_Landmark 這個項目可以很容易地獲取臉部 98 個關鍵點。

610265158/Peppa_Pig_Face_Landmark: A simple face detect and alignment method, which is easy and stable. (github.com)

通過讓目光跟隨鼠標位置,實時獲取圖片與鼠標位置并進行保存,我們便可以快捷地獲取到數據集。

為了盡量保持有效信息的占比,我們先分別截取兩個眼睛的圖片后 再拼接成一張圖片,即刪去鼻梁部分的位置,再進行保存,通過這種方法可以一定程度減少由頭部偏轉帶來眼部圖片的過度畸變。

def save_img_and_coords(img, coords, annot, saved_img_index):
  img_save_path = './dataset/img/' + '%d.png' % saved_img_index
  annot_save_path = './dataset/annot/' + '%d.txt' % saved_img_index
  cv2.imwrite(img_save_path, img)
  np.savetxt(annot_save_path, np.array([*coords, *annot]))
  print("[INFO] | SAVED:", saved_img_index)

向右滑動查看完整代碼

def trim_eye_img(image, face_kp):
  """
  :param image: [H W C] 格式人臉圖片
  :param face_kp: 面部關鍵點
  :return: 拼接后的圖片 [H W C] 格式
  """
  l_l, l_r, l_t, l_b = return_boundary(face_kp[60:68])
  r_l, r_r, r_t, r_b = return_boundary(face_kp[68:76])
  left_eye_img = image[int(l_t):int(l_b), int(l_l):int(l_r)]
  right_eye_img = image[int(r_t):int(r_b), int(r_l):int(r_r)]
  left_eye_img = cv2.resize(left_eye_img, (64, 32), interpolation=cv2.INTER_AREA)
  right_eye_img = cv2.resize(right_eye_img, (64, 32), interpolation=cv2.INTER_AREA)
  return np.concatenate((left_eye_img, right_eye_img), axis=1)

向右滑動查看完整代碼

這一步將保存的文件命名為 index.png 和 index.txt,并保存在 /img 和 /annot 兩個子文件夾中。

需要注意的是,使用 cv2.VideoCapture() 的時候,獲取的圖片默認是(640,480)大小的。經過 FaceLandMark 后得到的眼部圖片過于模糊,因此需要手動指定攝像頭的分辨率:

vide_capture = cv2.VideoCapture(1)
vide_capture.set(cv2.CAP_PROP_FRAME_WIDTH, HEIGHT)
vide_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, WEIGHT)

向右滑動查看完整代碼

04簡單的 DataLoader

由于每個樣本圖片的大小只有 32 x 128, 相對來說比較小,因此就干脆直接全部加載到內存中:

def EpochDataLoader(path, batch_size=64):
  """
  :param path: 數據集的根路徑
  :param batch_size: batch_size
  :return: epoch_img, epoch_annots, epoch_coords:
[M, batch_size, C, H, W], [M, batch_size, 7], [M, batch_size, 2]
  """
  epoch_img, epoch_annots, epoch_coords = [], [], []
  all_file_name = os.listdir(path + "img/") # get all file name -> list
  file_num = len(all_file_name)
  batch_num = file_num // batch_size


  for i in range(batch_num): # how many batch
    curr_batch = all_file_name[batch_size * i:batch_size * (i + 1)]
    batch_img, batch_annots, batch_coords = [], [], []
    for file_name in curr_batch:


      img = cv2.imread(str(path) + "img/" + str(file_name)) # [H, W, C] format
      img = img.transpose((2, 0, 1))
      img = img / 255 # [C, H, W] format
      data = np.loadtxt(str(path) + "annot/" + str(file_name).split(".")[0] + ".txt")
      annot_mora, coord_mora = np.array([1920, 1080, 1920, 1080, 1, 1, 1.4]), np.array([1920, 1080])
      annot, coord = data[2:]/annot_mora, data[:2]/coord_mora


      batch_img.append(img)
      batch_annots.append(annot)
      batch_coords.append(coord)


    epoch_img.append(batch_img)
    epoch_annots.append(batch_annots)
    epoch_coords.append(batch_coords)


  epoch_img = torch.from_numpy(np.array(epoch_img)).float()
  epoch_annots = torch.from_numpy(np.array(epoch_annots)).float()
  epoch_coords = torch.from_numpy(np.array(epoch_coords)).float()
  return epoch_img, epoch_annots, epoch_coords

向右滑動查看完整代碼

這個函數可以一次性返回所有的樣本。

05定義損失函數并訓練

由于網絡輸出的結果是 N 個二維坐標,因此直接使用 torch.nn.MSELoss() 作為損失函數。

def eye_track_train():
  img, annot, coord = EpochDataLoader(TRAIN_DATASET_PATH, batch_size=TRAIN_BATCH_SIZE)
  batch_num = img.size()[0]
  model = EyeTrackModel().to(device).train()
  loss = torch.nn.MSELoss()
  optim = torch.optim.SGD(model.parameters(), lr=LEARN_STEP)
  writer = SummaryWriter(LOG_SAVE_PATH)


  trained_batch_num = 0
  for epoch in range(TRAIN_EPOCH):
    for batch in range(batch_num):
      batch_img = img[batch].to(device)
      batch_annot = annot[batch].to(device)
      batch_coords = coord[batch].to(device)
      # infer and calculate loss
      outputs = model((batch_img, batch_annot))
      result_loss = loss(outputs, batch_coords)
      # reset grad and calculate grad then optim model
      optim.zero_grad()
      result_loss.backward()
      optim.step()
      # save loss and print info
      trained_batch_num += 1
      writer.add_scalar("loss", result_loss.item(), trained_batch_num)
      print("[INFO]: trained epoch num | trained batch num | loss "
         , epoch + 1, trained_batch_num, result_loss.item())
    if epoch % 100 == 0:
      torch.save(model, "../model/ET-" + str(epoch) + ".pt")
  # save model
  torch.save(model, "../model/ET-last.pt")
  writer.close()
  print("[SUCCEED!] model saved!")

向右滑動查看完整代碼

訓練過程中每 100 輪都會保存一次模型,訓練結束后也會進行保存。

06通過導出為 ONNX 模型

通過 torch.onnx.export() 我們便可以很方便導出 onnx 模型。

def export_onnx(model_path, if_fp16=False):
  """
  :param model_path: 模型的路徑
:param if_fp16: 是否要將模型壓縮為 FP16 格式
:return: 模型輸出路徑
  """
  model = torch.load(model_path, map_location=torch.device('cpu')).eval()
  print(model)
  model_path = model_path.split(".")[0]
  dummy_input_img = torch.randn(1, 3, 32, 128, device='cpu')
  dummy_input_position = torch.randn(1, 7, device='cpu')
  torch.onnx.export(model, [dummy_input_img, dummy_input_position], model_path + ".onnx", export_params=True)
  model = mo.convert_model(model_path + ".onnx", compress_to_fp16=if_fp16) # if_fp16=False, output = FP32
  serialize(model, model_path + ".xml")
  print(EyeTrackModel(), "
[FINISHED] CONVERT DONE!")
  return model_path + ".xml"

向右滑動查看完整代碼

07使用 OpenVINO 的 NNCF 工具進行 int8 量化

Neural Network Compression Framework (NNCF) provides a new post-training quantization API available in Python that is aimed at reusing the code for model training or validation that is usually available with the model in the source framework, for example, PyTorch* or TensroFlow*. The API is cross-framework and currently supports models representing in the following frameworks: PyTorch, TensorFlow 2.x, ONNX, and OpenVINO.

Post-training Quantization with NNCF (new) — OpenVINO documentation[1]

通過 OpenVINO 的官方文檔我們可以知道:Post-training Quantization with NNCF分為兩個子模塊:

Basic quantization

Quantization with accuracy control

def basic_quantization(input_model_path):
  # prepare required data
  data = data_source(path=DATASET_ROOT_PATH)
  nncf_calibration_dataset = nncf.Dataset(data, transform_fn)
  # set the parameter of how to quantize
  subset_size = 1000
  preset = nncf.QuantizationPreset.MIXED
  # load model
  ov_model = Core().read_model(input_model_path)
  # perform quantize
  quantized_model = nncf.quantize(ov_model, nncf_calibration_dataset, preset=preset, subset_size=subset_size)
  # save model
  output_model_path = input_model_path.split(".")[0] + "_BASIC_INT8.xml"
  serialize(quantized_model, output_model_path)




def accuracy_quantization(input_model_path, max_drop):
  # prepare required data
  calibration_source = data_source(path=DATASET_ROOT_PATH, with_annot=False)
  validation_source = data_source(path=DATASET_ROOT_PATH, with_annot=True)
  calibration_dataset = nncf.Dataset(calibration_source, transform_fn)
  validation_dataset = nncf.Dataset(validation_source, transform_fn_with_annot)
  # load model
  xml_model = Core().read_model(input_model_path)
  # perform quantize
  quantized_model = nncf.quantize_with_accuracy_control(xml_model,
                             calibration_dataset=calibration_dataset,
                             validation_dataset=validation_dataset,
                             validation_fn=validate,
                             max_drop=max_drop)
  # save model
  output_model_path = xml_model_path.split(".")[0] + "_ACC_INT8.xml"
  serialize(quantized_model, output_model_path)




def export_onnx(model_path, if_fp16=False):
  """
  :param model_path: the path that will be converted
  :param if_fp16: if the output onnx model compressed to fp16
  :return: output xml model path
  """
  model = torch.load(model_path, map_location=torch.device('cpu')).eval()
  print(model)
  model_path = model_path.split(".")[0]
  dummy_input_img = torch.randn(1, 3, 32, 128, device='cpu')
  dummy_input_position = torch.randn(1, 7, device='cpu')
  torch.onnx.export(model, [dummy_input_img, dummy_input_position], model_path + ".onnx", export_params=True)
  model = mo.convert_model(model_path + ".onnx", compress_to_fp16=if_fp16) # if_fp16=False, output = FP32
  serialize(model, model_path + ".xml")
  print(EyeTrackModel(), "
[FINISHED] CONVERT DONE!")
  return model_path + ".xml"

向右滑動查看完整代碼

這里需要注意的是 nncf.Dataset (calibration_source, transform_fn) 這一部分,calibration_source 所返回的必須是一個可迭代對象,每次迭代返回的是一個訓練樣本 [1, C, H, W],transform_fn 則是對這個訓練樣本作轉換(比如改變通道數,交換 H, W)這里的操作是進行歸一化,并轉換為 numpy。

08量化后的性能提升

測試的硬件平臺 12700H。

這種小模型通過 OpenVINO NNCF 方法量化后可以獲得很明顯的性能提升:

benchmark_app -m ET-last_ACC_INT8.xml -d CPU -api async
[ INFO ] Execution Devices:['CPU'] [ INFO ] Count: 226480 iterations [ INFO ] Duration: 60006.66 ms [ INFO ] Latency: [ INFO ] Median: 3.98 ms [ INFO ] Average: 4.18 ms [ INFO ] Min: 2.74 ms [ INFO ] Max: 38.98 ms [ INFO ] Throughput: 3774.25 FPS benchmark_app -m ET-last_INT8.xml -d CPU -api async
[ INFO ] Execution Devices:['CPU'] [ INFO ] Count: 513088 iterations [ INFO ] Duration: 60002.85 ms [ INFO ] Latency: [ INFO ] Median: 1.46 ms [ INFO ] Average: 1.76 ms [ INFO ] Min: 0.82 ms [ INFO ] Max: 61.07 ms [ INFO ] Throughput: 8551.06 FPS

向右滑動查看

09在 AIxBoard愛克斯板開發者套件上進行部署

由于 AlxBoard 上已經安裝好了 Python,因此只需要再安裝 OpenVINO 即可。

下載英特爾發行版 OpenVINO 工具套件 (intel.cn)[2]

然后在項目的根目錄執行 python eye_track.py 即可查看到網絡的推理結果,如下圖所示。

b26aed88-53ab-11ee-a25d-92fbcf53809c.png

性能概覽:

b2ae24ea-53ab-11ee-a25d-92fbcf53809c.png

在iGPU上的運行性能

b2def318-53ab-11ee-a25d-92fbcf53809c.png

在CPU上運行的性能

總結

OpenVINO 提供了一個方便快捷的開發方式,通過幾個核心的API便可實現模型轉換和模型量化。

AIxBoard 基于 x86 架構提供了一個高通用、高性能的部署平臺,體積小巧,非常適合項目的最終部署。

自訓練 Pytorch 模型在通過 OpenVINO 的模型優化工具優化后,使用 OpenVINO Runtime 進行推理,對于如上文所示的小模型可以獲得巨大的性能提升,并且推理過程簡單清晰。在開發板上推理僅需幾個核心函數便可實現基于自訓練 Pytorch 模型的推理。

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 處理器
    +關注

    關注

    68

    文章

    19259

    瀏覽量

    229651
  • 英特爾
    +關注

    關注

    61

    文章

    9949

    瀏覽量

    171692
  • 開發板
    +關注

    關注

    25

    文章

    5032

    瀏覽量

    97371
  • 開發套件
    +關注

    關注

    2

    文章

    154

    瀏覽量

    24271
  • OpenVINO
    +關注

    關注

    0

    文章

    92

    瀏覽量

    196

原文標題:基于 OpenVINO? 在英特爾開發套件上實現眼部追蹤 | 開發者實戰

文章出處:【微信號:英特爾物聯網,微信公眾號:英特爾物聯網】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    介紹英特爾?分布式OpenVINO?工具包

    性能。 英特爾?OpenlandOpen?管理軟件包包括英特爾?深度學習部署工具包(英特爾?DLDT)。適用于Linux *的OpenVINO?工具包的
    發表于 07-26 06:45

    OpenVINO工具套件是否可以商業化使用?

    參閱 英特爾? OpenVINO?分銷許可第 2.1 節(2021 年 5 月版本)。 無法了解英特爾? 發行版 OpenVINO? 工具套件
    發表于 08-15 08:19

    安裝OpenVINO工具套件英特爾Distribution時出現錯誤的原因?

    安裝OpenVINO?工具套件英特爾 Distribution時,出現錯誤: Python 3.10.0.ECHO is off. Unsupported Python version.
    發表于 08-15 08:14

    英特爾82801HM IO控制器開發套件

    英特爾 82801HM I/O 控制器開發套件英特爾 凌動 處理器系列包括板載處理器,該處理器采用 45 納米制程技術的集成優化圖形和內存控制器,與上一代英特爾 凌動 處理器 N2
    發表于 12-07 14:05 ?29次下載
    <b class='flag-5'>英特爾</b>82801HM IO控制器<b class='flag-5'>開發套件</b>

    英特爾QM57高速芯片組開發套件

    英特爾酷睿處理器系列和移動式英特爾QM57高速芯片組開發套件采用行業標準的x86架構,擁有智能性能、優異能效、集成顯卡和糾錯編碼(ECC)內存。這些集成的雙芯片平臺不僅可提供卓越
    發表于 12-07 14:06 ?50次下載
    <b class='flag-5'>英特爾</b>QM57高速芯片組<b class='flag-5'>開發套件</b>

    英特爾BOOT Loader開發套件-高級嵌入式開發基礎

    從技術角度概括介紹用于快速開發和部署啟動加載器的英特爾 Boot Loader 開發套件(英特爾 BLDK),該套件基于
    發表于 12-07 14:57 ?59次下載
    <b class='flag-5'>英特爾</b>BOOT Loader<b class='flag-5'>開發套件</b>-高級嵌入式<b class='flag-5'>開發</b>基礎

    英特爾945GME高速芯片組開發套件

    英特爾945GME高速芯片組開發套件是多種低功耗嵌入式應用,如工業自動化,測試和儀表、航空、國防和醫療成像系統的開發人員的理想選擇
    發表于 12-08 10:15 ?47次下載
    <b class='flag-5'>英特爾</b>945GME高速芯片組<b class='flag-5'>開發套件</b>

    英特爾的945GME高速芯片組開發套件

    英特爾的945GME高速芯片組開發套件
    發表于 10-30 11:57 ?3次下載

    使用英特爾物聯網商業開發套件改變世界

    使用英特爾?物聯網商業開發套件改變世界。
    的頭像 發表于 05-31 10:06 ?1822次閱讀

    最新版英特爾? SoC FPGA 嵌入式開發套件(SoC EDS)全面的工具套件

    使用內置于英特爾? SoC FPGA 開發套件(也可以用作外部 JTAG 調試線纜)的英特爾? FPGA Download Cable II 執行裸機調試從 Platform Designer
    的頭像 發表于 11-20 09:34 ?7048次閱讀

    英特爾? FPGA AI套件搭配OpenVINO?工具包

    您可以使用英特爾 分發版 OpenVINO 工具包和英特爾 FPGA AI 套件開發推理系統,服務于從 DL 增強型嵌入式系統一直到
    的頭像 發表于 08-11 11:53 ?1079次閱讀

    基于英特爾開發套件的AI字幕生成器設計

    市面上有很多自然語言處理模型,本文旨在幫助開發者快速將 OpenAI* 的熱門 NLP 模型 Whisper 部署至英特爾 開發套件愛克斯開發
    的頭像 發表于 09-27 16:59 ?875次閱讀
    基于<b class='flag-5'>英特爾</b><b class='flag-5'>開發套件</b>的AI字幕生成器設計

    基于英特爾? QuickAssist的?EP80579集成處理器開發套件

    采用英特爾? QuickAssist 技術的英特爾? EP80579 集成處理器的開發套件使客戶能夠為嵌入式、存儲和通信應用創建新一代解決方案。該處理器采用片系統 (SOC) 處理器
    發表于 11-14 08:32 ?0次下載
    基于<b class='flag-5'>英特爾</b>? QuickAssist的?EP80579集成處理器<b class='flag-5'>開發套件</b>

    基于英特爾哪吒開發套件平臺來快速部署OpenVINO Java實戰

    OpenVINO 工具套件基于OneAPI開發,可以加快高性能計算機視覺和深度學習應用開發速度的工具套件,適用于從邊緣到云的各種
    的頭像 發表于 03-21 18:24 ?1473次閱讀
    基于<b class='flag-5'>英特爾</b>哪吒<b class='flag-5'>開發</b>者<b class='flag-5'>套件</b>平臺來快速部署<b class='flag-5'>OpenVINO</b> Java實戰

    使用英特爾哪吒開發套件部署YOLOv5完成透明物體目標檢測

    英特爾的哪吒(Nezha)開發套件是一款專為邊緣AI和物聯網應用設計的高性能計算平臺,搭載了英特爾 N97處理器、內置英特爾 UHD Graphics GPU,并提供高達8GB LPD
    的頭像 發表于 11-25 17:15 ?211次閱讀
    使用<b class='flag-5'>英特爾</b>哪吒<b class='flag-5'>開發套件</b>部署YOLOv5完成透明物體目標檢測
    主站蜘蛛池模板: 龙腾亚洲人成电影网站| 成人女人A级毛片免费软件| 亚洲AV久久无码精品九九软件| 青春禁区动漫免费观看| 美女医生深夜在家裸睡惨死| 玖玖在线精品| 快播免费电影| 老师那里好大又粗h男男| 拉菲娱乐主管高工资q39709| 久久夜色精品国产亚州AV卜| 久久青草费线频观看国产| 精品一区二区三区免费毛片| 果冻传媒在线观看资源七夕| 果冻传媒完整免费网站在线观看| 国产在线观看成人| 极品少妇伦理一区二区| 精品久久久久中文字幕日本 | 色拍拍噜噜噜久久蜜桃| 影音先锋色av男人资源网| 一本大道香蕉中文在线视频观看| 一个人的视频在线观看免费观看| 一个人的免费完整在线观看HD| 伊人AV一区二区三区夜色撩人| 在教室伦流澡到高潮H免费视频 | 色多多涩涩屋下载软件| 手机看片国产免费| 性色爽爱性色爽爱网站| 亚洲色爽视频在线观看| 中文国产在线观看| 99热这里只有的精品| 成人在线视频观看| 国产乱人视频在线观看| 精品久久久噜噜噜久久久app| 久久一区精品| 青柠在线观看视频在线高清| 日日干夜夜艹| 亚洲精品婷婷无码成人A片在线| 在线观看永久免费网站| a级毛片高清免费视频| 国产99久久九九精品无码不卡| 国产蜜臀AV在线一区视频|