国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

關(guān)鍵點(diǎn)檢測(cè)項(xiàng)目代碼開(kāi)源了!

共 42989字,需瀏覽 86分鐘

 ·

2022-01-14 08:08

 Datawhale干貨 
作者:閆永強(qiáng),算法工程師,Datawhale成員

本文通過(guò)自建手勢(shì)數(shù)據(jù)集,利用YOLOv5s檢測(cè),然后通過(guò)開(kāi)源數(shù)據(jù)集訓(xùn)練squeezenet進(jìn)行手部關(guān)鍵點(diǎn)預(yù)測(cè),最后通過(guò)指間的夾角算法來(lái)判斷具體的手勢(shì),并顯示出來(lái)。文章第四部分為用C++實(shí)現(xiàn)整體的ncnn推理(代碼較長(zhǎng),可先馬后看)

一、YOLOV5訓(xùn)練手部檢測(cè)

訓(xùn)練及部署思路類(lèi)似表情識(shí)別,需要將handpose數(shù)據(jù)集標(biāo)簽改成一類(lèi),只檢測(cè)手部,簡(jiǎn)化流程,更易上手。

此部分?jǐn)?shù)據(jù)集來(lái)源格物鈦  https://gas.graviti.cn/dataset/datawhale/HandPose,具體的效果如圖:

本教程所用訓(xùn)練環(huán)境:
系統(tǒng)環(huán)境:Ubuntu16.04
cuda版本:10.2
cudnn版本:7.6.5
pytorch版本:1.6.0
python版本:3.8

部署環(huán)境:
編譯器:vs2015
依賴(lài)庫(kù):opencv   ncnn
外設(shè):普通USB攝像頭

二、手部關(guān)節(jié)點(diǎn)檢測(cè)

1、依賴(lài)環(huán)境

和YOLOV5訓(xùn)練手部檢測(cè)一致。

2、檢測(cè)數(shù)據(jù)集準(zhǔn)備

該數(shù)據(jù)集包括網(wǎng)絡(luò)圖片以及數(shù)據(jù)集<Large-scale Multiview 3D Hand Pose Dataset> 篩選動(dòng)作重復(fù)度低的圖片,進(jìn)行制作大概有5w張數(shù)據(jù)樣本。其中<Large-scale Multiview 3D Hand Pose Dataset>數(shù)據(jù)集的官網(wǎng)地址:http://www.rovit.ua.es/dataset/mhpdataset/,其中標(biāo)注文件示例如圖2所示

制作好可以直接訓(xùn)練的數(shù)據(jù)集放在了開(kāi)源數(shù)據(jù)平臺(tái)格物鈦:https://gas.graviti.com/dataset/datawhale/HandPoseKeyPoints

3、數(shù)據(jù)集在線使用

步驟1:安裝格物鈦平臺(tái)SDK

 pip install tensorbay

步驟2:  數(shù)據(jù)預(yù)處理

要使用已經(jīng)處理好可以直接訓(xùn)練的數(shù)據(jù)集,步驟如下:

a. 打開(kāi)本文對(duì)應(yīng)數(shù)據(jù)集鏈接 https://gas.graviti.cn/dataset/datawhale/HandPose,在數(shù)據(jù)集頁(yè)面,fork數(shù)據(jù)集到自己賬戶(hù)下;

b. 點(diǎn)擊網(wǎng)頁(yè)上方開(kāi)發(fā)者工具 --> AccessKey --> 新建一個(gè)AccessKey --> 復(fù)制這個(gè)Key:KEY = 'Acces...........'

我們可以在不下載數(shù)據(jù)集的情況下,通過(guò)格物鈦進(jìn)行數(shù)據(jù)預(yù)處理,并將結(jié)果保存在本地。下面以使用HandPose數(shù)據(jù)集為例,使用HandPoseKeyPoints數(shù)據(jù)集操作同HandPose操作一樣。

數(shù)據(jù)集開(kāi)源地址

https://gas.graviti.com/dataset/datawhale/HandPoseKeyPoints

完整項(xiàng)目代碼

https://github.com/datawhalechina/HandPoseKeyPoints

import numpy as np
from PIL import Image
from tensorbay import GAS
from tensorbay.dataset import Dataset

def read_gas_image(data):
    with data.open() as fp:
        image = Image.open(fp)
        image.load()
    return np.array(image)
# Authorize a GAS client.
gas = GAS('填入你的AccessKey')
# Get a dataset.
dataset = Dataset("HandPose", gas)
dataset.enable_cache("data")
# List dataset segments.
segments = dataset.keys()

# Get a segment by name
segment = dataset["train"]
for data in segment:
    # 圖片數(shù)據(jù)
    image = read_gas_image(data)
    # 標(biāo)簽數(shù)據(jù)
    # Use the data as you like.
    for label_box2d in data.label.box2d:
        xmin = label_box2d.xmin
        ymin = label_box2d.ymin
        xmax = label_box2d.xmax
        ymax = label_box2d.ymax
        box2d_category = label_box2d.category
    break

數(shù)據(jù)集頁(yè)面可視化效果:

#數(shù)據(jù)集劃分
print(segments)
#  ("train",'val')

print(len(dataset["train"]), "images in train dataset")
print(len(dataset["val"]), "images in valid dataset")

# 1306 images in train dataset
# 14 images in valid dataset

4、關(guān)節(jié)點(diǎn)檢測(cè)原理

關(guān)節(jié)點(diǎn)檢測(cè)pipeline流程是:

1)輸入圖片對(duì)應(yīng)手部的42個(gè)關(guān)節(jié)點(diǎn)坐標(biāo),

2)整個(gè)網(wǎng)絡(luò)的backbone可以是任何分類(lèi)網(wǎng)絡(luò),我這里采用的是squeezenet,然后損失函數(shù)是wingloss。

3)整個(gè)過(guò)程就是輸入原圖經(jīng)過(guò)squeezenet網(wǎng)路計(jì)算出42個(gè)坐標(biāo)值,然后通過(guò)wingloss進(jìn)行回歸計(jì)算更新權(quán)重,最后達(dá)到指定閾值,得出最終模型。

5、手部關(guān)節(jié)點(diǎn)訓(xùn)練

手部關(guān)節(jié)點(diǎn)算法采用開(kāi)源代碼參考地址:https://gitcode.net/EricLee/handpose_x

1)預(yù)訓(xùn)練模型

預(yù)訓(xùn)練模型在上述鏈接中有相應(yīng)的網(wǎng)盤(pán)鏈接,可以直接下載。如果不想用預(yù)訓(xùn)練模型,可以直接從原始分類(lèi)網(wǎng)絡(luò)的原始權(quán)重開(kāi)始訓(xùn)練。

2)模型的訓(xùn)練

以下是訓(xùn)練網(wǎng)絡(luò)指定參數(shù)解釋?zhuān)湟饬x直接看圖中注釋就可以了。

訓(xùn)練只需要運(yùn)行訓(xùn)練命令,指定自己想要指定的參數(shù)就可以跑起來(lái)了,如下圖:

python train.py

6、手部關(guān)節(jié)點(diǎn)模型轉(zhuǎn)換

1)安裝依賴(lài)庫(kù)

pip install onnx coremltools onnx-simplifier

2)導(dǎo)出onnx模型

python model2onnx.py --model_path squeezenet1_1-size-256-loss-wing_loss-model_epoch-2999.pth --model squeezenet1_1

會(huì)出現(xiàn)如下圖所示

其中model2onnx.py文件是在上述鏈接工程目錄下的。此時(shí)當(dāng)前文件夾下會(huì)出現(xiàn)一個(gè)相應(yīng)的onnx模型export。

3)用onnx-simplifer簡(jiǎn)化模型

為什么要簡(jiǎn)化?

因?yàn)樵谟?xùn)練完深度學(xué)習(xí)的pytorch或者tensorflow模型后,有時(shí)候需要把模型轉(zhuǎn)成onnx,但是很多時(shí)候,很多節(jié)點(diǎn)比如cast節(jié)點(diǎn),Identity這些節(jié)點(diǎn)可能都不需要,需要進(jìn)行簡(jiǎn)化,這樣會(huì)方便把模型轉(zhuǎn)成ncnn mnn等端側(cè)部署模型格式。

python -m onnxsim squeezenet1_1_size-256.onnx squeezenet1_1_sim.onnx

會(huì)出現(xiàn)下圖:

上述過(guò)程完成后就生成了簡(jiǎn)化版本的模型squeezenet1_1_sim.onnx。

4)把檢測(cè)模型轉(zhuǎn)換成ncnn模型

可以直接利用網(wǎng)頁(yè)在線版本轉(zhuǎn)換模型,地址:https://convertmodel.com/  頁(yè)面如圖:

選擇目標(biāo)格式ncnn,選擇輸入格式onnx,點(diǎn)擊選擇,選擇本地的簡(jiǎn)化版本的模型,然后選擇轉(zhuǎn)換,可以看到轉(zhuǎn)換成功,下面兩個(gè)就是轉(zhuǎn)換成功的模型文件,如圖。

三、利用關(guān)節(jié)點(diǎn)手勢(shì)識(shí)別算法

通過(guò)對(duì)檢測(cè)到的手部關(guān)節(jié)點(diǎn)之間的角度計(jì)算,可以實(shí)現(xiàn)簡(jiǎn)單的手勢(shì)識(shí)別。例如:計(jì)算大拇指向量0-2和3-4之間的角度,它們之間的角度大于某一個(gè)角度閾值(經(jīng)驗(yàn)值)定義為彎曲,小于某一個(gè)閾值(經(jīng)驗(yàn)值)為伸直。具體效果如下面三張圖。

四、工程推理部署整體實(shí)現(xiàn)

此關(guān)節(jié)點(diǎn)手勢(shì)識(shí)別的整體過(guò)程總結(jié):首先是利用目標(biāo)檢測(cè)模型檢測(cè)到手的位置,然后利用手部關(guān)節(jié)點(diǎn)檢測(cè)模型,檢測(cè)手部關(guān)節(jié)點(diǎn)具體位置,繪制關(guān)節(jié)點(diǎn),以及關(guān)節(jié)點(diǎn)之間的連線。再利用簡(jiǎn)單的向量之間角度進(jìn)行手勢(shì)識(shí)別。

整體的ncnn推理C++ 代碼實(shí)現(xiàn):

#include <string>
#include <vector>
#include "iostream"  
#include<cmath>

// ncnn
#include "ncnn/layer.h"
#include "ncnn/net.h"
#include "ncnn/benchmark.h"

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <opencv2/imgproc.hpp>
#include "opencv2/opencv.hpp"  

using namespace std;
using namespace cv;

static ncnn::UnlockedPoolAllocator g_blob_pool_allocator;
static ncnn::PoolAllocator g_workspace_pool_allocator;

static ncnn::Net yolov5;
static ncnn::Net hand_keyPoints;

class YoloV5Focus : public ncnn::Layer
{
public:
 YoloV5Focus()
 {
  one_blob_only = true;
 }

 virtual int forward(const ncnn::Mat& bottom_blob, ncnn::Mat& top_blob, const ncnn::Option& opt) const
 
{
  int w = bottom_blob.w;
  int h = bottom_blob.h;
  int channels = bottom_blob.c;

  int outw = w / 2;
  int outh = h / 2;
  int outc = channels * 4;

  top_blob.create(outw, outh, outc, 4u1, opt.blob_allocator);
  if (top_blob.empty())
   return -100;
#pragma omp parallel for num_threads(opt.num_threads)
  for (int p = 0; p < outc; p++)
  {
   const float* ptr = bottom_blob.channel(p % channels).row((p / channels) % 2) + ((p / channels) / 2);
   float* outptr = top_blob.channel(p);

   for (int i = 0; i < outh; i++)
   {
    for (int j = 0; j < outw; j++)
    {
     *outptr = *ptr;

     outptr += 1;
     ptr += 2;
    }

    ptr += w;
   }
  }
  return 0;
 }
};

DEFINE_LAYER_CREATOR(YoloV5Focus)
struct Object
{

 float x;
 float y;
 float w;
 float h;
 int label;
 float prob;
};

static inline float intersection_area(const Object& a, const Object& b)
{
 if (a.x > b.x + b.w || a.x + a.w < b.x || a.y > b.y + b.h || a.y + a.h < b.y)
 {
  // no intersection
  return 0.f;
 }

 float inter_width = std::min(a.x + a.w, b.x + b.w) - std::max(a.x, b.x);
 float inter_height = std::min(a.y + a.h, b.y + b.h) - std::max(a.y, b.y);
 return inter_width * inter_height;
}

static void qsort_descent_inplace(std::vector<Object>& faceobjects, int left, int right)
{
 int i = left;
 int j = right;
 float p = faceobjects[(left + right) / 2].prob;
 while (i <= j)
 {
  while (faceobjects[i].prob > p)
   i++;

  while (faceobjects[j].prob < p)
   j--;

  if (i <= j)
        {
   std::swap(faceobjects[i], faceobjects[j]);

   i++;
   j--;
  }
 }

#pragma omp parallel sections
 {
#pragma omp section
  {
   if (left < j) qsort_descent_inplace(faceobjects, left, j);
  }
#pragma omp section
  {
   if (i < right) qsort_descent_inplace(faceobjects, i, right);
  }
 }
}

static void qsort_descent_inplace(std::vector<Object>& faceobjects)
{
 if (faceobjects.empty())
  return;

 qsort_descent_inplace(faceobjects, 0, faceobjects.size() - 1);
}

static void nms_sorted_bboxes(const std::vector<Object>& faceobjects, std::vector<int>& picked, float nms_threshold)
{
 picked.clear();

 const int n = faceobjects.size();

 std::vector<floatareas(n);
 for (int i = 0; i < n; i++)
 {
  areas[i] = faceobjects[i].w * faceobjects[i].h;
 }
 for (int i = 0; i < n; i++)
 {
  const Object& a = faceobjects[i];

  int keep = 1;
  for (int j = 0; j < (int)picked.size(); j++)
  {
   const Object& b = faceobjects[picked[j]];
   float inter_area = intersection_area(a, b);
   float union_area = areas[i] + areas[picked[j]] - inter_area;
   // float IoU = inter_area / union_area
   if (inter_area / union_area > nms_threshold)
    keep = 0;
  }

  if (keep)
   picked.push_back(i);
 }
}

static inline float sigmoid(float x)
{
 return static_cast<float>(1.f / (1.f + exp(-x)));
}

static void generate_proposals(const ncnn::Mat& anchors, int stride, const ncnn::Mat& in_pad, const ncnn::Mat& feat_blob, float prob_threshold, std::vector<Object>& objects)
{
 const int num_grid = feat_blob.h;

 int num_grid_x;
 int num_grid_y;
 if (in_pad.w > in_pad.h)
 {
  num_grid_x = in_pad.w / stride;
  num_grid_y = num_grid / num_grid_x;
 }
 else
 {
  num_grid_y = in_pad.h / stride;
  num_grid_x = num_grid / num_grid_y;
 }

 const int num_class = feat_blob.w - 5;

 const int num_anchors = anchors.w / 2;
 for (int q = 0; q < num_anchors; q++)
 {
  const float anchor_w = anchors[q * 2];
  const float anchor_h = anchors[q * 2 + 1];

  const ncnn::Mat feat = feat_blob.channel(q);

  for (int i = 0; i < num_grid_y; i++)
  {
   for (int j = 0; j < num_grid_x; j++)
   {
    const float* featptr = feat.row(i * num_grid_x + j);

    // find class index with max class score
    int class_index = 0;
    float class_score = -FLT_MAX;
    for (int k = 0; k < num_class; k++)
    {
     float score = featptr[5 + k];
     if (score > class_score)
     {
      class_index = k;
      class_score = score;
     }
    }

    float box_score = featptr[4];

    float confidence = sigmoid(box_score) * sigmoid(class_score);
                
    if (confidence >= prob_threshold)
    {
     float dx = sigmoid(featptr[0]);
     float dy = sigmoid(featptr[1]);
     float dw = sigmoid(featptr[2]);
     float dh = sigmoid(featptr[3]);

     float pb_cx = (dx * 2.f - 0.5f + j) * stride;
     float pb_cy = (dy * 2.f - 0.5f + i) * stride;
     float pb_w = pow(dw * 2.f2) * anchor_w;
     float pb_h = pow(dh * 2.f2) * anchor_h;

     float x0 = pb_cx - pb_w * 0.5f;
     float y0 = pb_cy - pb_h * 0.5f;
     float x1 = pb_cx + pb_w * 0.5f;
     float y1 = pb_cy + pb_h * 0.5f;
     Object obj;
     obj.x = x0;
     obj.y = y0;
     obj.w = x1 - x0;
     obj.h = y1 - y0;
     obj.label = class_index;
     obj.prob = confidence;

     objects.push_back(obj);
    }
   }
  }
 }
}

extern "C" {

 void release()
 
{
  fprintf(stderr"YoloV5Ncnn finished!");
 }

 int init_handKeyPoint() {
  ncnn::Option opt;
  opt.lightmode = true;
  opt.num_threads = 4;
  opt.blob_allocator = &g_blob_pool_allocator;
  opt.workspace_allocator = &g_workspace_pool_allocator;
  opt.use_packing_layout = true;
  fprintf(stderr"handKeyPoint init!\n");
  hand_keyPoints.opt = opt;
  int ret_hand = hand_keyPoints.load_param("squeezenet1_1.param");  //squeezenet1_1   resnet_50
  if (ret_hand != 0) {
   std::cout << "ret_hand:" << ret_hand << std::endl;
  }
  ret_hand = hand_keyPoints.load_model("squeezenet1_1.bin");  //squeezenet1_1   resnet_50
  if (ret_hand != 0) {
   std::cout << "ret_hand:" << ret_hand << std::endl;
  }

  return 0;
 }
 int init()
 
{
  fprintf(stderr"YoloV5sNcnn init!\n");
  ncnn::Option opt;
  opt.lightmode = true;
  opt.num_threads = 4;
  opt.blob_allocator = &g_blob_pool_allocator;
  opt.workspace_allocator = &g_workspace_pool_allocator;
  opt.use_packing_layout = true;
  yolov5.opt = opt;

  yolov5.register_custom_layer("YoloV5Focus", YoloV5Focus_layer_creator);

  // init param
  {
   int ret = yolov5.load_param("yolov5s.param");  
   if (ret != 0)
   {
    std::cout << "ret= " << ret << std::endl;
    fprintf(stderr"YoloV5Ncnn, load_param failed");
    return -301;
   }
  }

  // init bin
  {
   int ret = yolov5.load_model("yolov5s.bin");  
   if (ret != 0)
   {
    fprintf(stderr"YoloV5Ncnn, load_model failed");
    return -301;
   }
  }

  return 0;
 }
 int detect(cv::Mat img, std::vector<Object> &objects)
 
{

  double start_time = ncnn::get_current_time();
  const int target_size = 320;

  const int width = img.cols;
  const int height = img.rows;
  int w = img.cols;
  int h = img.rows;
  float scale = 1.f;
  if (w > h)
  {
   scale = (float)target_size / w;
   w = target_size;
   h = h * scale;
  }
  else
  {
   scale = (float)target_size / h;
   h = target_size;
   w = w * scale;
  }
  cv::resize(img, img, cv::Size(w, h));
  ncnn::Mat in = ncnn::Mat::from_pixels(img.data, ncnn::Mat::PIXEL_BGR2RGB, w, h);
  int wpad = (w + 31) / 32 * 32 - w;
  int hpad = (h + 31) / 32 * 32 - h;
  ncnn::Mat in_pad;
  ncnn::copy_make_border(in, in_pad, hpad / 2, hpad - hpad / 2, wpad / 2, wpad - wpad / 2, ncnn::BORDER_CONSTANT, 114.f);
        
  {
   const float prob_threshold = 0.4f;
   const float nms_threshold = 0.51f;

   const float norm_vals[3] = { 1 / 255.f1 / 255.f1 / 255.f };
   in_pad.substract_mean_normalize(0, norm_vals);

   ncnn::Extractor ex = yolov5.create_extractor();
      ex.input("images", in_pad);
   std::vector<Object> proposals;
   {
    ncnn::Mat out;
    ex.extract("output", out);
    ncnn::Mat anchors(6);
    anchors[0] = 10.f;
    anchors[1] = 13.f;
    anchors[2] = 16.f;
    anchors[3] = 30.f;
    anchors[4] = 33.f;
    anchors[5] = 23.f;
    std::vector<Object> objects8;
    generate_proposals(anchors, 8, in_pad, out, prob_threshold, objects8);

    proposals.insert(proposals.end(), objects8.begin(), objects8.end());
   }
   
            {
    ncnn::Mat out;
    ex.extract("771", out);

    ncnn::Mat anchors(6);
    anchors[0] = 30.f;
    anchors[1] = 61.f;
    anchors[2] = 62.f;
    anchors[3] = 45.f;
    anchors[4] = 59.f;
    anchors[5] = 119.f;
                
    std::vector<Object> objects16;
    generate_proposals(anchors, 16, in_pad, out, prob_threshold, objects16);

    proposals.insert(proposals.end(), objects16.begin(), objects16.end());
   }
   {
    ncnn::Mat out;
    ex.extract("791", out);
    ncnn::Mat anchors(6);
    anchors[0] = 116.f;
    anchors[1] = 90.f;
    anchors[2] = 156.f;
    anchors[3] = 198.f;
    anchors[4] = 373.f;
    anchors[5] = 326.f;
    std::vector<Object> objects32;
    generate_proposals(anchors, 32, in_pad, out, prob_threshold, objects32);

    proposals.insert(proposals.end(), objects32.begin(), objects32.end());
   }

   // sort all proposals by score from highest to lowest
   qsort_descent_inplace(proposals);
   std::vector<int> picked;
   nms_sorted_bboxes(proposals, picked, nms_threshold);

   int count = picked.size();
   objects.resize(count);
   for (int i = 0; i < count; i++)
   {
    objects[i] = proposals[picked[i]];
    float x0 = (objects[i].x - (wpad / 2)) / scale;
    float y0 = (objects[i].y - (hpad / 2)) / scale;
    float x1 = (objects[i].x + objects[i].w - (wpad / 2)) / scale;
    float y1 = (objects[i].y + objects[i].h - (hpad / 2)) / scale;

    // clip
    x0 = std::max(std::min(x0, (float)(width - 1)), 0.f);
    y0 = std::max(std::min(y0, (float)(height - 1)), 0.f);
    x1 = std::max(std::min(x1, (float)(width - 1)), 0.f);
    y1 = std::max(std::min(y1, (float)(height - 1)), 0.f);
    objects[i].x = x0;
    objects[i].y = y0;
    objects[i].w = x1;
    objects[i].h = y1;
   }
  }

  return 0;
 }
}

static const char* class_names[] = {"hand"};

void draw_face_box(cv::Mat& bgr, std::vector<Object> object)
{
 for (int i = 0; i < object.size(); i++)
 {
  const auto obj = object[i];
  cv::rectangle(bgr, cv::Point(obj.x, obj.y), cv::Point(obj.w, obj.h), cv::Scalar(02550), 380);
  std::cout << "label:" << class_names[obj.label] << std::endl;
  string emoji_path = "emoji\\" + string(class_names[obj.label]) + ".png";
  cv::Mat logo = cv::imread(emoji_path);
  if (logo.empty()) {
   std::cout << "imread logo failed!!!" << std::endl;
   return;
  }
  resize(logo, logo, cv::Size(8080));
  cv::Mat imageROI = bgr(cv::Range(obj.x, obj.x + logo.rows), cv::Range(obj.y, obj.y + logo.cols));
  logo.copyTo(imageROI);
 }

}

static int detect_resnet(const cv::Mat& bgr,std::vector<float>& output) {
 ncnn::Mat in = ncnn::Mat::from_pixels_resize(bgr.data,ncnn::Mat::PIXEL_RGB,bgr.cols,bgr.rows,256,256);

 const float mean_vals[3] = { 104.f,117.f,123.f };//
 const float norm_vals[3] = { 1/255.f1/255.f1/255.f };//1/255.f
 in.substract_mean_normalize(mean_vals, norm_vals);  //0  mean_vals, norm_vals

 ncnn::Extractor ex = hand_keyPoints.create_extractor();

 ex.input("input", in);
 ncnn::Mat out;
 ex.extract("output",out);
 
 std::cout << "out.w:" << out.w <<" out.h: "<< out.h <<std::endl;
 output.resize(out.w);
 for (int i = 0; i < out.w; i++) {
  output[i] = out[i];
 }

 return 0;
}
float vector_2d_angle(cv::Point p1,cv::Point p2) {
 //求解二維向量的角度
 float angle = 0.0;
 try {
  float radian_value = acos((p1.x*p2.x+p1.y*p2.y)/(sqrt(p1.x*p1.x+p1.y*p1.y)*sqrt(p2.x*p2.x+p2.y*p2.y)));
  angle = 180*radian_value/3.1415;
 }catch(...){
  angle = 65535.;
 }
 if (angle > 180.) {
  angle = 65535.;
 }

 return angle;
}

std::vector<floathand_angle(std::vector<int>& hand_x,std::vector<int>& hand_y) {
 //獲取對(duì)應(yīng)手相關(guān)向量的二維角度,根據(jù)角度確定手勢(shì)


 float angle = 0.0;
 std::vector<float> angle_list;
 //------------------- thumb 大拇指角度
 angle = vector_2d_angle(cv::Point((hand_x[0]-hand_x[2]),(hand_y[0]-hand_y[2])),cv::Point((hand_x[3]-hand_x[4]),(hand_y[3]-hand_y[4])));
 angle_list.push_back(angle);

 //--------------------index 食指角度
 angle = vector_2d_angle(cv::Point((hand_x[0] - hand_x[6]), (hand_y[0] - hand_y[6])), cv::Point((hand_x[7] - hand_x[8]), (hand_y[7] - hand_y[8])));
 angle_list.push_back(angle);

 //---------------------middle  中指角度
 angle = vector_2d_angle(cv::Point((hand_x[0] - hand_x[10]), (hand_y[0] - hand_y[10])), cv::Point((hand_x[11] - hand_x[12]), (hand_y[11] - hand_y[12])));
 angle_list.push_back(angle);

 //----------------------ring 無(wú)名指角度
 angle = vector_2d_angle(cv::Point((hand_x[0] - hand_x[14]), (hand_y[0] - hand_y[14])), cv::Point((hand_x[15] - hand_x[16]), (hand_y[15] - hand_y[16])));
 angle_list.push_back(angle);

 //-----------------------pink 小拇指角度
 angle = vector_2d_angle(cv::Point((hand_x[0] - hand_x[18]), (hand_y[0] - hand_y[18])), cv::Point((hand_x[19] - hand_x[20]), (hand_y[19] - hand_y[20])));
 angle_list.push_back(angle);
 return angle_list;
}

string h_gestrue(std::vector<float>& angle_lists) {
 //二維約束的方式定義手勢(shì)
 //fist five gun love one six three thumbup yeah
 float thr_angle = 65.;
 float thr_angle_thumb = 53.;
 float thr_angle_s = 49.;
 string gesture_str;
 bool flag = false;
 for (int i = 0; i < angle_lists.size(); i++) {
  if (abs(65535 - int(angle_lists[i])) > 0) {
   flag = true;   //進(jìn)入手勢(shì)判斷標(biāo)識(shí)
  }
 }
 std::cout << "flag:" << flag << std::endl;
 if (flag) {
  if (angle_lists[0] > thr_angle_thumb && angle_lists[1] > thr_angle 
   && angle_lists[2] > thr_angle && angle_lists[3] > thr_angle 
   && angle_lists[4] > thr_angle) {
   gesture_str = "fist";
  }
  else if (angle_lists[0] < thr_angle_s && angle_lists[1] < thr_angle_s
   && angle_lists[2] < thr_angle_s && angle_lists[3] < thr_angle_s
   && angle_lists[4] < thr_angle_s) {
   gesture_str = "five";
  }
  else if(angle_lists[0] < thr_angle_s && angle_lists[1] < thr_angle_s
   && angle_lists[2] > thr_angle && angle_lists[3] > thr_angle
   && angle_lists[4] > thr_angle){
   gesture_str = "gun";
  }
  else if (angle_lists[0] < thr_angle_s && angle_lists[1] < thr_angle_s
   && angle_lists[2] > thr_angle && angle_lists[3] > thr_angle
   && angle_lists[4] < thr_angle_s) {
   gesture_str = "love";
  }
  else if (angle_lists[0] < 5 && angle_lists[1] < thr_angle_s
   && angle_lists[2] > thr_angle && angle_lists[3] > thr_angle
   && angle_lists[4] > thr_angle) {
   gesture_str = "one";
  }
  else if (angle_lists[0] < thr_angle_s && angle_lists[1] > thr_angle
   && angle_lists[2] > thr_angle && angle_lists[3] > thr_angle
   && angle_lists[4] < thr_angle_s) {
   gesture_str = "six";
  }
  else if (angle_lists[0] > thr_angle_thumb && angle_lists[1] < thr_angle_s
   && angle_lists[2] < thr_angle_s && angle_lists[3] < thr_angle_s
   && angle_lists[4] > thr_angle) {
   gesture_str = "three";
  }
  else if (angle_lists[0] < thr_angle_s && angle_lists[1] > thr_angle
   && angle_lists[2] > thr_angle && angle_lists[3] > thr_angle
   && angle_lists[4] > thr_angle) {
   gesture_str = "thumbUp";
  }
  else if (angle_lists[0] > thr_angle_thumb && angle_lists[1] < thr_angle_s
   && angle_lists[2] < thr_angle_s && angle_lists[3] > thr_angle
   && angle_lists[4] > thr_angle) {
   gesture_str = "two";
  }
 
 }
 return gesture_str;
}

int main()
{
 Mat frame;
 VideoCapture capture(0);
 init();
 init_handKeyPoint();
 while (true)
 {
  capture >> frame;            
  if (!frame.empty()) {          
   std::vector<Object> objects;
   detect(frame, objects);

   std::vector<float> hand_output;
   for (int j = 0; j < objects.size(); ++j) {
    cv::Mat handRoi;
    int x, y, w, h;
    try {
     x = (int)objects[j].x < 0 ? 0 : (int)objects[j].x;
     y = (int)objects[j].y < 0 ? 0 : (int)objects[j].y;
     w = (int)objects[j].w < 0 ? 0 : (int)objects[j].w;
     h = (int)objects[j].h < 0 ? 0 : (int)objects[j].h;

     if (w > frame.cols){
      w = frame.cols;
     }
     if (h > frame.rows) {
      h = frame.rows;
     }
                
    }
    catch (cv::Exception e) {
        
    }

    //把手區(qū)域向外擴(kuò)30個(gè)像素
    x = max(0, x - 30);
    y = max(0, y - 30);
    int w_ = min(w - x + 30640);
    int h_ = min(h - y + 30480);
    cv::Rect roi(x,y,w_,h_);
    handRoi = frame(roi);
    cv::resize(handRoi,handRoi,cv::Size(256,256));
    //detect_resnet(handRoi, hand_output);
    detect_resnet(handRoi, hand_output);

    std::vector<float> angle_lists;
    string gesture_string;
    std::vector<int> hand_points_x;  //
    std::vector<int> hand_points_y;

    for (int k = 0; k < hand_output.size()/2; k++) {
     int x = int(hand_output[k * 2 + 0] * handRoi.cols);//+int(roi.x)-1;
     int y = int(hand_output[k * 2 + 1] * handRoi.rows);// +int(roi.y) - 1;

     //x1 = x1 < 0 ? abs(x1) : x1;
     //x2 = x2 < 0 ? abs(x2) : x2;
     hand_points_x.push_back(x);
     hand_points_y.push_back(y);
     std::cout << "x1: " << x << " x2: " << y << std::endl;
     cv::circle(handRoi, cv::Point(x,y), 3, (02550), 3);
     cv::circle(handRoi, cv::Point(x,y), 3, (02550), 3);
                    
    }
                
    cv::line(handRoi, cv::Point(hand_points_x[0], hand_points_y[0]), cv::Point(hand_points_x[1], hand_points_y[1]), cv::Scalar(25500), 3);
    cv::line(handRoi, cv::Point(hand_points_x[1], hand_points_y[1]), cv::Point(hand_points_x[2], hand_points_y[2]), cv::Scalar(25500), 3);
    cv::line(handRoi, cv::Point(hand_points_x[2], hand_points_y[2]), cv::Point(hand_points_x[3], hand_points_y[3]), cv::Scalar(25500), 3);
                
    cv::line(handRoi, cv::Point(hand_points_x[3], hand_points_y[3]), cv::Point(hand_points_x[4], hand_points_y[4]), cv::Scalar(25500), 3);

    cv::line(handRoi, cv::Point(hand_points_x[0], hand_points_y[0]), cv::Point(hand_points_x[5], hand_points_y[5]), cv::Scalar(02550), 3);
    cv::line(handRoi, cv::Point(hand_points_x[5], hand_points_y[5]), cv::Point(hand_points_x[6], hand_points_y[6]), cv::Scalar(02550), 3);
    cv::line(handRoi, cv::Point(hand_points_x[6], hand_points_y[6]), cv::Point(hand_points_x[7], hand_points_y[7]), cv::Scalar(02550), 3);
    cv::line(handRoi, cv::Point(hand_points_x[7], hand_points_y[7]), cv::Point(hand_points_x[8], hand_points_y[8]), cv::Scalar(02550), 3);

    cv::line(handRoi, cv::Point(hand_points_x[0], hand_points_y[0]), cv::Point(hand_points_x[9], hand_points_y[9]), cv::Scalar(00255), 3);
    cv::line(handRoi, cv::Point(hand_points_x[9], hand_points_y[9]), cv::Point(hand_points_x[10], hand_points_y[10]), cv::Scalar(00255), 3);
    cv::line(handRoi, cv::Point(hand_points_x[10], hand_points_y[10]), cv::Point(hand_points_x[11], hand_points_y[11]), cv::Scalar(00255), 3);
    cv::line(handRoi, cv::Point(hand_points_x[11], hand_points_y[11]), cv::Point(hand_points_x[12], hand_points_y[12]), cv::Scalar(00255), 3);

          cv::line(handRoi, cv::Point(hand_points_x[0], hand_points_y[0]), cv::Point(hand_points_x[13], hand_points_y[13]), cv::Scalar(25500), 3);
    cv::line(handRoi, cv::Point(hand_points_x[13], hand_points_y[13]), cv::Point(hand_points_x[14], hand_points_y[14]), cv::Scalar(25500), 3);
    cv::line(handRoi, cv::Point(hand_points_x[14], hand_points_y[14]), cv::Point(hand_points_x[15], hand_points_y[15]), cv::Scalar(25500), 3);
    cv::line(handRoi, cv::Point(hand_points_x[15], hand_points_y[15]), cv::Point(hand_points_x[16], hand_points_y[16]), cv::Scalar(25500), 3);

    cv::line(handRoi, cv::Point(hand_points_x[0], hand_points_y[0]), cv::Point(hand_points_x[17], hand_points_y[17]), cv::Scalar(02550), 3);
    cv::line(handRoi, cv::Point(hand_points_x[17], hand_points_y[17]), cv::Point(hand_points_x[18], hand_points_y[18]), cv::Scalar(02550), 3);
                
    cv::line(handRoi, cv::Point(hand_points_x[18], hand_points_y[18]), cv::Point(hand_points_x[19], hand_points_y[19]), cv::Scalar(02550), 3);
    cv::line(handRoi, cv::Point(hand_points_x[19], hand_points_y[19]), cv::Point(hand_points_x[20], hand_points_y[20]), cv::Scalar(02550), 3);
                
    angle_lists =  hand_angle(hand_points_x, hand_points_y);
    gesture_string = h_gestrue(angle_lists);

    std::cout << "getsture_string:" << gesture_string << std::endl;
    cv::putText(handRoi,gesture_string,cv::Point(30,30),cv::FONT_HERSHEY_COMPLEX,1, cv::Scalar(0255255), 110);
    cv::imshow("handRoi", handRoi);
    cv::waitKey(10);
    angle_lists.clear();
    hand_points_x.clear();
    hand_points_y.clear();

   }
  }
  if (cv::waitKey(20) == 'q')    
   break;
 }

 capture.release();     

 return 0;
}               

五、視頻展示


整理不易,點(diǎn)三連
瀏覽 49
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)
評(píng)論
圖片
表情
推薦
點(diǎn)贊
評(píng)論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 中文字幕三级av片| 免费黄网站在线观看| 麻豆视频在线免费观看| 国产成人视频| 亚洲天堂免费| 在线视频免费观看| 国产免费av片| 另类老妇奶性BBWBBwBBw| 亚洲无码免费在线视频| 国产欧美二区综合中文字幕精品一 | 无码成人av| 超碰97av| 男人视频网| 亚洲成人精品一区| 欧一美一伦一A片| 欧美一区| 人人插人人| 人妻体内射精一区二区| 久草手机视频| 天堂俺去俺来也www久久婷婷 | 人人干超碰| 国产午夜福利免费视频在线观看 | 久久青草免费视频| 骚逼国产| 亚洲高潮| 九九热无码| 亚洲小电影| 国产av影视| 少妇嫩搡BBBB搡BBBB| 91午夜视频| 中日韩特黄A片免费视频| 在线观看免费一区| 国产一区二区在线播放| 性爱AV网| 精品成人无码一区二区三区| 伊人操逼网| 日韩女人性爱| 日韩高清在线观看| 91无码精品| 囯产精品久久久久久久久久| 国产深夜福利| 色综合久久天天综合网| 黑人狂躁女人高潮视频| 欧美伦妇AAAAAA片| 国产无码AV在线| 亚洲一区久久| 九九九av| 国产中文字幕在线免费观看 | 久久五月婷| 九九成人视频| 国产色无码网站www色视频| 粉嫩小泬BBBBBB免费| 国产久久精品| 超碰在线视| 成人黄色免费看| 男人天堂视频网站| 夜夜骚av.一区二区三区四区| 九九九av| 国产一级a免一级a免费| www.久久精品视频| 屁屁影院CCYYCOM国产| 午夜久| 成人才看的在线视频| 狠狠色噜噜狠狠狠7777米奇网| 小黄片高清无码| 人人妻人人澡人人爽久久| 亚洲视频日韩在线观看| 国产三级片在线观看| 二区无码| 日韩性爱在线| 国产成人精品AV在线观| 大香蕉人妻| 欧一美一婬一伦一区| 动漫3d啪啪成人h动漫| 91小宝寻花一区二区三区三级| 青娱乐无码| 黄色影片在线观看| 亚洲无码网址| 91亚洲在线| 超碰在线观看91| 午夜黄色福利| 色444| 国产视频99| 婷婷丁香激情| 亚洲天堂2017| 九九热精品视频在线播放| 日毛片| 国产精品无码永久免费不卡| 中文字幕+乱码+中文乱码www | 国产欧美日本视频| 综合五月婷婷| 亚洲精品乱码久久久久久蜜桃欧美 | 亚洲中文字幕人妻。| 婷婷激情丁香五月天| 欧美专区一区| 黄色成人视频网站在线观看| 免费AV播放| 亲子乱AV一区二区| 翔田千里av在线| 亚洲AV永久无码国产精品久久| 日本欧美中文字幕| 久久国产2025| yjizz视频网| 免费黄色一级视频| 日日99| 波多野结衣大战黑人| 在线a免费| 露脸老熟女91集合| 婷婷五月一区| 亚洲免费小视频| 国产欧美精品一区二区| 人人妻人人澡人人爽人人欧美一区 | 久大香蕉| 国产av中文字幕| 人人妻人人澡人人爽人人欧美一区 | 99色综合| 99在线视频免费观看| 欧美草逼| 精品一区二区三区三区| 四虎影院人妻| 丰满无码| 一级婬片A片AAAAA毛片| 国产18禁网站| 亚洲精品视频免费在线观看| 求欧美精品网址| 特级西西444www精品视频| 18禁黄色免费网站| 91欧美视频| 四川少扫搡BBw搡BBBB| 苍井空无码| 久久99精品国产| 国产欧美一区二区三区视频| 国产A片精品| 久久精品视频在线免费观看| 婷婷日韩在线| 色哟哟一中文字慕| 在线免费看黄网站| 人人操人人摸人人爱| 成人激情在线观看| 东方av在线观看| 一级片免费观看| 亚洲精品乱码久久久久久按摩观 | igao视频| 波多野结衣无码视频在线观看| 波多野结衣高清无码| 一道本一区二区三区免费视频| A级视频网| 永久免费叼嘿| 在线亚洲AV| 奇米88888| 中国黄色大片| 青青草大香蕉| av免费网站| 国产免费成人| 91在线观看免费视频| 亚洲性爱小说网址| 欧美日韩亚洲天堂| 国产原创精品| 无码A∨| 日韩在线小视频| 亚洲成人性爱av| 日本成人免费电影| 91原创国产内射| 日本免费无码| 少妇黄色视频| 影音先锋自拍| 北条麻妃无码精品AV怎么看| 欧美老女人逼| www.久热| 亚洲无码一二三| 亚洲国产精品久久人人爱| 免费看操逼视频| 久久99久久99久久| 日本少妇高潮喷水XXXXXXX| 亚洲精品二| 伊人影院久久| 丁香五月色情| 人人色人人| 欧美撸一撸| 你懂得视频在线观看| 亚洲精品国产成人AV在线| 91网在线| 男女午夜福利| 少妇在厨房| 老太色HD色老太HD.| 青青操视频在线| 成人A片免费视频| 北条麻妃人妻中文无码| 日韩精品三区| 欧美XXXXBBBB| 另类国产| 日韩精品一区二区在线观看| 日韩欧美国产精品综合嫩V| 成人亚洲A片V一区二区三区蜜月| 青青草免费公开视频| 玩弄大乳乳妾高潮乳喷视频| 日本一区二区精品| 超碰成人在线免费观看| 久久久久久高清毛片一级| www.天天日| 天天干天天撸影视| 夜夜爽夜夜| 超碰伊人大香蕉| 日韩高清av| 中文字幕无码在线| 欧美大胆视频| 亚洲三级电影在线观看| 亚洲精品911| 日韩成人中文字幕| 影音先锋成人视频| 国产午夜精品一区二区三区嫩A | 亚洲一区在线视频| 在线观看黄a| 国产精品V日韩精品V在线观看 | 色资源站| 欧美国产综合| 青吴乐大香蕉| 欧美自拍第一页| 久久超碰精品| 无码精品视频| 国产精品一级无码免费播放| 91探花在线播放| 日日干天天射| 青娱乐超碰| 黄色网址在线观看视频| 69av在线观看视频| 男人天堂V| 亚洲影院中文字幕| 蜜桃人妻无码AV天堂三区| 3344在线观看免费下载视频| 玖玖在线| 在线观看免费黄视频| 中文字幕一区二区三区在线观看| 国产高清一区二区三区| 日本女优婷婷青青草原| 人人舔人人草| 欧美日韩东京热| www.四虎成人网站| 蜜桃在线无码| 黄色片视频| 国产a片| 狠狠精品| 欧美一区三区| 伊人导航| 欧美精品xxx| 日韩成人免费在线观看| 在线观看黄色AV| 亚洲精品欧美久久婷婷| 大地影视官网第三页入口| 国产无码播放| 亚洲视频免费在线观看| 欧美XX888做受| 欧美日韩精品一区| 国产成人一区二区| 911国产视频| 麻豆黄色片| 天堂中文在线观看| 国产欧美综合在线观看| 麻豆AV无码| 国产精品秘久久久久久久久| 色99在线| 亚洲高清无码在线免费观看| 91在线视频免费观看| 北条麻妃九九九在线视频| 国产色呦呦| 丁香六月婷婷综合| 国产精品自在线| 岛国AV在线播放| 一区二区三区四区无码| 日韩欧美高清无码| 激情视频在线免费观看| 性感成人在线| 91视频网站免费| 97成人人妻一区二区三区| 午夜无码鲁丝片午夜精品一区二区 | 亚洲人妻系列| 黄片av| 日本一级片免费看| 91人妻人人人人爽| 久久99久久99久久| 九九九九九九精品| 水蜜桃一曲二区| 日本色影院| 亚洲40p| 精品秘无码一区二区三区老师| 97精品超碰一区二区三区| 亚洲最大视频| 欧美成人一区免费视频| 加勒比操逼| 人人妻人人| 日韩AV电影网| 青青草中文字幕| 男人色天堂| 丁香六月婷婷综合缴| 九九热热| 欧美一级无码| 国产一级二级视频| 大香蕉现在视频中心一| 91瑟瑟| 在线操| 国产波霸爆乳一区二区| 在线免费毛片| 伊人春色AV| 精品视频在线观看免费| 午夜免费视频| 中文字幕国产在线观看| 天天日天天射天天干| 无码不卡一区| 黄色电影网站在线观看| 激情淫荡少妇| 午夜性爱视频| 日韩黄色毛片| 无码人妻蜜桃| 欧美日韩国产高清| 国产人人爽| 在线免费毛片| 亚洲日韩免费在线观看| 日韩视频――中文字幕| 骚小姨子无码| 日韩三级片在线视频| 人人色人人爱| 粉嫩99精品99久久久久久特污 | 国产成人无码免费看片| 性欧美XXXX| A国产| 三级片日本在线| 日本中文字幕网站| 一级片在线播放| 国产毛片精品一区二区色欲黄A片| 亚洲成人av在线| 中文资源在线a| 五月婷婷一区| 91老熟| 色婷婷色五月| 成人综合激情| AV一区二区三区四区| 亚洲精品无码永久| 激情亚洲婷婷| 日本a一级片| 欧美国产日韩在线观看| 男人天堂中文字幕| av无码免费观看| 日逼片A| 操逼逼综合网| 亚洲AV无码成人精品区天堂小说| 91久久精品无码一区| 国产成人精品视频| 农村三级片| 国产精品123区| 草在线| 日本黄色免费网站| 在线aaa| 中文无码字幕| 亚洲视频91| 免费av网站| 丝袜一区二区三区| 白虎高清无码大尺度免费在线观看| 大香蕉尹人在线观看| 日韩性爱视频| 天天干在线观看| 亚洲AV无码成人精品区天堂小说| 99国产热| 免费在线观看中文字幕| 无码一区二区三区在线观看| 日本a一级片| 亚洲日韩欧美视频| 婷婷五月18永久免费视频| 色婷婷亚洲婷婷| 人妻北条麻妃在线| 亚洲精品国产精品国自产曰本| 国产精品九九视频| 色五月综合网| 一区二区三区四区无码在线| 亚洲中文AV| 无码专区亚洲| 日韩免费视频在线观看| 欧美操逼在线| 国产黄色不卡| 69久久久| 国产女人18毛片水真多18| 99热这里只有精品1| 国产黄色一级电影| 自拍偷拍视频网址| 一级黄色视频片| 国产精品一级| 婷婷五月开心五月| 人妻无码A| 欧美国产日本| 激情五月婷婷网| 欧美精品在线播放| 日韩一级性爱视频| 午夜婷婷| 国产av三级片| 久久黄色A片| 尤物最新网址| 国精品无码一区二区三区在线秋菊| 肏屄免费视频| 五十路老国产| 久久午夜无码鲁丝片午夜精品偷窥 | 欧美熟妇性爱视频| 亚洲超碰在线| 苍井空视频| 嫩BBB嫩BBB嫩BBB| 大学生一级特黄大片| 人人操碰成人网| 日韩a片在线观看| 麻豆911精一区二区| 久久久久久| 国产精品秘ThePorn| 人妻电影亚洲av| AV在线影院| 人人看人人摸人人插| 婷婷久久综合久色综| 人人色在线观看| 高清中字无码| www.天天射| 无码69| 日本免费一区二区三区| 欧美午夜精品久久久久久3D| 亚洲无码A片在线| 人人操人人撸| 午夜三级无码| 4虎亚洲人成人网www| www.激情| 九九九九九九精品视频| 日本无码一区二区三三| 国产精品成人一区二区| 亚洲人成高清| 色婷婷综合久久久中文字幕| 亚洲日韩欧美中在线| AⅤ视频在线观看| 日本免费高清视频| 亚洲AV人人夜夜澡人人| mm131亚洲国产精品久久| 91精品免费| 色中色av| 中文字幕免费观看| 日韩一二三四区| 亚洲午夜激情| 欧美日韩在线免费观看| 亚洲国产成人91PORN| 中文字幕婷婷五月天| 日韩中文在线观看| 精品欧美一区二区三区久久久| 蜜桃人妻| 精品人妻一区二区三区含羞草| 久久久精品免费视频| 91视频美女| 91九色蝌蚪| 日韩熟妇无码中文字慕| 亚洲国产精品成人综合色在线婷婷| 国产18| 99re这里| 日韩第22页| 一本一道久久综合狠狠躁牛牛影视| 成人首页| 五月天成人导航| 99电影网手机在线观看| 欧美操逼视频网站| 99黄网| 91精品老司机| 超碰操逼| 人人看人人色| 日皮视频在线观看免费| 操比视频| 亚洲美女视频在线观看| 99精品国产热久久91色欲| 无码免费视频| 影音先锋日韩| 国产精品色情| 国产精品国产三级片| 超碰久热| 美女免费网站| 国语精品自拍| 韩国日本美国免费毛片| 国产在线拍揄自揄拍无码福利| 色色色热| 色就是亚洲| 无码一区二区三| 四lll少妇BBBB槡BBBB| 色欲成人网| 人人操人人干人人操| 双飞人妻13p| 亚洲.欧美.丝袜.中文.综合| 色情综合| 巨い巨乳の少妇あジed2k| 一区二区视频在线观看| 日本在线一区| 国产夫妻自拍av| 91麻豆免费视频网站| 国产精品久久精品| 国产亲子乱XXXXimim/| 欧美性爱在线网站| 8050午夜| 九色PORNY9l原创自拍| 青青青青青操| 久久六六| 一级无码专区| 日韩一级无码视频| 成人精品一区二区三区中文字幕 | 国产一区二区三区在线观看免费视频免费视频免费视频 | 久久久免费黄色视频| 日本草逼视频| 18禁一区| 欧美日韩在线视频免费| 久草大香蕉在线视频| 超碰欧美| 超碰在线看| 熟女人妻ThePorn| 18精品爽视频| 中韩AV在线免费观看| 青青草99| 国产精品婷婷午夜在线观看| 另类老妇极品BBWBBw| 韩国精品一区| 岛国AV在线| 欧美精品久久久久| 精品蜜桃秘一区二区三区在线播放| 亚洲电影免费观看| 久操综合视频在线| 乱子伦国产精品| 成人超碰| 精品少妇人妻一区二区| 操逼免费观看视频| 91麻豆精品A片国产在线观看| 山东wBBBB搡wBBBB| 久久精品亚洲无码| 狠狠狠狠狠狠狠狠狠| 91丨国产丨白丝| 黄工厂精品视频在线播| 老熟女痒到不行-ThePorn | 伊人色色色| 韩国色情中文字幕| 91亚洲成人| a片在线免费看| 国产伦精品一区二区三区视频女 | 国产AV电影网| 国产性精品| 尤物视频在线播放| 高清国产mv在线观看| 亚洲精品久久久蜜桃| a级片在线观看| 精品国产999久久久免费| 日韩天堂av| 久久69| 日本高清黄色视频| 欧美aaa视频| 99色婷婷| 天天毛片| 黄网免费看| 天天操操| 日韩成人无码一区二区| 人妻少妇无码精品| AV黄色片| 欧美性爱XXXX黑人XYX性爽 | 国产黄色片在线观看| www.蜜桃视频| 亚洲性爱视频| 欧美日韩一区在线观看| 亚洲国产精品成人综合色在线婷婷 | 无码秘蜜桃一区二区| 男女午夜福利| 五月丁香花| 日韩有码一区| 操美女大逼| 天堂AV网站| 亚洲中文字幕第一| 日本操鸡小视频| 91精东传媒果冻传媒| 欧美三级片网址| 农村少妇久久久久久久| 中国黄色学生妹一级片| 影音先锋在线视频观看| 久久久久一区二区三区| 作爱免费视频| 北条麻妃无码精品AV怎么看 | 人妻少妇精品视频一区二区三区 | 六月激情丁香| 水果派红桃AV解说| 欧美久草蜜桃视频| 日本高清视频网站网wwwwww | 99热这里只有精| AV无码一区二区三区| 一区二区三区四区无码在线| 久久久久久久久久久亚洲| 日韩在线中文字幕亚洲| 操逼的视频| 伊人干综合| 国产成人av在线播放| 99久| 国产三级片自拍| 中文字幕在线播放视频| 国产最新av| 国产精品自拍在线观看| 夜夜操夜夜撸| 日韩精彩视频| 色丁香视频在线观看的| 上海熟搡BBB搡BBBB| 欧美成人无码片免费看A片秀色| 中文字幕一区二区久久人妻| 日韩精品成人无码免费| 日韩性做爰免费A片AA片| 日韩不卡AV| 亚洲操逼电影| 亚洲一| 亚洲天堂中文| 午夜爱爱免费视频| 国产一二三区在线| 看欧美黄片| а√天堂中文最新版8| AV大香蕉| 国产AV福利| 影音先锋自拍| 欧美不卡| 国产精品扒开腿做爽爽爽A片唱戏 中文字幕一区二区三区精华液 | 热re99久久精品国产99热| 一本色道久久综合狠狠| a片视频免费观看| 欧美日韩国产不卡视频| 丁月婷婷五香天日五月天| 人妻夜夜爽天天爽三区麻豆AV网站| 五月婷婷丁香六月| 人人色综合| 日韩福利在线| 日本A∨| 免费网站观看www在线观看| 黄色视频在线观看国产| 黄色A片一级| 日韩怡春院| 国产精品啪啪视频| 日韩天堂网| 黄色电影天堂| 亚洲精品中文字幕成人片| 大香蕉这里只有精品| 国产成人欧美| 国产精品秘ThePorn| 人与禽一级A片一区二区三区| 无码国产+白浆| 午夜精品久久久久久久91蜜桃| 99re在线精品| 亚洲天堂国产视频| 成年人黄色视频| 日韩加勒比在线| 成年人黄色视频| 少妇人妻在线| 欧美日韩综合网| 亚洲中文字幕日韩精品| 91天天操| 在线观看AV资源| 亚洲成人高清在线| 激情久久综合| 成人免费视频一区二区三区| 深爱激情五月婷婷| 国产超碰青青草| 青娱乐成人电影| 北条麻妃三区| 国产白丝精品91爽爽久久| 五月六月婷婷| 9l视频自拍九色9l视频成人| A级片网站| 婷婷欧美日韩| 国产精品福利导航| 日韩在线看片| 日韩欧美成人在线视频| 国产TS变态重口人妖| 国产传媒精品| 欧美日韩国产成人在线| 手机在线观看av| 大荫蒂hd大荫蒂视频| 爆乳尤物一区二区三区| 大香蕉伊人在线观看视频| 人妻少妇一区二区三区| 99er视频| jizz在线观看视频| www色色| 五月丁香在线视频| 亚洲天天干| 91成人情欲影视网| 国产人妻一区二区三区欧美毛片| 免费在线观看中文字幕| 国产一级二级三级视频| 开心色播五月天| 精品操逼视频| 亚洲黑人av| 黑人毛片91久久久久久| 蜜臀AV午夜精品| 成人网站欧美| 亚洲日本中文| 中文字幕第一| 国产区AV| 7799精品| 人人妻人人草| 成人网在线观看| 激情亚洲| 国产熟女一区二区三区五月婷 | 国产欧美日韩在线播放| 色福利视频| 欧美午夜精品久久久久久3D| 日本熟妇高潮BBwBBwBBw| 成人无码一区二区三区| 亚洲中文字幕2025| 在线中文字幕视频| 99精品视频免费观看| 大鸡巴黄色视频免费观看| 中国A级片| 中文字幕无码A片久久| 久久99视频免费观看| 国产香蕉视频在线播放| 丁香网五月天| 69xx视频| 91丨国产丨熟女熟女| 口爆av| 日本无码嫩草一区二区| 人人妻人人操人人爽| 一区二区三区操逼| 亚洲俺去了| 狼友在线播放| 黑人大肉棒| 色色色色五月| 免费91视频| 三级精品| 香蕉伊人网| 青青草原在线视频| 精品国产乱子伦一区二区三区,小小扐| 亚洲日本一区二区三区| 97伊人超碰| 中文一线二线视频| 欧洲成人午夜精品无码区久久| 日韩AV片| 大香蕉在线网| 一本在线| 日本操鸡小视频| 亚洲美穴| 久久久久a| 国产亚洲中文| 99久在线精品99re8热| 性色网| 久草福利| 亚洲影视中文字幕| 高潮无码在线观看| 久久精品免费电影| 91丨露脸丨熟女抽搐| 最新在线中文字幕| 久色| 久久国产黄色一级片| 欧美啪啪视频| 天堂a在线8| 日木毛片| 亚洲欧美国产日韩字幕| 西西人体WW大胆无码| 国产性爱网站| 动漫日逼| 蜜桃91精品| 熟妇人妻中文| 久久噜噜噜精品国产亚洲综合| 国产成人精品免费视频| 人妻少妇av中文字幕乱码牛牛| 成人精品永久免费视频99久久精品 | 懂色AV一区二区三区国产中文在线| 自拍三级片| 男人的天堂黄色| 国产性爱精品影片免费看| 熟妇高潮一区二区高潮| 国产色色视频| 露脸老熟女91集合| 亚洲色欲色欲www在线成人网| 亚洲日韩一区二区| 浮力影院久久| 69AV电影| 91无码人妻一区二区成人aⅴ| 一级片在线视频| 午夜日韩| 韩国日本美国免费毛片| 日韩69视频| 五月婷婷六月婷婷| 人妻熟女一区二区| 成人黄色A片| 97色色得| 婷婷成人综合网| 北条麻妃波多波多野结衣| 特逼视频| 中文字幕亚洲有码| 无码精品一区二区三区在线播放| www.色色网| 91三级电影| 丰满少妇在线观看网站| 国产成人Av| 日本熟妇HD| 国产酒店自拍| 337p西西人体大胆瓣开下部 | 中文字幕在线网站| 亚洲成人少妇老妇a视频在线| 亚洲av高清| 七十路の高齢熟女千代子下载| 国产主播在线播放| 男女啪啪免费| 黄色电影一区二区三区| 欧美aaa在线| 亚洲中文字幕在线看| 日韩城人免费| 日韩人妻午夜| 免费黄色a片| 欧美五月激情| 无码aa| 亚洲区无码| 伊人久久无码| 日韩无码精品电影| 欧美不卡| 婷婷五月天在线电影| 91涩| 中文字幕免费在线播放| 亚洲热热| 久久婷婷青青| 日韩在线免费播放| 国产色情在线观看| 日本黄色免费网站| 岛国免费视频| 河南熟妇搡BBBB搡BBBB| 亚洲v天堂| 亚洲综合社区在线| 婷婷久久久久久| 中文字幕亚洲欧美| 国产在线秘麻豆精品观看| 青草成人在线视频| 婷婷无码成人精品俺来俺去| 先锋成人在线| 国产在线观看免费视频| 亚洲日韩一区二区三区| 午夜日逼网站| 中文字幕精品亚洲熟女| 无码视频在线播放| 香蕉国产在线| 免费观看一区二区三区| 成人精品三级AV在线看| 青青草手机视频在线| 91九色TS另类国产人妖| 狠狠穞A片一區二區三區| 91夫妻交友视频| 精品免费一区二区三区四区| 亚洲色综合久久五月| 婷婷操逼| 99在线小视频| 欧美日韩黄色片| 久色| 黄色一级片免费在线观看| 无码精品一区二区在线| 久草免费在线| 抽插逼| 国产亲子乱XXXXimim/| 高清国产mv在线观看| 91在线无码精品秘网站| 亚洲天堂网在线观看视频| 91人妻论坛| 91性爱小视频| 蜜桃Av噜噜一区二区三区四区| 内射久久| 三级乱伦86丝袜无码| 黄色AV免费观看| 天天骑夜夜操| 伊人激情| 日韩日韩日韩日韩日韩| 亚洲无码黄色| 亚洲133| 天堂8在线视频| 免费一级无码成人片| 日本高清视频网站网wwwwww | 国产日逼视频| 丁香五月综合啪啪| 国产婷婷色一区二区三区| 最新中文字幕一区| 色欲成人网| 日本欧美亚洲| AV无码精品| 中文字幕在线免费观看电影| 最近中文字幕免费MV第一季歌词怀孕 | 激情男人网| 国产AⅤ无码一区二区| 特级西西44www无码| 国产做受精品网站在线观看| 特黄色视频| 欧美自拍视频在线观看| 无码精品人妻一区二区欧美| 毛片久久久| 国产高清视频在线| 免费观看黄片视频| 精品久久ai| xiuxiuav| 婷婷五月天大香蕉| 潮喷在线| 免费看V片| 国产做爱| 无码视频免费观看| 乱伦激情视频| 亚洲精品一区二区三区在线观看| 五月天激情网址| 老司机视频在线视频18| 在线免费观看黄色| 久久精品婷婷| 中文在线字幕高清电视剧| 瘦精品无码一区二区三区四区五区六区七区八区 |