在线看毛片视频-国产免费av在线-欧美日韩一区二区三区-国产成人无码av在线播放无广告-亚洲人va欧美va人人爽-国产第一草草-西班牙黄色片-四虎在线网站8848-最新av片免费网站入口-东京热无码中文字幕av专区-日本大人吃奶视频xxxx-欧美精品一区二区三区四区五区-国产片天天弄-国产免费内射又粗又爽密桃视频-欧美爱爱网站-日韩v欧美

當前位置:雨林木風下載站 > 圖形圖像教程 > 詳細頁面

PhotoShop算法原理解析系列 -  風格化-搜索邊緣。

PhotoShop算法原理解析系列 - 風格化-搜索邊緣。

更新時間:2025-09-20 文章作者:未知 信息來源:網絡 閱讀次數:

Adobe Photoshop,簡稱“PS”,是由Adobe Systems開發和發行的圖像處理軟件。Photoshop主要處理以像素所構成的數字圖像。使用其眾多的編修與繪圖工具,可以有效地進行圖片...
Adobe Photoshop,簡稱“PS”,是由Adobe Systems開發和發行的圖像處理軟件。Photoshop主要處理以像素所構成的數字圖像。使用其眾多的編修與繪圖工具,可以有效地進行圖片編輯工作。ps有很多功能,在圖像、圖形、文字、視頻、出版等各方面都有涉及。
之所以不寫系列文章一、系列文章二這樣的標題,是因為我不知道我能堅持多久。我知道我對事情的表達能力和語言的豐富性方面的天賦不高。而一段代碼需要我去用心的把他從基本原理--》初步實現--》優化速度 等過程用文字的方式表述清楚,恐怕不是一件很容易的事情。

我所掌握的一些Photoshop中的算法,不能說百分之一百就是正確的,但是從執行的效果中,大的方向肯定是沒有問題的。

目前,從別人的文章、開源的代碼以及自己的思考中我掌握的PS的算法可能有近100個吧。如果時間容許、自身的耐心容許,我會將這些東西慢慢的整理開來,雖然在很多人看來,這些算法并不具有什么研究的價值了,畢竟人家都已經商業化了。說的也有道理,我姑且把他作為自我欣賞和自我滿足的一種方式吧。

今天,我們講講查找邊緣算法?赡芪艺f了原理,很多人就不會看下去了,可有幾人層仔細的研究過呢。

  先貼個效果圖吧:

PhotoShop算法原理解析系列 -  風格化---》查找邊緣。

  原理:常見的Sobel邊緣算子的結果進行反色即可

為了能吸引你繼續看下去,我先給出我的代碼的執行速度: 針對3000*4000*3的數碼圖片,處理時間300ms。

何為Sobel,從百度抄幾張圖過來了并修改地址后:

PhotoShop算法原理解析系列 -  風格化---》查找邊緣。

  對上面兩個式子不做過多解釋,你只需要知道其中A為輸入圖像,把G作為A的輸出圖像就可以了,最后還要做一步: G=255-G,就是查找邊緣算法。

查找邊緣類算法都有個問題,對圖像物理邊緣處的像素如何處理,在平日的處理代碼中,很多人就是忽略四個邊緣的像素,作為專業的圖像處理軟件,這可是違反最基本的原則的。對邊緣進行的單獨的代碼處理,又會給編碼帶來冗余和繁瑣的問題。解決問題的最簡單又高效的方式就是采用哨兵邊界。

寫多了特效類算法的都應該知道,除了那種對單個像素進行處理的算法不需要對原始圖像做個備份(不一定去全局備份),那些需要領域信息的算法由于算法的前一步修改了一個像素,而算法的當前步需要未修改的像素值,因此,一般這種算法都會在開始前對原始圖像做個克隆,在計算時,需要的領域信息從克隆的數據中讀取。如果這個克隆的過程不是完完全全的克隆,而是擴展適當邊界后再克隆,就有可能解決上述的邊界處理問題。

  比如對下面的一個圖,19×14像素大小,我們的備份圖為上下左右各擴展一個像素的大小,并用邊緣的值填充,變為21*16大小:

PhotoShop算法原理解析系列 -  風格化---》查找邊緣。 PhotoShop算法原理解析系列 -  風格化---》查找邊緣。

  這樣,在計算原圖的3*3領域像素時,從擴展后的克隆圖對應點取樣,就不會出現不在圖像范圍內的問題了,編碼中即可以少很多判斷,可讀性也加強了。

在計算速度方面,注意到上面的計算式G中有個開方運算,這是個耗時的過程,由于圖像數據的特殊性,都必須是整數,可以采用查找表的方式優化速度,這就需要考慮表的建立。

針對本文的具體問題,我們分兩步討論,第一:針對根號下的所有可能情況建立查找表?纯碐X和GY的計算公式,考慮下兩者的平方和的最大值是多少,可能要考慮一會吧。第二:就是只建立0^2到255^2范圍內的查找表,然后確保根號下的數字不大于255^2。為什么可以這樣做,就是因為圖像數據的最大值就是255,如果根號下的數字大于255^2,在求出開方值后,還是需要規整為255的。因此,本算法中應該取后者。

private void CmdFindEdgesArray_Click(object sender, EventArgs e)
{    int X, Y;    int Width, Height, Stride, StrideC, HeightC;    int Speed, SpeedOne, SpeedTwo, SpeedThree;    int BlueOne, BlueTwo, GreenOne, GreenTwo, RedOne, RedTwo;    int PowerRed, PowerGreen, PowerBlue;
    Bitmap Bmp = (Bitmap)Pic.Image;    if (Bmp.PixelFormat != PixelFormat.Format24bppRgb) throw new Exception("不支持的圖像格式.");    byte[] SqrValue = new byte[65026];    for (Y = 0; Y < 65026; Y++) SqrValue[Y] = (byte)(255 - (int)Math.Sqrt(Y));      // 計算查找表,注意已經砸查找表里進行了反色
    Width = Bmp.Width; Height = Bmp.Height; Stride = (int)((Bmp.Width * 3 + 3) & 0XFFFFFFFC);
    StrideC = (Width + 2) * 3; HeightC = Height + 2;                                 // 寬度和高度都擴展2個像素

    byte[] ImageData = new byte[Stride * Height];                                    // 用于保存圖像數據,(處理前后的都為他)
    byte[] ImageDataC = new byte[StrideC * HeightC];                                // 用于保存擴展后的圖像數據

    fixed (byte* Scan0 = &ImageData[0])
    {
        BitmapData BmpData = new BitmapData();
        BmpData.Scan0 = (IntPtr)Scan0;                                              //  設置為字節數組的的第一個元素在內存中的地址
        BmpData.Stride = Stride;
        Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, Bmp.Height), ImageLockMode.ReadWrite | ImageLockMode.UserInputBuffer, PixelFormat.Format24bppRgb, BmpData);

        Stopwatch Sw = new Stopwatch();                                             //  只獲取計算用時        Sw.Start();        for (Y = 0; Y < Height; Y++)
        {
            System.Buffer.BlockCopy(ImageData, Stride * Y, ImageDataC, StrideC * (Y + 1), 3);        // 填充擴展圖的左側第一列像素(不包括第一個和最后一個點)
            System.Buffer.BlockCopy(ImageData, Stride * Y + (Width - 1) * 3, ImageDataC, StrideC * (Y + 1) + (Width + 1) * 3, 3);  // 填充最右側那一列的數據
            System.Buffer.BlockCopy(ImageData, Stride * Y, ImageDataC, StrideC * (Y + 1) + 3, Width * 3);
        }
        System.Buffer.BlockCopy(ImageDataC, StrideC, ImageDataC, 0, StrideC);              //  第一行
        System.Buffer.BlockCopy(ImageDataC, (HeightC - 2) * StrideC, ImageDataC, (HeightC - 1) * StrideC, StrideC);    //  最后一行               

        for (Y = 0; Y < Height; Y++)
        {
            Speed = Y * Stride;
            SpeedOne = StrideC * Y;            for (X = 0; X < Width; X++)
            {
                SpeedTwo = SpeedOne + StrideC;          //  盡量減少計算
                SpeedThree = SpeedTwo + StrideC;        //  下面的就是嚴格的按照Sobel算字進行計算,代碼中的*2一般會優化為移位或者兩個Add指令的,如果你不放心,當然可以直接改成移位
                BlueOne = ImageDataC[SpeedOne] + 2 * ImageDataC[SpeedTwo] + ImageDataC[SpeedThree] - ImageDataC[SpeedOne + 6] - 2 * ImageDataC[SpeedTwo + 6] - ImageDataC[SpeedThree + 6];
                GreenOne = ImageDataC[SpeedOne + 1] + 2 * ImageDataC[SpeedTwo + 1] + ImageDataC[SpeedThree + 1] - ImageDataC[SpeedOne + 7] - 2 * ImageDataC[SpeedTwo + 7] - ImageDataC[SpeedThree + 7];
                RedOne = ImageDataC[SpeedOne + 2] + 2 * ImageDataC[SpeedTwo + 2] + ImageDataC[SpeedThree + 2] - ImageDataC[SpeedOne + 8] - 2 * ImageDataC[SpeedTwo + 8] - ImageDataC[SpeedThree + 8];
                BlueTwo = ImageDataC[SpeedOne] + 2 * ImageDataC[SpeedOne + 3] + ImageDataC[SpeedOne + 6] - ImageDataC[SpeedThree] - 2 * ImageDataC[SpeedThree + 3] - ImageDataC[SpeedThree + 6];
                GreenTwo = ImageDataC[SpeedOne + 1] + 2 * ImageDataC[SpeedOne + 4] + ImageDataC[SpeedOne + 7] - ImageDataC[SpeedThree + 1] - 2 * ImageDataC[SpeedThree + 4] - ImageDataC[SpeedThree + 7];
                RedTwo = ImageDataC[SpeedOne + 2] + 2 * ImageDataC[SpeedOne + 5] + ImageDataC[SpeedOne + 8] - ImageDataC[SpeedThree + 2] - 2 * ImageDataC[SpeedThree + 5] - ImageDataC[SpeedThree + 8];

                PowerBlue = BlueOne * BlueOne + BlueTwo * BlueTwo;
                PowerGreen = GreenOne * GreenOne + GreenTwo * GreenTwo;
                PowerRed = RedOne * RedOne + RedTwo * RedTwo;                if (PowerBlue > 65025) PowerBlue = 65025;           //  處理掉溢出值
                if (PowerGreen > 65025) PowerGreen = 65025;                if (PowerRed > 65025) PowerRed = 65025;
                ImageData[Speed] = SqrValue[PowerBlue];             //  查表
                ImageData[Speed + 1] = SqrValue[PowerGreen];
                ImageData[Speed + 2] = SqrValue[PowerRed];

                Speed += 3;                                  // 跳往下一個像素
                SpeedOne += 3;
            }
        }
        Sw.Stop();        this.Text = "計算用時: " + Sw.ElapsedMilliseconds.ToString() + " ms";

        Bmp.UnlockBits(BmpData);                         //  必須先解鎖,否則Invalidate失敗     }
    Pic.Invalidate();
}

  為簡單的起見,這里先是用的C#的一維數組實現的,并且計時部分未考慮圖像數據的獲取和更新, 因為真正的圖像處理過程中圖像數據肯定是已經獲得的了。

針對上述代碼,編譯為Release模式后,執行編譯后的EXE,對于3000*4000*3的彩色圖像,耗時約480ms,如果你是在IDE的模式先運行,記得一定要在選項--》調試--》常規里不勾選 在模塊加載時取消JIT優化(僅限托管)一欄。

PhotoShop算法原理解析系列 -  風格化---》查找邊緣。

上述代碼中的填充克隆圖數據時并沒有新建一副圖,然后再填充其中的圖像數據,而是直接填充一個數組,圖像其實不就是一片連續內存加一點頭信息嗎,頭信息已經有了,所以只要一片內存就夠了。

克隆數據的填充采用了系統Buffer.BlockCopy函數,該函數類似于我們以前常用CopyMemory,速度非常快。

為進一步調高執行速度,我們首先來看看算法的關鍵耗時部位的代碼,即for (X = 0; X < Width; X++)內部的代碼,我們取一行代碼的反編譯碼來看看:

 BlueOne = ImageDataC[SpeedOne] + 2 * ImageDataC[SpeedTwo] + ImageDataC[SpeedThree] - ImageDataC[SpeedOne + 6] - 2 * ImageDataC[SpeedTwo + 6] - ImageDataC[SpeedThree + 6];

00000302 cmp ebx,edi 00000304 jae 0000073C             // 數組是否越界? 0000030a movzx eax,byte ptr [esi+ebx+8]    //  將ImageDataC[SpeedOne]中的數據傳送的eax寄存器 0000030f mov dword ptr [ebp-80h],eax 00000312 mov edx,dword ptr [ebp-2Ch] 00000315 cmp edx,edi 00000317 jae 0000073C            // 數組是否越界?            0000031d movzx edx,byte ptr [esi+edx+8]   //   將ImageDataC[SpeedTwo]中的數據傳送到edx寄存器00000322 add edx,edx             // 計算2*ImageDataC[SpeedTwo]    00000324 add eax,edx             // 計算ImageDataC[SpeedOne]+2*ImageDataC[SpeedTwo],并保存在eax寄存器中           00000326 cmp ecx,edi 00000328 jae 0000073C 0000032e movzx edx,byte ptr [esi+ecx+8]   // 將ImageDataC[SpeedThree]中的數據傳送到edx寄存器00000333 mov dword ptr [ebp+FFFFFF78h],edx 00000339 add eax,edx 0000033b lea edx,[ebx+6] 0000033e cmp edx,edi 00000340 jae 0000073C 00000346 movzx edx,byte ptr [esi+edx+8] 0000034b mov dword ptr [ebp+FFFFFF7Ch],edx 00000351 sub eax,edx 00000353 mov edx,dword ptr [ebp-2Ch] 00000356 add edx,6 00000359 cmp edx,edi 0000035b jae 0000073C 00000361 movzx edx,byte ptr [esi+edx+8] 00000366 add edx,edx 00000368 sub eax,edx 0000036a lea edx,[ecx+6] 0000036d cmp edx,edi 0000036f jae 0000073C 00000375 movzx edx,byte ptr [esi+edx+8] 0000037a mov dword ptr [ebp+FFFFFF74h],edx 00000380 sub eax,edx 00000382 mov dword ptr [ebp-30h],eax

   上述匯編碼我只注釋一點點,其中最0000073c 標號,我們跟蹤后返現是調用了另外一個函數:

0000073c call 685172A4

我們看到在獲取每一個數組元素前,都必須執行一個cmp 和 jae指令,從分析我認為這里是做類似于判斷數組的下標是否越界之類的工作的。如果我們能確保我們的算法那不會產生越界,這部分代碼有很用呢,不是耽誤我做正事嗎。

為此,我認為需要在C#中直接利用指針來實現算法,C#中有unsafe模式,也有指針,所以很方便,而且指針的表達即可以用*,也可以用[],比如*(P+4) 和P[4]是一個意思。那么只要做很少的修改就可以將上述代碼修改為指針版。

private void CmdFindEdgesPointer_Click(object sender, EventArgs e)
    {        int X, Y;        int Width, Height, Stride, StrideC, HeightC;        int Speed, SpeedOne, SpeedTwo, SpeedThree;        int BlueOne, BlueTwo, GreenOne, GreenTwo, RedOne, RedTwo;        int PowerRed, PowerGreen, PowerBlue;
        Bitmap Bmp = (Bitmap)Pic.Image;        if (Bmp.PixelFormat != PixelFormat.Format24bppRgb) throw new Exception("不支持的圖像格式.");        byte[] SqrValue = new byte[65026];        for (Y = 0; Y < 65026; Y++) SqrValue[Y] = (byte)(255 - (int)Math.Sqrt(Y));      // 計算查找表,注意已經砸查找表里進行了反色
        Width = Bmp.Width; Height = Bmp.Height; Stride = (int)((Bmp.Width * 3 + 3) & 0XFFFFFFFC);
        StrideC = (Width + 2) * 3; HeightC = Height + 2;                                 // 寬度和高度都擴展2個像素

        byte[] ImageData = new byte[Stride * Height];                                    // 用于保存圖像數據,(處理前后的都為他)
        byte[] ImageDataC = new byte[StrideC * HeightC];                                 // 用于保存擴展后的圖像數據

        fixed (byte* P = &ImageData[0], CP = &ImageDataC[0], LP = &SqrValue[0])
        {            byte* DataP = P, DataCP = CP, LutP = LP;
            BitmapData BmpData = new BitmapData();
            BmpData.Scan0 = (IntPtr)DataP;                                              //  設置為字節數組的的第一個元素在內存中的地址
            BmpData.Stride = Stride;
            Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, Bmp.Height), ImageLockMode.ReadWrite | ImageLockMode.UserInputBuffer, PixelFormat.Format24bppRgb, BmpData);

            Stopwatch Sw = new Stopwatch();                                             //  只獲取計算用時            Sw.Start();            for (Y = 0; Y < Height; Y++)
            {
                System.Buffer.BlockCopy(ImageData, Stride * Y, ImageDataC, StrideC * (Y + 1), 3);        // 填充擴展圖的左側第一列像素(不包括第一個和最后一個點)
                System.Buffer.BlockCopy(ImageData, Stride * Y + (Width - 1) * 3, ImageDataC, StrideC * (Y + 1) + (Width + 1) * 3, 3);  // 填充最右側那一列的數據
                System.Buffer.BlockCopy(ImageData, Stride * Y, ImageDataC, StrideC * (Y + 1) + 3, Width * 3);
            }
            System.Buffer.BlockCopy(ImageDataC, StrideC, ImageDataC, 0, StrideC);              //  第一行
            System.Buffer.BlockCopy(ImageDataC, (HeightC - 2) * StrideC, ImageDataC, (HeightC - 1) * StrideC, StrideC);    //  最后一行               

            for (Y = 0; Y < Height; Y++)
            {
                Speed = Y * Stride;
                SpeedOne = StrideC * Y;                for (X = 0; X < Width; X++)
                {
                    SpeedTwo = SpeedOne + StrideC;          //  盡量減少計算
                    SpeedThree = SpeedTwo + StrideC;        //  下面的就是嚴格的按照Sobel算字進行計算,代碼中的*2一般會優化為移位或者兩個Add指令的,如果你不放心,當然可以直接改成移位
                    BlueOne = DataCP[SpeedOne] + 2 * DataCP[SpeedTwo] + DataCP[SpeedThree] - DataCP[SpeedOne + 6] - 2 * DataCP[SpeedTwo + 6] - DataCP[SpeedThree + 6];
                    GreenOne = DataCP[SpeedOne + 1] + 2 * DataCP[SpeedTwo + 1] + DataCP[SpeedThree + 1] - DataCP[SpeedOne + 7] - 2 * DataCP[SpeedTwo + 7] - DataCP[SpeedThree + 7];
                    RedOne = DataCP[SpeedOne + 2] + 2 * DataCP[SpeedTwo + 2] + DataCP[SpeedThree + 2] - DataCP[SpeedOne + 8] - 2 * DataCP[SpeedTwo + 8] - DataCP[SpeedThree + 8];
                    BlueTwo = DataCP[SpeedOne] + 2 * DataCP[SpeedOne + 3] + DataCP[SpeedOne + 6] - DataCP[SpeedThree] - 2 * DataCP[SpeedThree + 3] - DataCP[SpeedThree + 6];
                    GreenTwo = DataCP[SpeedOne + 1] + 2 * DataCP[SpeedOne + 4] + DataCP[SpeedOne + 7] - DataCP[SpeedThree + 1] - 2 * DataCP[SpeedThree + 4] - DataCP[SpeedThree + 7];
                    RedTwo = DataCP[SpeedOne + 2] + 2 * DataCP[SpeedOne + 5] + DataCP[SpeedOne + 8] - DataCP[SpeedThree + 2] - 2 * DataCP[SpeedThree + 5] - DataCP[SpeedThree + 8];

                    PowerBlue = BlueOne * BlueOne + BlueTwo * BlueTwo;
                    PowerGreen = GreenOne * GreenOne + GreenTwo * GreenTwo;
                    PowerRed = RedOne * RedOne + RedTwo * RedTwo;                    if (PowerBlue > 65025) PowerBlue = 65025;           //  處理掉溢出值
                    if (PowerGreen > 65025) PowerGreen = 65025;                    if (PowerRed > 65025) PowerRed = 65025;

                    DataP[Speed] = LutP[PowerBlue];                     //  查表
                    DataP[Speed + 1] = LutP[PowerGreen];
                    DataP[Speed + 2] = LutP[PowerRed];

                    Speed += 3;                                         //  跳往下一個像素
                    SpeedOne += 3;
                }
            }
            Sw.Stop();            this.Text = "計算用時: " + Sw.ElapsedMilliseconds.ToString() + " ms";

            Bmp.UnlockBits(BmpData);                         //  必須先解鎖,否則Invalidate失敗         }
        Pic.Invalidate();
    }

同樣的效果,同樣的圖像,計算用時330ms。

我們在來看看相同代碼的匯編碼:

BlueOne = DataCP[SpeedOne] + 2 * DataCP[SpeedTwo] + DataCP[SpeedThree] - DataCP[SpeedOne + 6] - 2 * DataCP[SpeedTwo + 6] - DataCP[SpeedThree + 6];

00000318 movzx eax,byte ptr [esi+edi] 0000031c mov dword ptr [ebp-74h],eax 0000031f movzx edx,byte ptr [esi+ebx] 00000323 add edx,edx 00000325 add eax,edx 00000327 movzx edx,byte ptr [esi+ecx] 0000032b mov dword ptr [ebp-7Ch],edx 0000032e add eax,edx 00000330 movzx edx,byte ptr [esi+edi+6] 00000335 mov dword ptr [ebp-78h],edx 00000338 sub eax,edx 0000033a movzx edx,byte ptr [esi+ebx+6] 0000033f add edx,edx 00000341 sub eax,edx 00000343 movzx edx,byte ptr [esi+ecx+6] 00000348 mov dword ptr [ebp-80h],edx 0000034b sub eax,edx 0000034d mov dword ptr [ebp-30h],eax

生產的匯編碼簡潔,意義明確,對比下少了很多指令。當然速度會快很多。

注意這一段代碼:

  fixed (byte* P = &ImageData[0], CP = &ImageDataC[0], LP = &SqrValue[0])
        {            byte* DataP = P, DataCP = CP, LutP = LP;

如果你把更換為:

  fixed (byte* DataP = &ImageData[0], DataCP = &ImageDataC[0], LutP = &SqrValue[0])
{

代碼的速度反而比純數組版的還慢,至于為什么,實踐為王吧,我也沒有去分析,反正我知道有這個結果。你可以參考鐵哥的一篇文章:

閑談.Net類型之public的不public,fixed的不能fixed

當然這個還可以進一步做小動作的的優化,比如movzx eax,byte ptr [esi+edi] 這句中,esi其實就是數組的基地址,向這樣寫DataCP[SpeedOne] ,每次都會有這個基址+偏移的計算的,如果能實時直接動態控制一個指針變量,使他直接指向索要的位置,則少了一次加法,雖然優化不是很明顯,基本可以達到問中之前所提到的300ms的時間了。具體的代碼可見附件。

很多人可能對我這些東西不感冒,說這些東西丟給GPU比你現在的.......希望這些朋友也不要過分的打擊吧,每個人都有自己的愛好,我只愛好CPU。

更多PhotoShop算法原理解析系列 - 風格化-查找邊緣。相關文章請關注PHP中文網!



Photoshop默認保存的文件格式,可以保留所有有圖層、色版、通道、蒙版、路徑、未柵格化文字以及圖層樣式等。

溫馨提示:喜歡本站的話,請收藏一下本站!

本類教程下載

系統下載排行

在线看毛片视频-国产免费av在线-欧美日韩一区二区三区-国产成人无码av在线播放无广告-亚洲人va欧美va人人爽-国产第一草草-西班牙黄色片-四虎在线网站8848-最新av片免费网站入口-东京热无码中文字幕av专区-日本大人吃奶视频xxxx-欧美精品一区二区三区四区五区-国产片天天弄-国产免费内射又粗又爽密桃视频-欧美爱爱网站-日韩v欧美
  • <li id="86scu"><menu id="86scu"></menu></li>
    <li id="86scu"></li>
    <button id="86scu"></button>
  • <s id="86scu"></s><button id="86scu"><menu id="86scu"></menu></button>
  • 三上悠亚在线一区二区| www.天天射.com| 国产 欧美 日本| 成年人午夜免费视频| 已婚少妇美妙人妻系列| 日韩a级黄色片| 97人人爽人人| 午夜视频你懂的| 日本免费黄视频| 99久久久精品视频| 成年人三级视频| 在线观看免费不卡av| 国产精品亚洲二区在线观看| cao在线观看| 91免费网站视频| 91丨九色丨蝌蚪| 久久久久久久片| www.日日操| 男人舔女人下面高潮视频| 久久久久久人妻一区二区三区| eeuss中文| 黄频视频在线观看| 天天操天天干天天玩| 青青草原播放器| 做a视频在线观看| 在线观看亚洲色图| www.这里只有精品| 日韩av在线中文| 超碰人人草人人| 欧美性受xxxxxx黑人xyx性爽| 天天干天天综合| 欧美成人三级在线播放| 欧美在线aaa| 色中文字幕在线观看| 裸体大乳女做爰69| av日韩一区二区三区| 免费一级特黄毛片| 欧美日韩亚洲一| av免费中文字幕| 蜜桃免费在线视频| 福利视频999| 伊人网在线免费| 免费观看国产精品视频| 成年网站在线免费观看| 国产色视频在线播放| 26uuu成人| 日韩国产一级片| 一区二区三区免费播放| а 天堂 在线| 欧美精品一区二区三区三州| 久久久久久久久久久免费视频| 成年女人18级毛片毛片免费 | 日本中文字幕二区| 国产日韩第一页| 成人黄色av片| 国产xxxxhd| 成人亚洲精品777777大片| 国产在线拍揄自揄拍无码| 国产美女无遮挡网站| 成人午夜视频免费观看| 午夜啪啪免费视频| 亚洲一级片网站| 国产xxxx振车| 99热手机在线| 超级碰在线观看| 成人亚洲视频在线观看| 中国女人做爰视频| 日日噜噜噜噜久久久精品毛片| 国产资源中文字幕| 无人在线观看的免费高清视频| 好色先生视频污| 天天插天天操天天射| av在线免费观看国产| jizz欧美性11| 国产美女无遮挡网站| 黄色a级在线观看| 亚洲综合色在线观看| 香港三级韩国三级日本三级| 黄色免费高清视频| 色戒在线免费观看| www.亚洲天堂网| 国产精品www在线观看| 九九九九九伊人| 搡女人真爽免费午夜网站| 黄色激情在线视频| 97精品国产97久久久久久粉红| 亚洲第一中文av| 久久精品一区二| 日韩精品视频一区二区在线观看| 欧美日韩中文字幕在线播放| 日本中文字幕影院| 最新天堂在线视频| 亚洲无吗一区二区三区| 50路60路老熟妇啪啪| 日韩网址在线观看| 欧美日韩二三区| 欧美成人一区二区在线观看| 欧美国产视频一区| 分分操这里只有精品| www.xxx麻豆| 九一国产精品视频| 2018日日夜夜| 国产免费成人在线| 日韩av资源在线| 九热视频在线观看| 最新国产黄色网址| 91免费网站视频| 免费在线黄网站| aa视频在线播放| 99免费视频观看| www.51色.com| 日韩精品手机在线观看| 男女激情免费视频| 国产精品秘入口18禁麻豆免会员 | 夜夜夜夜夜夜操| 成人午夜视频免费在线观看| 美女一区二区三区视频| 五月婷婷激情久久| 中文字幕无码不卡免费视频| 久久黄色片视频| 久久婷婷五月综合色国产香蕉| 黄色激情在线视频| 欧美日本视频在线观看| 男人操女人免费软件| 中文字幕22页| 青青草影院在线观看| 99re精彩视频| 国内外成人激情免费视频| 97国产在线播放| 亚洲男人天堂av在线| 成人性生活视频免费看| 午夜在线观看av| 欧美日韩视频免费| 超碰av在线免费观看| 91免费国产精品| 欧美伦理视频在线观看| 日本一道在线观看| 91网址在线播放| 激情五月婷婷六月| 亚洲精品视频三区| 国产青青在线视频| 精品嫩模一区二区三区| 国产黄色特级片| 久久久久久免费看| 不卡中文字幕在线观看| 女人天堂av手机在线| 日本三级中文字幕在线观看| 别急慢慢来1978如如2| 成人精品视频在线播放| 亚洲18在线看污www麻豆| 亚洲色欲综合一区二区三区| 国产尤物av一区二区三区| 另类小说色综合| 国产精品亚洲二区在线观看| 免费视频爱爱太爽了| 波多野结衣激情| 日韩成人av免费| 亚洲黄色a v| 免费观看日韩毛片| 国内精品在线观看视频| 中国女人做爰视频| 欧美亚洲视频一区| 1314成人网| 搡的我好爽在线观看免费视频| 免费在线观看的毛片| 一本大道熟女人妻中文字幕在线| 成人短视频在线观看免费| 久久国产精品免费观看| gogogo免费高清日本写真| 婷婷中文字幕在线观看| 一区二区久久精品| 中文字幕国产高清| 日本不卡一区二区三区四区| 超碰成人在线播放| 夜夜爽久久精品91| www.-级毛片线天内射视视| 香蕉视频色在线观看| 亚洲成人动漫在线| 欧美乱做爰xxxⅹ久久久| 97久久国产亚洲精品超碰热| 一二三四中文字幕| 97在线国产视频| 成人在线看视频| 亚洲最大成人在线观看| 一级黄色片在线免费观看| 手机成人av在线| 和岳每晚弄的高潮嗷嗷叫视频 | 精品国产乱码久久久久久1区二区| 99久热在线精品视频| 日本福利视频在线观看| 成人免费看片'免费看| 亚洲xxxx2d动漫1| 日本老熟妇毛茸茸| 91激情视频在线| 冲田杏梨av在线| 五月天亚洲视频| 日韩人妻精品一区二区三区| 亚洲va在线va天堂va偷拍| 在线观看国产一级片| 亚洲精品久久久久久宅男|