日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

PointNet++详解与代码

發(fā)布時間:2023/12/10 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PointNet++详解与代码 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在之前的一篇文章《PointNet:3D點集分類與分割深度學習模型》中分析了PointNet網(wǎng)絡是如何進行3D點云數(shù)據(jù)分類與分割的。但是PointNet存在的一個缺點是無法獲得局部特征,這使得它很難對復雜場景進行分析。在PointNet++中,作者通過兩個主要的方法進行了改進,使得網(wǎng)絡能更好的提取局部特征。第一,利用空間距離(metric space distances),使用PointNet對點集局部區(qū)域進行特征迭代提取,使其能夠學到局部尺度越來越大的特征。第二,由于點集分布很多時候是不均勻的,如果默認是均勻的,會使得網(wǎng)絡性能變差,所以作者提出了一種自適應密度的特征提取方法。通過以上兩種方法,能夠更高效的學習特征,也更有魯棒性。

(2021-1-27日補充):這是PointNet作者2021年分享的報告《3D物體檢測發(fā)展與未來》,對3D物體檢測感興趣的朋友可以看看。

【PointNet作者親述】90分鐘帶你了解3D物體檢測算法和未來方向!


補充:下面的視頻是PointNet++作者分享的報告《點云上的深度學習及其在三維場景理解中的應用》,里面有詳細介紹PointNet++(將門創(chuàng)投 | 斯坦福大學在讀博士生祁芮中臺:點云上的深度學習及其在三維場景理解中的應用_嗶哩嗶哩_bilibili)。

將門創(chuàng)投 | 斯坦福大學在讀博士生祁芮中臺:點云上的深度學習及其在三維場景理解中的應用

目錄

1.PointNet不足之處

2. PointNet++網(wǎng)絡結構

2.1 Sample layer

2.2 Grouping layer

2.3 PointNet layer

2.4 點云分布不一致的處理方法

2.5 Point Feature Propagation for Set Segmentation

2.6 Classification

2.7 Part Segmentation

2.8 Scene Segmentation

3. 參考資料


1.PointNet不足之處

在卷積神經(jīng)網(wǎng)絡中,3D CNN和2D CNN很像,也可以通過多級學習不斷進行提取,同時也具有著卷積的平移不變性。

而在PointNet中 網(wǎng)絡對每一個點做低維到高維的映射進行特征學習,然后把所有點映射到高維的特征通過最大池化最終表示全局特征。從本質上來說,要么對一個點做操作,要么對所有點做操作,實際上沒有局部的概念(loal context)同時也缺少local context 在平移不變性上也有局限性。(世界坐標系和局部坐標系)。對點云數(shù)據(jù)做平移操作后,所有的數(shù)據(jù)都將發(fā)生變化,導致所有的特征,全局特征都不一樣了。對于單個的物體還好,可以將其平移到坐標系的中心,把他的大小歸一化到一個球中,但是在一個場景中有多個物體時則不好辦,需要對哪個物體做歸一化呢?

在PointNet++中,作者利用所在空間的距離度量將點集劃分(partition)為有重疊的局部區(qū)域。在此基礎上,首先在小范圍中從幾何結構中提取局部特征(淺層特征),然后擴大范圍,在這些局部特征的基礎上提取更高層次的特征,直到提取到整個點集的全局特征。可以發(fā)現(xiàn),這個過程和CNN網(wǎng)絡的特征提取過程類似,首先提取低級別的特征,隨著感受野的增大,提取的特征level越來越高

PointNet++需要解決兩個關鍵的問題:第一,如何將點集劃分為不同的區(qū)域;第二,如何利用特征提取器獲取不同區(qū)域的局部特征。這兩個問題實際上是相關的,要想通過特征提取器來對不同的區(qū)域進行特征提取,需要每個分區(qū)具有相同的結構。這里同樣可以類比CNN來理解,在CNN中,卷積塊作為基本的特征提取器,對應的區(qū)域都是(n, n)的像素區(qū)域。而在3D點集當中,同樣需要找到結構相同的子區(qū)域,和對應的區(qū)域特征提取器。

在本文中,作者使用了PointNet作為特征提取器,另外一個問題就是如何來劃分點集從而產(chǎn)生結構相同的區(qū)域。作者使用鄰域球來定義分區(qū),每個區(qū)域可以通過中心坐標和半徑來確定。中心坐標的選取,作者使用了最遠點采樣算法算法來實現(xiàn)(farthest point sampling (FPS) algorithm)。


2. PointNet++網(wǎng)絡結構

PointNet++是PointNet的延伸,在PointNet的基礎上加入了多層次結構(hierarchical structure),使得網(wǎng)絡能夠在越來越大的區(qū)域上提供更高級別的特征。

網(wǎng)絡的每一組set abstraction layers主要包括3個部分:Sampling layer, Grouping layer and PointNet layer。

· Sample layer:主要是對輸入點進行采樣,在這些點中選出若干個中心點;
· Grouping layer:是利用上一步得到的中心點將點集劃分成若干個區(qū)域;
· PointNet layer:是對上述得到的每個區(qū)域進行編碼,變成特征向量。

每一組提取層的輸入是,其中N是輸入點的數(shù)量,d是坐標維度,C是特征維度。輸出是,其中N'是輸出點的數(shù)量,d是坐標維度不變,C'是新的特征維度。下面詳細介紹每一層的作用及實現(xiàn)過程。


2.1 Sample layer

使用farthest point sampling(FPS)選擇N'個點,至于為什么選擇使用這種方法選擇點,文中提到相比于隨機采樣,這種方法能更好的的覆蓋整個點集。具體選擇多少個中心點,數(shù)量怎么確定,可以看做是超參數(shù)視數(shù)據(jù)規(guī)模來定

FPS算法原理為:

  • 從點云中選取第一個點A作為查詢點,從剩余點中,選取一個距離最遠的點B;
  • 以取出來的點A,B作為查詢點,從剩余點中,取距離最遠的點C。此時,由于已經(jīng)取出來的點的個數(shù)超過1,需要同時考慮所有查詢點(A,B)。方法如下:
  • 對于剩余點中的任意一個點P,計算該點P到已經(jīng)選中的點集中所有點(A, B)的距離;取與點A和B的距離最小值作為該點到已選點集的距離d
  • 計算出每個剩余點到點集的距離后,選取距離最大的那個點即為點C
  • 重復第2步,一直采樣到N'個點為止。
  • 其Python實現(xiàn)代碼為:

    def farthest_point_sample(xyz, npoint):"""Input:xyz: pointcloud data, [B, N, 3]npoint: number of samplesReturn:centroids: sampled pointcloud index, [B, npoint, 3]"""device = xyz.deviceB, N, C = xyz.shapecentroids = torch.zeros(B, npoint, dtype=torch.long).to(device) # 采樣點矩陣(B, npoint)distance = torch.ones(B, N).to(device) * 1e10 # 采樣點到所有點距離(B, N)farthest = torch.randint(0, N, (B,), dtype=torch.long).to(device) # 最遠點,初試時隨機選擇一點點batch_indices = torch.arange(B, dtype=torch.long).to(device) # batch_size 數(shù)組for i in range(npoint):centroids[:, i] = farthest # 更新第i個最遠點centroid = xyz[batch_indices, farthest, :].view(B, 1, 3) # 取出這個最遠點的xyz坐標dist = torch.sum((xyz - centroid) ** 2, -1) # 計算點集中的所有點到這個最遠點的歐式距離mask = dist < distance distance[mask] = dist[mask] # 更新distances,記錄樣本中每個點距離所有已出現(xiàn)的采樣點的最小距離farthest = torch.max(distance, -1)[1] # 返回最遠點索引return centroids

    2.2 Grouping layer

    這一層使用Ball query方法對sample layers采樣的點生成個對應的局部區(qū)域,根據(jù)論文中的意思,這里使用到兩個超參數(shù)?,一個是每個區(qū)域中點的數(shù)量K,另一個是query的半徑r。這里半徑應該是占主導的,在某個半徑的球內找點,點的數(shù)量上限是K。球的半徑和每個區(qū)域中點的數(shù)量都是超參數(shù)。

    代碼為:

    def square_distance(src, dst):"""Calculate Euclid distance between each two points.src^T * dst = xn * xm + yn * ym + zn * zm;sum(src^2, dim=-1) = xn*xn + yn*yn + zn*zn;sum(dst^2, dim=-1) = xm*xm + ym*ym + zm*zm;dist = (xn - xm)^2 + (yn - ym)^2 + (zn - zm)^2= sum(src**2,dim=-1)+sum(dst**2,dim=-1)-2*src^T*dstInput:src: source points, [B, N, C]dst: target points, [B, M, C]Output:dist: per-point square distance, [B, N, M]"""B, N, _ = src.shape_, M, _ = dst.shapedist = -2 * torch.matmul(src, dst.permute(0, 2, 1))dist += torch.sum(src ** 2, -1).view(B, N, 1)dist += torch.sum(dst ** 2, -1).view(B, 1, M)return distdef query_ball_point(radius, nsample, xyz, new_xyz):"""Input:radius: local region radiusnsample: max sample number in local regionxyz: all points, [B, N, 3]new_xyz: query points, [B, S, 3]Return:group_idx: grouped points index, [B, S, nsample]"""device = xyz.deviceB, N, C = xyz.shape_, S, _ = new_xyz.shapegroup_idx = torch.arange(N, dtype=torch.long).to(device).view(1, 1, N).repeat([B, S, 1])sqrdists = square_distance(new_xyz, xyz)group_idx[sqrdists > radius ** 2] = Ngroup_idx = group_idx.sort(dim=-1)[0][:, :, :nsample]group_first = group_idx[:, :, 0].view(B, S, 1).repeat([1, 1, nsample])mask = group_idx == Ngroup_idx[mask] = group_first[mask]return group_idx

    2.3 PointNet layer

    這一層是PointNet網(wǎng)絡,輸入為局部區(qū)域:。輸出是。需要注意的是,在輸入到網(wǎng)絡之前,會把該區(qū)域中的點變成圍繞中心點的相對坐標。作者提到,這樣做能夠獲取點與點之間的關系。至此則完成了set abstraction工作,set abstraction代碼為:

    class PointNetSetAbstraction(nn.Module):def __init__(self, npoint, radius, nsample, in_channel, mlp, group_all):super(PointNetSetAbstraction, self).__init__()self.npoint = npointself.radius = radiusself.nsample = nsampleself.mlp_convs = nn.ModuleList()self.mlp_bns = nn.ModuleList()last_channel = in_channelfor out_channel in mlp:self.mlp_convs.append(nn.Conv2d(last_channel, out_channel, 1))self.mlp_bns.append(nn.BatchNorm2d(out_channel))last_channel = out_channelself.group_all = group_alldef forward(self, xyz, points):"""Input:xyz: input points position data, [B, C, N]points: input points data, [B, D, N]Return:new_xyz: sampled points position data, [B, C, S]new_points_concat: sample points feature data, [B, D', S]"""xyz = xyz.permute(0, 2, 1)if points is not None:points = points.permute(0, 2, 1)if self.group_all:new_xyz, new_points = sample_and_group_all(xyz, points)else:new_xyz, new_points = sample_and_group(self.npoint, self.radius, self.nsample, xyz, points)# new_xyz: sampled points position data, [B, npoint, C]# new_points: sampled points data, [B, npoint, nsample, C+D]new_points = new_points.permute(0, 3, 2, 1) # [B, C+D, nsample,npoint]for i, conv in enumerate(self.mlp_convs):bn = self.mlp_bns[i]new_points = F.relu(bn(conv(new_points)))new_points = torch.max(new_points, 2)[0]new_xyz = new_xyz.permute(0, 2, 1)return new_xyz, new_points

    2.4 點云分布不一致的處理方法

    點云分布不一致時,每個子區(qū)域中如果在生成的時候使用相同的半徑r,會導致有些區(qū)域采樣點過少

    作者提到這個問題需要解決,并且提出了兩個方法:Multi-scale grouping (MSG) and Multi-resolution grouping (MRG)。下面是論文當中的示意圖。

    下面分別介紹一下這兩種方法。

    第一種多尺度分組(MSG),對于同一個中心點,如果使用3個不同尺度的話,就分別找圍繞每個中心點畫3個區(qū)域,每個區(qū)域的半徑及里面的點的個數(shù)不同。對于同一個中心點來說,不同尺度的區(qū)域送入不同的PointNet進行特征提取,之后concat,作為這個中心點的特征也就是說MSG實際上相當于并聯(lián)了多個hierarchical structure,每個結構中心點不變,但是區(qū)域范圍不同。PointNet的輸入和輸出尺寸也不同,然后幾個不同尺度的結構在PointNet有一個Concat。代碼是:

    class PointNetSetAbstractionMsg(nn.Module):def __init__(self, npoint, radius_list, nsample_list, in_channel, mlp_list):super(PointNetSetAbstractionMsg, self).__init__()self.npoint = npointself.radius_list = radius_listself.nsample_list = nsample_listself.conv_blocks = nn.ModuleList()self.bn_blocks = nn.ModuleList()for i in range(len(mlp_list)):convs = nn.ModuleList()bns = nn.ModuleList()last_channel = in_channel + 3for out_channel in mlp_list[i]:convs.append(nn.Conv2d(last_channel, out_channel, 1))bns.append(nn.BatchNorm2d(out_channel))last_channel = out_channelself.conv_blocks.append(convs)self.bn_blocks.append(bns)def forward(self, xyz, points):"""Input:xyz: input points position data, [B, C, N]points: input points data, [B, D, N]Return:new_xyz: sampled points position data, [B, C, S]new_points_concat: sample points feature data, [B, D', S]"""xyz = xyz.permute(0, 2, 1)if points is not None:points = points.permute(0, 2, 1)B, N, C = xyz.shapeS = self.npointnew_xyz = index_points(xyz, farthest_point_sample(xyz, S))new_points_list = []for i, radius in enumerate(self.radius_list):K = self.nsample_list[i]group_idx = query_ball_point(radius, K, xyz, new_xyz)grouped_xyz = index_points(xyz, group_idx)grouped_xyz -= new_xyz.view(B, S, 1, C)if points is not None:grouped_points = index_points(points, group_idx)grouped_points = torch.cat([grouped_points, grouped_xyz], dim=-1)else:grouped_points = grouped_xyzgrouped_points = grouped_points.permute(0, 3, 2, 1) # [B, D, K, S]for j in range(len(self.conv_blocks[i])):conv = self.conv_blocks[i][j]bn = self.bn_blocks[i][j]grouped_points = F.relu(bn(conv(grouped_points)))new_points = torch.max(grouped_points, 2)[0] # [B, D', S]new_points_list.append(new_points)new_xyz = new_xyz.permute(0, 2, 1)new_points_concat = torch.cat(new_points_list, dim=1)return new_xyz, new_points_concat

    另一種是多分辨率分組(MRG)。MSG很明顯會影響降低運算速度,所以提出了MRG,這種方法應該是對不同level的grouping做了一個concat,但是由于尺度不同,對于low level的先放入一個pointnet進行處理再和high level的進行concat。感覺和ResNet中的跳躍連接有點類似。

    在這部分,作者還提到了一種random input dropout(DP)的方法,就是在輸入到點云之前,對點集進行隨機的Dropout, 比例為95%,也就是說進行95%的比例采樣。


    2.5 Point Feature Propagation for Set Segmentation

    對于點云分割任務,我們還需要將點集上采樣回原始點集數(shù)量,這里使用了分層的差值方法。代碼為:

    class PointNetFeaturePropagation(nn.Module):def __init__(self, in_channel, mlp):super(PointNetFeaturePropagation, self).__init__()self.mlp_convs = nn.ModuleList()self.mlp_bns = nn.ModuleList()last_channel = in_channelfor out_channel in mlp:self.mlp_convs.append(nn.Conv1d(last_channel, out_channel, 1))self.mlp_bns.append(nn.BatchNorm1d(out_channel))last_channel = out_channeldef forward(self, xyz1, xyz2, points1, points2):"""Input:xyz1: input points position data, [B, C, N]xyz2: sampled input points position data, [B, C, S]points1: input points data, [B, D, N]points2: input points data, [B, D, S]Return:new_points: upsampled points data, [B, D', N]"""xyz1 = xyz1.permute(0, 2, 1)xyz2 = xyz2.permute(0, 2, 1)points2 = points2.permute(0, 2, 1)B, N, C = xyz1.shape_, S, _ = xyz2.shapeif S == 1:interpolated_points = points2.repeat(1, N, 1)else:dists = square_distance(xyz1, xyz2)dists, idx = dists.sort(dim=-1)dists, idx = dists[:, :, :3], idx[:, :, :3] # [B, N, 3]dists[dists < 1e-10] = 1e-10weight = 1.0 / dists # [B, N, 3]weight = weight / torch.sum(weight, dim=-1).view(B, N, 1) # [B, N, 3]interpolated_points = torch.sum(index_points(points2, idx) * weight.view(B, N, 3, 1), dim=2)if points1 is not None:points1 = points1.permute(0, 2, 1)new_points = torch.cat([points1, interpolated_points], dim=-1)else:new_points = interpolated_pointsnew_points = new_points.permute(0, 2, 1)for i, conv in enumerate(self.mlp_convs):bn = self.mlp_bns[i]new_points = F.relu(bn(conv(new_points)))return new_points

    2.6 Classification

    class PointNet2ClsMsg(nn.Module):def __init__(self):super(PointNet2ClsMsg, self).__init__()self.sa1 = PointNetSetAbstractionMsg(512, [0.1, 0.2, 0.4], [16, 32, 128], 0, [[32, 32, 64], [64, 64, 128], [64, 96, 128]])self.sa2 = PointNetSetAbstractionMsg(128, [0.2, 0.4, 0.8], [32, 64, 128], 320, [[64, 64, 128], [128, 128, 256], [128, 128, 256]])self.sa3 = PointNetSetAbstraction(None, None, None, 640 + 3, [256, 512, 1024], True)self.fc1 = nn.Linear(1024, 512)self.bn1 = nn.BatchNorm1d(512)self.drop1 = nn.Dropout(0.4)self.fc2 = nn.Linear(512, 256)self.bn2 = nn.BatchNorm1d(256)self.drop2 = nn.Dropout(0.4)self.fc3 = nn.Linear(256, 40)def forward(self, xyz):B, _, _ = xyz.shapel1_xyz, l1_points = self.sa1(xyz, None)l2_xyz, l2_points = self.sa2(l1_xyz, l1_points)l3_xyz, l3_points = self.sa3(l2_xyz, l2_points)x = l3_points.view(B, 1024)x = self.drop1(F.relu(self.bn1(self.fc1(x))))x = self.drop2(F.relu(self.bn2(self.fc2(x))))x = self.fc3(x)x = F.log_softmax(x, -1)return x

    2.7 Part Segmentation

    class PointNet2PartSeg(nn.Module): def __init__(self, num_classes):super(PointNet2PartSeg, self).__init__()self.sa1 = PointNetSetAbstraction(npoint=512, radius=0.2, nsample=64, in_channel=3, mlp=[64, 64, 128], group_all=False)self.sa2 = PointNetSetAbstraction(npoint=128, radius=0.4, nsample=64, in_channel=128 + 3, mlp=[128, 128, 256], group_all=False)self.sa3 = PointNetSetAbstraction(npoint=None, radius=None, nsample=None, in_channel=256 + 3, mlp=[256, 512, 1024], group_all=True)self.fp3 = PointNetFeaturePropagation(in_channel=1280, mlp=[256, 256])self.fp2 = PointNetFeaturePropagation(in_channel=384, mlp=[256, 128])self.fp1 = PointNetFeaturePropagation(in_channel=128, mlp=[128, 128, 128])self.conv1 = nn.Conv1d(128, 128, 1)self.bn1 = nn.BatchNorm1d(128)self.drop1 = nn.Dropout(0.5)self.conv2 = nn.Conv1d(128, num_classes, 1)def forward(self, xyz):# Set Abstraction layersl1_xyz, l1_points = self.sa1(xyz, None)l2_xyz, l2_points = self.sa2(l1_xyz, l1_points)l3_xyz, l3_points = self.sa3(l2_xyz, l2_points)# Feature Propagation layersl2_points = self.fp3(l2_xyz, l3_xyz, l2_points, l3_points)l1_points = self.fp2(l1_xyz, l2_xyz, l1_points, l2_points)l0_points = self.fp1(xyz, l1_xyz, None, l1_points)# FC layersfeat = F.relu(self.bn1(self.conv1(l0_points)))x = self.drop1(feat)x = self.conv2(x)x = F.log_softmax(x, dim=1)x = x.permute(0, 2, 1)return x, feat

    2.8 Scene Segmentation

    class PointNet2SemSeg(nn.Module):def __init__(self, num_classes):super(PointNet2SemSeg, self).__init__()self.sa1 = PointNetSetAbstraction(1024, 0.1, 32, 3, [32, 32, 64], False)self.sa2 = PointNetSetAbstraction(256, 0.2, 32, 64 + 3, [64, 64, 128], False)self.sa3 = PointNetSetAbstraction(64, 0.4, 32, 128 + 3, [128, 128, 256], False)self.sa4 = PointNetSetAbstraction(16, 0.8, 32, 256 + 3, [256, 256, 512], False)self.fp4 = PointNetFeaturePropagation(768, [256, 256])self.fp3 = PointNetFeaturePropagation(384, [256, 256])self.fp2 = PointNetFeaturePropagation(320, [256, 128])self.fp1 = PointNetFeaturePropagation(128, [128, 128, 128])self.conv1 = nn.Conv1d(128, 128, 1)self.bn1 = nn.BatchNorm1d(128)self.drop1 = nn.Dropout(0.5)self.conv2 = nn.Conv1d(128, num_classes, 1)def forward(self, xyz):l1_xyz, l1_points = self.sa1(xyz, None)l2_xyz, l2_points = self.sa2(l1_xyz, l1_points)l3_xyz, l3_points = self.sa3(l2_xyz, l2_points)l4_xyz, l4_points = self.sa4(l3_xyz, l3_points)l3_points = self.fp4(l3_xyz, l4_xyz, l3_points, l4_points)l2_points = self.fp3(l2_xyz, l3_xyz, l2_points, l3_points)l1_points = self.fp2(l1_xyz, l2_xyz, l1_points, l2_points)l0_points = self.fp1(xyz, l1_xyz, None, l1_points)x = self.drop1(F.relu(self.bn1(self.conv1(l0_points))))x = self.conv2(x)x = F.log_softmax(x, dim=1)return x

    3. 參考資料

    PointNet++作者分享報告:將門創(chuàng)投 | 斯坦福大學在讀博士生祁芮中臺:點云上的深度學習及其在三維場景理解中的應用_嗶哩嗶哩_bilibili

    PointNet++官網(wǎng)鏈接:PointNet++

    PointNet++代碼:https://github.com/yanx27/Pointnet_Pointnet2_pytorch

    ????????????????????????????PointNet++的pytorch實現(xiàn)代碼閱讀

    PointNet++作者視頻講解文字版:PointNet++作者的視頻講解文字版 - 一杯明月 - 博客園

    總結

    以上是生活随笔為你收集整理的PointNet++详解与代码的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 亚洲视频99 | 四季av日韩精品一区 | 黄色国产在线观看 | 欧美激情图片 | 午夜视频免费在线 | 中国在线观看视频高清免费 | 8x8ⅹ8成人免费视频观看 | 欧美色图在线观看 | 污污网址在线观看 | 精品人伦一区二区三区蜜桃免费 | 人妻夜夜爽天天爽 | 欧美系列在线观看 | 宅男噜噜噜66一区二区 | 欧美激情天堂 | 一区二区天堂 | 91无毒不卡 | 亚洲在线免费视频 | 亚欧在线视频 | 看全色黄大色黄大片女一次牛 | 日韩一级片免费看 | 成人高潮视频 | av毛片在线播放 | 最新av| 久久久久久久91 | 免费插插视频 | 亚洲激情午夜 | 亚洲影视一区二区 | 日韩超碰 | 4438x在线观看| 日韩电影在线一区二区 | 丰满岳跪趴高撅肥臀尤物在线观看 | 色婷婷国产 | 黄色高清视频 | 在线视频亚洲色图 | 69精品久久久久久 | 日本一区不卡在线观看 | 麻豆区1免费| 少妇一级淫片日本 | 黄色的视频网站 | 色漫在线观看 | 一级片小视频 | 六月色| 国产精品永久免费视频 | 国产又粗又深又猛又爽又在线观看 | 午夜激情网址 | av自拍偷拍 | 99极品视频 | 超碰97色 | 秋霞一区| 天天射寡妇 | 欧美视频第一区 | 亚洲第一色 | 看片日韩 | 日韩成人精品一区二区三区 | 一本之道久久 | 欧美系列在线观看 | 亚洲男人天堂av | 久久中文字幕精品 | 蜜桃tv一区二区三区 | 综合久久久久综合 | 香蕉久操 | 日日摸夜夜添狠狠添久久精品成人 | 午夜网址| 午夜影视大全 | 国产精品久久久久久久免费大片 | 亚洲精品一区二区三区四区五区 | 国产裸体永久免费视频网站 | 视频二区 | 欧美日韩123区 | 国产精品视频成人 | 日本中文字幕影院 | 久久yy| 国产在线观看 | 久久日本视频 | 久久久九九九九 | 大乳护士喂奶hd | 爱啪啪导航 | 久久久亚洲国产精品 | 又大又硬又爽免费视频 | 国产精品一区二区三区免费在线观看 | 天天干天天色 | 麻豆网站在线免费观看 | 亚洲国产精品成人综合久久久 | 亚洲 日本 欧美 中文幕 | 草草影院第一页 | 青草视频免费看 | 欧美午夜精品一区二区 | 久久艹av| 男人都懂的网址 | 最新国产精品自拍 | 日韩中文字幕国产 | 黄色av毛片 | 欧美一区二区三区四 | 亚洲淫欲 | 久久久久久欧美精品se一二三四 | 91亚洲精品视频 | 美女扒开粉嫩尿口 | 久操久热| 五月婷婷激情四射 |