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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

OpenCV还能实现这种效果? | 视频防抖技术

發(fā)布時間:2024/3/24 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV还能实现这种效果? | 视频防抖技术 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊上方“AI算法與圖像處理”,選擇加"星標"或“置頂”

重磅干貨,第一時間送達

這篇文章分享了一個視頻防抖的策略,這個方法同樣可以應用到其他領域,比如常見的關鍵點檢測,當使用視頻測試時,效果就沒有demo那么好,此時可以考慮本文的方法去優(yōu)化。

分享這些demo并不一定所有人都會用到,但是在解決實際問題的時候,可以提供一個思路去解決問題。希望能給我一個三連,鼓勵一下哈

在這篇文章中,我們將學習如何使用OpenCV庫中的點特征匹配技術來實現一個簡單的視頻穩(wěn)定器。我們將討論算法并且會分享代碼(python和C++版),以使用這種方法在OpenCV中設計一個簡單的穩(wěn)定器。

視頻中低頻攝像機運動的例子

視頻防抖是指用于減少攝像機運動對最終視頻的影響的一系列方法。攝像機的運動可以是平移(比如沿著x、y、z方向上的運動)或旋轉(偏航、俯仰、翻滾)。

視頻防抖的應用

對視頻防抖的需求在許多領域都有。

這在消費者和專業(yè)攝像中是極其重要的。因此,存在許多不同的機械、光學和算法解決方案。即使在靜態(tài)圖像拍攝中,防抖技術也可以幫助拍攝長時間曝光的手持照片。

在內窺鏡和結腸鏡等醫(yī)療診斷應用中,需要對視頻進行穩(wěn)定,以確定問題的確切位置和寬度。

同樣,在軍事應用中,無人機在偵察飛行中捕獲的視頻也需要進行穩(wěn)定,以便定位、導航、目標跟蹤等。同樣的道理也適用于機器人。

視頻防抖的不同策略

視頻防抖的方法包括機械穩(wěn)定方法、光學穩(wěn)定方法和數字穩(wěn)定方法。下面將簡要討論這些問題:

機械視頻穩(wěn)定:機械圖像穩(wěn)定系統(tǒng)使用由特殊傳感器如陀螺儀和加速度計檢測到的運動來移動圖像傳感器以補償攝像機的運動。
光學視頻穩(wěn)定:在這種方法中,不是移動整個攝像機,而是通過鏡頭的移動部分來實現穩(wěn)定。這種方法使用了一個可移動的鏡頭組合,當光通過相機的鏡頭系統(tǒng)時,可以可變地調整光的路徑長度。
數字視頻穩(wěn)定:這種方法不需要特殊的傳感器來估計攝像機的運動。主要有三個步驟:1)運動估計2)運動平滑,3)圖像合成。第一步導出了兩個連續(xù)坐標系之間的變換參數。第二步過濾不需要的運動,在最后一步重建穩(wěn)定的視頻。
在這篇文章中,我們將學習一個快速和魯棒性好的數字視頻穩(wěn)定算法的實現。它是基于二維運動模型,其中我們應用歐幾里得(即相似性)變換包含平移、旋轉和縮放。

OpenCV Motion Models

正如你在上面的圖片中看到的,在歐幾里得運動模型中,圖像中的一個正方形可以轉換為任何其他位置、大小或旋轉不同的正方形。它比仿射變換和單應變換限制更嚴格,但對于運動穩(wěn)定來說足夠了,因為攝像機在視頻連續(xù)幀之間的運動通常很小。

使用點特征匹配實現視頻防抖

該方法涉及跟蹤兩個連續(xù)幀之間的多個特征點。跟蹤特征允許我們估計幀之間的運動并對其進行補償。

下面的流程圖顯示了基本步驟。

我們來看看這些步驟。

第一步:設置輸入和輸出視頻

首先,讓我們完成讀取輸入視頻和寫入輸出視頻的設置。代碼中的注釋解釋每一行。

Python

# Import numpy and OpenCV import numpy as np import cv2# Read input video cap = cv2.VideoCapture('video.mp4') # Get frame count n_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # Get width and height of video stream w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))# Define the codec for output video fourcc = cv2.VideoWriter_fourcc(*'MJPG')# Set up output video out = cv2.VideoWriter('video_out.mp4', fourcc, fps, (w, h))

C++

// Read input videoVideoCapture cap("video.mp4");// Get frame countint n_frames = int(cap.get(CAP_PROP_FRAME_COUNT)); // Get width and height of video streamint w = int(cap.get(CAP_PROP_FRAME_WIDTH)); int h = int(cap.get(CAP_PROP_FRAME_HEIGHT));// Get frames per second (fps)double fps = cap.get(CV_CAP_PROP_FPS);// Set up output videoVideoWriter out("video_out.avi", CV_FOURCC('M','J','P','G'), fps, Size(2 * w, h));


第二步:讀取第一幀并將其轉換為灰度圖

對于視頻穩(wěn)定,我們需要捕捉視頻的兩幀,估計幀之間的運動,最后校正運動。

Python

# Read first frame _, prev = cap.read() # Convert frame to grayscale prev_gray = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)

C++

// Define variable for storing framesMat curr, curr_gray;Mat prev, prev_gray;// Read first framecap >> prev;// Convert frame to grayscalecvtColor(prev, prev_gray, COLOR_BGR2GRAY);


第三步:尋找?guī)g的移動

這是算法中最關鍵的部分。我們將遍歷所有的幀,并找到當前幀和前一幀之間的移動。沒有必要知道每一個像素的運動。歐幾里得運動模型要求我們知道兩個坐標系中兩個點的運動。但是在實際應用中,找到50-100個點的運動,然后用它們來穩(wěn)健地估計運動模型是一個好方法。

3.1 可用于跟蹤的優(yōu)質特征
現在的問題是我們應該選擇哪些點進行跟蹤。請記住,跟蹤算法使用一個小補丁圍繞一個點來跟蹤它。這樣的跟蹤算法受到孔徑問題的困擾,如下面的視頻所述

因此,光滑的區(qū)域不利于跟蹤,而有很多角的紋理區(qū)域則比較好。幸運的是,OpenCV有一個快速的特征檢測器,可以檢測最適合跟蹤的特性。它被稱為goodFeaturesToTrack)

3.2 Lucas-Kanade光流
一旦我們在前一幀中找到好的特征,我們就可以使用Lucas-Kanade光流算法在下一幀中跟蹤它們。

它是利用OpenCV中的calcOpticalFlowPyrLK函數實現的。在calcOpticalFlowPyrLK這個名字中,LK代表Lucas-Kanade,而Pyr代表金字塔。計算機視覺中的圖像金字塔是用來處理不同尺度(分辨率)的圖像的。

由于各種原因,calcOpticalFlowPyrLK可能無法計算出所有點的運動。例如,當前幀的特征點可能會被下一幀的另一個對象遮擋。幸運的是,您將在下面的代碼中看到,calcOpticalFlowPyrLK中的狀態(tài)標志可以用來過濾掉這些值。

3.3 估計運動
回顧一下,在3.1步驟中,我們在前一幀中找到了一些好的特征。在步驟3.2中,我們使用光流來跟蹤特征。換句話說,我們已經找到了特征在當前幀中的位置,并且我們已經知道了特征在前一幀中的位置。所以我們可以使用這兩組點來找到映射前一個坐標系到當前坐標系的剛性(歐幾里德)變換。這是使用函數estimateRigidTransform完成的。

一旦我們估計了運動,我們可以把它分解成x和y的平移和旋轉(角度)。我們將這些值存儲在一個數組中,這樣就可以平穩(wěn)地更改它們。

下面的代碼將完成步驟3.1到3.3。請務必閱讀代碼中的注釋以進行后續(xù)操作。

Python

# Pre-define transformation-store array transforms = np.zeros((n_frames-1, 3), np.float32) for i in range(n_frames-2):# Detect feature points in previous frameprev_pts = cv2.goodFeaturesToTrack(prev_gray,maxCorners=200,qualityLevel=0.01,minDistance=30,blockSize=3)# Read next framesuccess, curr = cap.read() if not success: break # Convert to grayscalecurr_gray = cv2.cvtColor(curr, cv2.COLOR_BGR2GRAY) # Calculate optical flow (i.e. track feature points)curr_pts, status, err = cv2.calcOpticalFlowPyrLK(prev_gray, curr_gray, prev_pts, None) # Sanity checkassert prev_pts.shape == curr_pts.shape # Filter only valid pointsidx = np.where(status==1)[0]prev_pts = prev_pts[idx]curr_pts = curr_pts[idx]#Find transformation matrixm = cv2.estimateRigidTransform(prev_pts, curr_pts, fullAffine=False) #will only work with OpenCV-3 or less# Extract traslationdx = m[0,2]dy = m[1,2]# Extract rotation angleda = np.arctan2(m[1,0], m[0,0])# Store transformationtransforms[i] = [dx,dy,da]# Move to next frameprev_gray = curr_grayprint("Frame: " + str(i) + "/" + str(n_frames) + " - Tracked points : " + str(len(prev_pts)))

C++

在c++實現中,我們首先定義一些類來幫助我們存儲估計的運動向量。下面的TransformParam類存儲了運動信息(dx -運動在x中,dy -運動在y中,da -角度變化),并提供了一個方法getTransform來將該運動轉換為變換矩陣。

struct TransformParam {TransformParam() {}TransformParam(double _dx, double _dy, double _da) {dx = _dx;dy = _dy;da = _da;}double dx;double dy;double da; // anglevoid getTransform(Mat &T) {// Reconstruct transformation matrix accordingly to new valuesT.at<double>(0,0) = cos(da);T.at<double>(0,1) = -sin(da);T.at<double>(1,0) = sin(da);T.at<double>(1,1) = cos(da);T.at<double>(0,2) = dx;T.at<double>(1,2) = dy;} };

在下面的代碼中,我們循環(huán)視頻幀并執(zhí)行步驟3.1到3.3。

// Pre-define transformation-store arrayvector <TransformParam> transforms; // Mat last_T;for(int i = 1; i < n_frames-1; i++){// Vector from previous and current feature pointsvector <Point2f> prev_pts, curr_pts;// Detect features in previous framegoodFeaturesToTrack(prev_gray, prev_pts, 200, 0.01, 30);// Read next frame bool success = cap.read(curr);if(!success) break; // Convert to grayscalecvtColor(curr, curr_gray, COLOR_BGR2GRAY);// Calculate optical flow (i.e. track feature points)vector <uchar> status;vector <float> err;calcOpticalFlowPyrLK(prev_gray, curr_gray, prev_pts, curr_pts, status, err);// Filter only valid pointsauto prev_it = prev_pts.begin(); auto curr_it = curr_pts.begin(); for(size_t k = 0; k < status.size(); k++) {if(status[k]) {prev_it++; curr_it++; }else {prev_it = prev_pts.erase(prev_it);curr_it = curr_pts.erase(curr_it);}}// Find transformation matrixMat T = estimateRigidTransform(prev_pts, curr_pts, false); // In rare cases no transform is found. // We'll just use the last known good transform.if(T.data == NULL) last_T.copyTo(T);T.copyTo(last_T);// Extract traslationdouble dx = T.at<double>(0,2);double dy = T.at<double>(1,2);// Extract rotation angledouble da = atan2(T.at<double>(1,0), T.at<double>(0,0));// Store transformation transforms.push_back(TransformParam(dx, dy, da));// Move to next framecurr_gray.copyTo(prev_gray);cout << "Frame: " << i << "/" << n_frames << " - Tracked points : " << prev_pts.size() << endl;}


第四步:計算幀之間的平滑運動


在前面的步驟中,我們估計幀之間的運動并將它們存儲在一個數組中。我們現在需要通過疊加上一步估計的微分運動來找到運動軌跡。

步驟4.1:軌跡計算

在這一步,我們將增加運動之間的幀來計算軌跡。我們的最終目標是平滑這條軌跡。

Python 在Python中,可以很容易地使用numpy中的cumsum(累計和)來實現。

# Compute trajectory using cumulative sum of transformations trajectory = np.cumsum(transforms, axis=0

C++

在c++中,我們定義了一個名為Trajectory的結構體來存儲轉換參數的累積和。

struct Trajectory {Trajectory() {}Trajectory(double _x, double _y, double _a) {x = _x;y = _y;a = _a;}double x;double y;double a; // angle };

C我們還定義了一個函數cumsum,它接受一個TransformParams 向量,并通過執(zhí)行微分運動dx、dy和da(角度)的累積和返回軌跡。

vector<Trajectory> cumsum(vector<TransformParam> &transforms) {vector <Trajectory> trajectory; // trajectory at all frames// Accumulated frame to frame transformdouble a = 0;double x = 0;double y = 0;for(size_t i=0; i < transforms.size(); i++) {x += transforms[i].dx;y += transforms[i].dy;a += transforms[i].da;trajectory.push_back(Trajectory(x,y,a));}return trajectory; }

步驟4.2:計算平滑軌跡

在上一步中,我們計算了運動軌跡。所以我們有三條曲線來顯示運動(x, y,和角度)如何隨時間變化。

在這一步,我們將展示如何平滑這三條曲線。

平滑任何曲線最簡單的方法是使用移動平均濾波器(moving average filter)。顧名思義,移動平均過濾器將函數在某一點上的值替換為由窗口定義的其相鄰函數的平均值。讓我們看一個例子。

假設我們在數組c中存儲了一條曲線,那么曲線上的點是c[0]…c[n-1]。設f是我們通過寬度為5的移動平均濾波器過濾c得到的平滑曲線。

該曲線的k^{th}元素使用

如您所見,平滑曲線的值是噪聲曲線在一個小窗口上的平均值。下圖顯示了左邊的噪點曲線的例子,使用右邊的尺度為5 濾波器進行平滑。

Python

在Python實現中,我們定義了一個移動平均濾波器,它接受任何曲線(即1-D的數字)作為輸入,并返回曲線的平滑版本。

def movingAverage(curve, radius): window_size = 2 * radius + 1# Define the filter f = np.ones(window_size)/window_size # Add padding to the boundaries curve_pad = np.lib.pad(curve, (radius, radius), 'edge') # Apply convolution curve_smoothed = np.convolve(curve_pad, f, mode='same') # Remove padding curve_smoothed = curve_smoothed[radius:-radius]# return smoothed curvereturn curve_smoothed

我們還定義了一個函數,它接受軌跡并對這三個部分進行平滑處理。

def smooth(trajectory): smoothed_trajectory = np.copy(trajectory) # Filter the x, y and angle curvesfor i in range(3):smoothed_trajectory[:,i] = movingAverage(trajectory[:,i], radius=SMOOTHING_RADIUS)return smoothed_trajectory

這是最后去使用

# Compute trajectory using cumulative sum of transformations trajectory = np.cumsum(transforms, axis=0)

C++

在c++版本中,我們定義了一個名為smooth的函數,用于計算平滑移動平均軌跡。

vector <Trajectory> smooth(vector <Trajectory>& trajectory, int radius) {vector <Trajectory> smoothed_trajectory; for(size_t i=0; i < trajectory.size(); i++) {double sum_x = 0;double sum_y = 0;double sum_a = 0;int count = 0;for(int j=-radius; j <= radius; j++) { if(i+j >= 0 && i+j < trajectory.size()) {sum_x += trajectory[i+j].x;sum_y += trajectory[i+j].y;sum_a += trajectory[i+j].a;count++;}}double avg_a = sum_a / count;double avg_x = sum_x / count;double avg_y = sum_y / count;smoothed_trajectory.push_back(Trajectory(avg_x, avg_y, avg_a));}return smoothed_trajectory; }


我們在主函數中使用它

// Smooth trajectory using moving average filtervector <Trajectory> smoothed_trajectory = smooth(trajectory, SMOOTHING_RADIUS);


步驟4.3:計算平滑變換
到目前為止,我們已經得到了一個平滑的軌跡。在這一步,我們將使用平滑的軌跡來獲得平滑的變換,可以應用到視頻的幀來穩(wěn)定它。

這是通過找到平滑軌跡和原始軌跡之間的差異,并將這些差異加回到原始的變換中來完成的。

Python

# Calculate difference in smoothed_trajectory and trajectory difference = smoothed_trajectory - trajectory# Calculate newer transformation array transforms_smooth = transforms + difference

C++

vector <TransformParam> transforms_smooth; for(size_t i=0; i < transforms.size(); i++) { // Calculate difference in smoothed_trajectory and trajectory double diff_x = smoothed_trajectory[i].x - trajectory[i].x; double diff_y = smoothed_trajectory[i].y - trajectory[i].y; double diff_a = smoothed_trajectory[i].a - trajectory[i].a; // Calculate newer transformation array double dx = transforms[i].dx + diff_x; double dy = transforms[i].dy + diff_y; double da = transforms[i].da + diff_a; transforms_smooth.push_back(TransformParam(dx, dy, da)); }

第五步:將平滑的攝像機運動應用到幀中

差不多做完了。現在我們所需要做的就是循環(huán)幀并應用我們剛剛計算的變換。

如果我們有一個指定為(x, y, \theta),的運動,對應的變換矩陣是

請閱讀代碼中的注釋以進行后續(xù)操作。

Python

# Reset stream to first frame cap.set(cv2.CAP_PROP_POS_FRAMES, 0) # Write n_frames-1 transformed frames for i in range(n_frames-2):# Read next framesuccess, frame = cap.read() if not success:break# Extract transformations from the new transformation arraydx = transforms_smooth[i,0]dy = transforms_smooth[i,1]da = transforms_smooth[i,2]# Reconstruct transformation matrix accordingly to new valuesm = np.zeros((2,3), np.float32)m[0,0] = np.cos(da)m[0,1] = -np.sin(da)m[1,0] = np.sin(da)m[1,1] = np.cos(da)m[0,2] = dxm[1,2] = dy# Apply affine wrapping to the given frameframe_stabilized = cv2.warpAffine(frame, m, (w,h))# Fix border artifactsframe_stabilized = fixBorder(frame_stabilized) # Write the frame to the fileframe_out = cv2.hconcat([frame, frame_stabilized])# If the image is too big, resize it.if(frame_out.shape[1] &gt; 1920): frame_out = cv2.resize(frame_out, (frame_out.shape[1]/2, frame_out.shape[0]/2));cv2.imshow("Before and After", frame_out)cv2.waitKey(10)out.write(frame_out)


C++

cap.set(CV_CAP_PROP_POS_FRAMES, 1); Mat T(2,3,CV_64F); Mat frame, frame_stabilized, frame_out; for( int i = 0; i &lt; n_frames-1; i++) { bool success = cap.read(frame); if(!success) break; // Extract transform from translation and rotation angle. transforms_smooth[i].getTransform(T); // Apply affine wrapping to the given frame warpAffine(frame, frame_stabilized, T, frame.size()); // Scale image to remove black border artifact fixBorder(frame_stabilized); // Now draw the original and stabilised side by side for coolness hconcat(frame, frame_stabilized, frame_out); // If the image is too big, resize it. if(frame_out.cols &gt; 1920) {resize(frame_out, frame_out, Size(frame_out.cols/2, frame_out.rows/2));}imshow("Before and After", frame_out);out.write(frame_out);waitKey(10); }


步驟5.1:修復邊界偽影
當我們穩(wěn)定一個視頻,我們可能會看到一些黑色的邊界偽影。這是意料之中的,因為為了穩(wěn)定視頻,幀可能不得不縮小大小。

我們可以通過將視頻的中心縮小一小部分(例如4%)來緩解這個問題。

下面的fixBorder函數顯示了實現。我們使用getRotationMatrix2D,因為它在不移動圖像中心的情況下縮放和旋轉圖像。我們所需要做的就是調用這個函數時,旋轉為0,縮放為1.04(也就是提升4%)。

Python

def fixBorder(frame):s = frame.shape# Scale the image 4% without moving the centerT = cv2.getRotationMatrix2D((s[1]/2, s[0]/2), 0, 1.04)frame = cv2.warpAffine(frame, T, (s[1], s[0]))return frame


C++

void fixBorder(Mat &frame_stabilized) { Mat T = getRotationvoid fixBorder(Mat &amp;frame_stabilized) {Mat T = getRotationMatrix2D(Point2f(frame_stabilized.cols/2, frame_stabilized.rows/2), 0, 1.04); warpAffine(frame_stabilized, frame_stabilized, T, frame_stabilized.size()); }Matrix2D(Point2f(frame_stabilized.cols/2, frame_stabilized.rows/2), 0, 1.04); warpAffine(frame_stabilized, frame_stabilized, T, frame_stabilized.size()); }

結果:

我們分享的視頻防抖代碼的結果如上所示。我們的目標是顯著減少運動,但不是完全消除它。

我們留給讀者去思考如何修改代碼來完全消除幀之間的移動。如果你試圖消除所有的相機運動,會有什么副作用?

目前的方法只適用于固定長度的視頻,而不適用于實時feed。我們不得不對這個方法進行大量修改,以獲得實時視頻輸出,這超出了本文的范圍,但這是可以實現的,更多的信息可以在這里找到。

https://abhitronix.github.io/2018/11/30/humanoid-AEAM-3/

優(yōu)點和缺點

優(yōu)點

這種方法對低頻運動(較慢的振動)具有良好的穩(wěn)定性。這種方法內存消耗低,因此非常適合嵌入式設備(如樹莓派)。這種方法對視頻縮放抖動有很好的效果。

缺點

這種方法對高頻擾動的抵抗效果很差。如果有一個嚴重的運動模糊,特征跟蹤將失敗,結果將不是最佳的。這種方法也不適用于滾動快門失真。

References:

  • Example video and Code reference from Nghia Ho’s?post

    http://nghiaho.com/uploads/code/videostab.cpp

  • Various References, data, and image from my?website

    https://abhitronix.github.io/

  • https://www.learnopencv.com/video-stabilization-using-point-feature-matching-in-opencv/

  • 資源傳送門(素材&代碼獲取)

    1. 掃碼關注【AI算法與圖像處理】公眾號2. 在【AI算法與圖像處理】公眾號后臺回復?【視頻防抖】?即可獲取????長按上方二維碼?2 秒 回復「視頻防抖」即可獲取資料

    覺得不錯,請點個在看

    總結

    以上是生活随笔為你收集整理的OpenCV还能实现这种效果? | 视频防抖技术的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 欧美日韩伦理片 | 国产成人精品av | 秘密基地免费观看完整版中文 | 97干干 | 51国产在线 | 最新福利在线 | 美女爆乳18禁www久久久久久 | 国产高清一区二区三区 | 青青青免费在线 | 高清不卡毛片 | 日韩精品成人 | 美女国产在线 | 亚洲精品乱码久久久久久蜜桃欧美 | 国产一区二区三区在线视频 | 穿情趣内衣被c到高潮视频 欧美性猛交xxxx黑人猛交 | 国产福利一区二区三区视频 | 欧美在线视频精品 | sao虎视频在线精品永久 | www.日韩精品 | 天天综合网入口 | 日本在线高清 | 激情小说视频在线 | 国产精品人人爽 | 色呦呦视频在线 | 黑人操白妞 | 久久在线免费观看 | 又粗又猛又爽又黄少妇视频网站 | caopeng在线 | 少妇肥臀大白屁股高清 | 国产夫妻av | 婷婷视频在线 | 山村大伦淫第1部分阅读小说 | 玖草在线| 欧美色图激情 | 日韩av一区二区三区在线观看 | 中文视频一区二区 | 99热91 | 男人操女人免费视频 | 欧美日韩免费看 | 91久久视频 | 亚洲高清av在线 | 波多野结衣一区二区三区 | 亚洲淫 | 成人黄色激情视频 | 欧美打屁股 | 亚洲一区中文字幕在线 | 国产成人自拍偷拍 | 美女试爆场恐怖电影在线观看 | 久久女人网 | 中文字幕在线看 | 香蕉久久影院 | 经典三级第一页 | 91蜜桃 | 91精品国产综合久久精品 | 国产午夜精品一区二区三区欧美 | 无码人妻精品一区二区三区99v | 男人的天堂一区二区 | 午夜影视体验区 | 黄色高潮| 国产福利视频 | 波多野吉衣av无码 | 超碰最新在线 | 又黄又骚又爽 | 欧美性色黄大片手机版 | 白丝av | 亚洲成人少妇 | 国产精品无码自拍 | 久久人妻精品白浆国产 | 亚州色图欧美色图| 中文字幕2区 | 亚洲熟女一区二区三区 | 国产精品无码人妻一区二区在线 | 日韩黄色网页 | 日韩中文视频 | 亚洲欧美激情精品一区二区 | 韩国av免费观看 | 四虎精品一区二区三区 | 欧美小视频在线观看 | 日本aaaa| 日韩女优在线观看 | 超碰97在线人人 | 亚洲天堂av影院 | 搞中出 | 精品乱码一区二区三区四区 | 国产毛片不卡 | 欧美黄色大片免费看 | 深夜福利国产精品 | 中文字幕制服诱惑 | 亚洲色图在线观看 | 亚洲国产v | 国产大片一区 | 亚洲美女视频一区 | 男人靠女人免费视频网站 | 国产麻豆a毛片 | 性欧美精品男男 | youjizz.com中国| 天天撸天天操 | 欧美特黄| 欧美天堂久久 |