菜单

SSE图像算法优化系列三:超快速导向滤波实现过程记录(欢迎挑战)SSE图像算法优化系列三:超快导向滤波实现过程记录(欢迎挑战)

2018年9月25日 - 中甲报道

  自从何凯明提出导向滤波后,因为该算法的简单性和管事,该算法得到了广泛的动,以至于新版的matlab都拿其当标准自带的函数之一了,利用他得化解的有的保边滤波器的能迎刃而解之问题,比如细节增强、HDR压缩、细节羽化、去雾、风格化,而且由于其保边特性,如果过多民俗函数中利用高斯滤波或者都值滤波的地方用他代表,能杀好解决一些胜似边缘之连通不自然问题,比如retinex、Highlight/shadow等采用被,因此,快速的兑现该算法有很强的适用意义。

  自从何凯明提出导向滤波后,因为那算法的简单性和行,该算法得到了大面积的运用,以至于新版的matlab都以那个用作正式自带的函数之一了,利用他可以缓解之持有的保边滤波器的能够解决的题目,比如细节增强、HDR压缩、细节羽化、去雾、风格化,而且由于其保边特性,如果博传统函数中动用高斯滤波或者都值滤波的地方用外取代,能十分好解决一部分赛边缘之接不自问题,比如retinex、Highlight/shadow等使用被,因此,快速的兑现该算法有十分强的适用意义。

  本文简要的笔录了自我在优化导向滤波实现之经过遭到所适用的优化措施跟有些细节,以免日老了后好还未记了,但是要不要向自身直接索取源代码。

  本文简要的笔录了我于优化导向滤波实现的经过遭到所适用的优化措施和有细节,以免日久了后自己都不记得了,但是要不要向自家直接索取源代码。

     
自以为眼前自家优化的速在CPU版本中老不便有人能够超过了(仅仅用CPU、不用多线程,下采样率0.2),如果哪位起还快的算法,在第三正公证的情景下,我甘愿提供1000首位奖励^_^。

     
自当目前本人优化的速在CPU版本中充分麻烦有人能跳了(仅仅以CPU、不用多线程,下采样率0.2),如果哪个起再度快的算法,在第三正值公证的情下,我甘愿提供1000正奖励^_^。

     
何凯明以导向滤波一和平之连带资料被提供了那matlab代码,或者用脚的流程也可以清晰的表达:

     
何凯明以导向滤波一温软之连带材料遭受提供了彼matlab代码,或者用脚的流程也可清楚的表达:

图片 1

图片 2

  我们视了面的6软沾mean计算的历程,也就算是浮点数的boxfilter,这个东西都是一味掉牙的一个算法了,我于几年前研究过opencv内部的此算法,并且提出了同一种植比opencv实现重新快的主意,详见解析opencv中Box
Filter的贯彻并提出更加快的方案(源码共享) 一中和。不过那里的拍卖时对字节数据的,其内部用到了一些整形数据的SSE优化,如果原本数据是浮点数,那倒就更是简单了,因为SSE指令生来就为浮点数服务的。

  我们看看了方的6赖得到mean计算的进程,也就是是浮点数的boxfilter,这个事物就是老掉牙的一个算法了,我于几年前研究了opencv内部的此算法,并且提出了同一种植比opencv实现又快的不二法门,详见解析opencv中Box
Filter的贯彻并提出更进一步加速的方案(源码共享) 一平和。不过那里的处理常对字节数据的,其中间用到了有整形数据的SSE优化,如果原本数据是浮点数,那倒就越简易了,因为SSE指令生来就啊浮点数服务之。

     
但是就是是如此,由于6涂鸦计算和中间的旁部分浮点运算,依然被通算法带来了杀充分的运算开销和内存开销,在无数场所还是无法满足要求的,比如实时去雾等场景。在最初我的很快去雾实现中,都是先期使用下采样图的导向滤波结果,然后再次双线性插值放大得到大图的透射率图,虽然以视觉效果上能够解决去雾算法的速问题,但是只要是其余场景的导向滤波需求,还是会视成千上万弱点的。

     
但是就算是如此,由于6坏计算和中间的其它组成部分浮点运算,依然被整算法带来了十分要命之运算开销和内存开销,在不少场合还是无法满足要求的,比如实时去雾等场景。在前期我的高效去雾实现着,都是先期以下采样图的导向滤波结果,然后再次双线性插值放大得到大图的透射率图,虽然在视觉效果上能够迎刃而解去雾算法的速度问题,但是若是其余场景的导向滤波需求,还是会看到不少毛病的。

      何凯明在2015同时刊出了扳平篇《Fast
Guided Filter》的文章,阐述了同栽颇实用的重新便捷的导向滤波流程:

      何凯明在2015并且登了平等首《Fast
Guided Filter》的文章,阐述了一如既往种很实用的复敏捷的导向滤波流程:

图片 3

图片 4

 
   我刚好领取的于夺雾中自我实用的小Trick实际上即便是第六步及第七步不同,我的方而发挥如下:

 
   我刚好领取的以错过雾中自我实用的小Trick实际上就是第六步及第七步不同,我的不二法门可发挥如下:

       6: q = meana. * +
meanb

       6: q = meana. * +
meanb

       7:   q = fupsample(q,
s)

       7:   q = fupsample(q,
s)

     
很明显,由于I的插足计算,何的做法能再次老程度上保障结果及原汁原味的类似,而自的主意则会发生比生之丁相似,所以住户大神就是大神。

     
很明显,由于I的插足计算,何的做法会再次甚程度达保持结果和原汁原味的类,而自己之措施尽管会来于生的块相似,所以住户大神就是大神。

      在乌的舆论中都证明下采样比例 s
取4时,计算的结果跟纯粹结果为或那个守的,我以自己之落实里s
取到了5。

      在何的论文被已认证下采样比例 s
取4时,计算的结果以及规范结果吧还是老靠近的,我当自己的贯彻里s
取到了5。

     
这样改后,所有的boxfilter均是本着生取样后的多寡进行拍卖,当s=4时,计算量减少及原始的1/16,而s=5,则减少至了本来的1/25,当然这时刻差不多了2独下取样与2个达标取样的算法,下取样由于是压缩,计算量很有点,无需关注,而落得采样,计算量和原图大小有关,根据我的评测,这个上采样的耗时可能占所有过程的一般时间左右底,是不行值得注意优化的。

     
这样改后,所有的boxfilter均是对准生取样后的数额进行处理,当s=4时,计算量减少至原的1/16,而s=5,则缩减到了原来的1/25,当然这时节基本上矣2只下取样和2独及取样的算法,下取样由于是缩小,计算量很有些,无需关注,而达到采样,计算量和原图大小有关,根据自身的评测,这个上采样的耗时可能占全体经过的貌似时间左右之,是充分值得注意优化的。

   
 首先,第一,步骤6惨遭之星星点点只采样过程不要分开写,直接写及跟一个for循环内部,这样可节省成千上万坐标的乘除过程,第二,这里一般的达成采样通常用双线性插值就OK了,网络直达发出许多关于双线性插值的SSE优化的代码,但是那些基本都是对准32号的图像做的优化,搬至24各类和8各类备受凡免适用的,而我辈会于50%上述之票房价值中相遇24个图像,所以说啊,网络直达之物就多,但花太少。

   
 首先,第一,步骤6面临的有数个采样过程不要分开写,直接写到和一个for循环内部,这样可节约成千上万坐标的算计过程,第二,这里一般的齐采样通常以对线性插值就OK了,网络达到有诸多有关双线性插值的SSE优化的代码,但是那些基本都是指向32号的图像做的优化,搬至24各项与8各项受凡免适用的,而我们见面以50%以上之概率中碰到24员图像,所以说啊,网络上之东西便多,但花太少。

     
我动用的一个优化措施时,先进行水平方向的达成采样到一个缓冲区中(Width  *
SmallH),然后在从这个缓冲区中挨高度方向缓冲到(Width *
Height),如下图所示:

     
我以的一个优化措施时,先进行水平方向的直达采样到一个缓冲区中(Width  *
SmallH),然后于由者缓冲区中沿着高度方向缓冲到(Width *
Height),如下图所示:

       
 图片 5 
 ———–——>   图片 6 
 ———–——>  图片 7

       
 图片 8 
 ———–——>   图片 9 
 ———–——>  图片 10

     
 由于此上采样是对准浮点型的数目,所以中间的精度损失问题得以毫不考虑,而若是图像的字节数据,则只要慎重了。

     
 由于这个上采样是本着浮点型的数,所以中级的精度损失问题得以毫无考虑,而只要是图像的字节数据,则使慎重了。

     
 由地方的首先个图及第二单图的大概代码如下:

     
 由地方的首先独图及第二个图的大体代码如下:

 for (int Y = 0; Y < SmallH; Y++)
 {
     float PosX = 0;
     float AddX = (SmallW - 1.0f) / Width;        //  主要是为了减少下面插值向右增1的指针超过范围,但这样做其实是和精确的算法有一点点差异的
     float *LinePDA = TempA + Y * Width * Channel;    //  TempA和TempB为临时分配的大小为(SmallH * Width * Channel * sizeof(float)大小的内存
     float *LinePDB = TempB + Y * Width * Channel;
     float *LinePA = MeanA + Y * SmallW * Channel;
     float *LinePB = MeanB + Y * SmallW * Channel;
     if (Channel == 1)
     {
         for (int X = 0; X < Width; X++)
         {
             int XX = (int)PosX;
             float PartXX = PosX - XX;
             float InvertXX = 1 - PartXX;
             float *PtLeftA = LinePA + XX;
             float *PtLeftB = LinePB + XX;
             LinePDA[X] = PtLeftA[0] * InvertXX + PtLeftA[1] * PartXX;
             LinePDB[X] = PtLeftB[0] * InvertXX + PtLeftB[1] * PartXX;
             PosX += AddX;
         }
     }
   //  ...................
 }
 for (int Y = 0; Y < SmallH; Y++)
 {
     float PosX = 0;
     float AddX = (SmallW - 1.0f) / Width;        //  主要是为了减少下面插值向右增1的指针超过范围,但这样做其实是和精确的算法有一点点差异的
     float *LinePDA = TempA + Y * Width * Channel;    //  TempA和TempB为临时分配的大小为(SmallH * Width * Channel * sizeof(float)大小的内存
     float *LinePDB = TempB + Y * Width * Channel;
     float *LinePA = MeanA + Y * SmallW * Channel;
     float *LinePB = MeanB + Y * SmallW * Channel;
     if (Channel == 1)
     {
         for (int X = 0; X < Width; X++)
         {
             int XX = (int)PosX;
             float PartXX = PosX - XX;
             float InvertXX = 1 - PartXX;
             float *PtLeftA = LinePA + XX;
             float *PtLeftB = LinePB + XX;
             LinePDA[X] = PtLeftA[0] * InvertXX + PtLeftA[1] * PartXX;
             LinePDB[X] = PtLeftB[0] * InvertXX + PtLeftB[1] * PartXX;
             PosX += AddX;
         }
     }
   //  ...................
 }

  这段代码用SSE去优化的侵害的脑细胞有点多,而且由于那个计算量不是极度非常,意义或者有限。

  这段代码用SSE去优化的加害的脑细胞有点多,而且由于该计算量不是最好老,意义可能有数。

  而出于第二个图及第三单图的长河大概可使得下面的代码表述:

  而出于第二个图及第三单图的历程大概可实用下面的代码表述:

 for (int Y = 0; Y < Height; Y++)
 {
     float PosY = Y * (SmallH - 1.0f) / Height;
     int YY = (int)PosY;
     float PartYY = PosY - YY;
     float InvertYY = 1 - PartYY;
     byte *LinePS = Guide + Y * Stride;
     byte *LinePD = Dest + Y * Stride;
     float *PtTopA = TempA + YY * Width * Channel;
     float *PtBottomA = PtTopA + Width * Channel;
     float *PtTopB = TempB + YY * Width * Channel;
     float *PtBottomB = PtTopB + Width * Channel;
     for (int X = 0;; X < Width * Channel; X++)
     {
         float ValueA = PtTopA[X] * InvertYY + PtBottomA[X] * PartYY;
         float ValueB = PtTopB[X] * InvertYY + PtBottomB[X] * PartYY;
         LinePD[X] = IM_ClampFHtoByte(ValueA * LinePS[X] + ValueB * 255);
     }
 }
 for (int Y = 0; Y < Height; Y++)
 {
     float PosY = Y * (SmallH - 1.0f) / Height;
     int YY = (int)PosY;
     float PartYY = PosY - YY;
     float InvertYY = 1 - PartYY;
     byte *LinePS = Guide + Y * Stride;
     byte *LinePD = Dest + Y * Stride;
     float *PtTopA = TempA + YY * Width * Channel;
     float *PtBottomA = PtTopA + Width * Channel;
     float *PtTopB = TempB + YY * Width * Channel;
     float *PtBottomB = PtTopB + Width * Channel;
     for (int X = 0;; X < Width * Channel; X++)
     {
         float ValueA = PtTopA[X] * InvertYY + PtBottomA[X] * PartYY;
         float ValueB = PtTopB[X] * InvertYY + PtBottomB[X] * PartYY;
         LinePD[X] = IM_ClampFHtoByte(ValueA * LinePS[X] + ValueB * 255);
     }
 }

  注意最后的IM_ClampFHtoByte函数是将括号内的价限制在0和255内的。

  注意最后的IM_ClampFHtoByte函数是将括号内之价限制在0和255中间的。

     
有不少爱人或者无掌握,如果管方的IM_ClampFHtoByte这个函数去丢,直接行使括号内之代码,VS的编译器可以老好的对准点代码进行向量化编译(VS编译只要你未曾把代码生成–》启用增强指令集设置成无增强指令/arch:IA32,哪怕设置为不安装,都见面拿浮点的代码编译为SIMD相关指令的),而要我们对两样之Channel,比如3通道4坦途在循环里展开后,很倒霉,按照我们的拓展循环的辩论,速度应该加紧,但实际也反了。所以我们用充分掌握编译器的朝量化特性,就能够写成又高速的代码。

     
有很多恋人或无明了,如果拿点的IM_ClampFHtoByte这个函数去丢,直接行使括号内的代码,VS的编译器可以老好的指向点代码进行向量化编译(VS编译只要您没把代码生成–》启用增强指令集设置成无增强指令/arch:IA32,哪怕设置为未设置,都见面拿浮点的代码编译为SIMD相关指令的),而而我们本着两样之Channel,比如3通道4坦途在循环里开展后,很不幸,按照我们的开展循环的申辩,速度相应加紧,但实际可反倒了。所以我们用充分掌握编译器的往量化特性,就能够写成又迅速之代码。

   
 由于在测算过程被确是一些结实大于了0跟255之范围,因此只要将IM_ClampFHtoByte函数去除,对有些图像会冒出噪点,因此,我们无可知一心依赖编译器的通往量化优化了,这就算不能不团结写SIMD指令,由于SIMD自带了饱和处理的连带函数,而上述内部的X
的for循环是蛮容易用SSE处理的,唯一用留意的即是得把LinePS对应之字节数据易为浮点数据,这里自己大概的提拔可以据此如下指令以8只字节数据易为8独浮点数:

   
 由于在计算过程中的确在有的结实大于了0暨255底限,因此要管IM_ClampFHtoByte函数去除,对小图像会油然而生噪点,因此,我们不可知一心依靠编译器的向量化优化了,这便不能不团结写SIMD指令,由于SIMD自带了饱和处理的相关函数,而上述内部的X
的for循环是殊爱用SSE处理的,唯一需要专注的就是急需将LinePS对应的字节数据易为浮点数据,这里我简单的唤醒可以为此如下指令以8个字节数据易为8单浮点数:

__m128i SrcI = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i const *)(LinePS + X)), Zero);        //    Load the lower 64 bits of the value pointed to by p into the lower 64 bits of the result, zeroing the upper 64 bits of the result.
__m128 SrcFL = _mm_cvtepi32_ps(_mm_unpacklo_epi16(SrcI, Zero));                                //    转换为浮点
__m128 SrcFH = _mm_cvtepi32_ps(_mm_unpackhi_epi16(SrcI, Zero));
__m128i SrcI = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i const *)(LinePS + X)), Zero);        //    Load the lower 64 bits of the value pointed to by p into the lower 64 bits of the result, zeroing the upper 64 bits of the result.
__m128 SrcFL = _mm_cvtepi32_ps(_mm_unpacklo_epi16(SrcI, Zero));                                //    转换为浮点
__m128 SrcFH = _mm_cvtepi32_ps(_mm_unpackhi_epi16(SrcI, Zero));

     
里面的浮点计算的过程的SSE代码就和普通的函数调用没什么可变卦,最后的抒写及LinePD这个字节数据的长河得用_mm_storel_epi64与有关活动搞定。

     
里面的浮点计算的长河的SSE代码就和一般的函数调用没什么可变化,最后的勾勒到LinePD这个字节数据的经过可就此_mm_storel_epi64跟关于活动搞定。

     
这里如此做的另外一个功利是以Y循环中计算是独立的,因此还好行使OPENMP加速。

     
这里如此做的另外一个补是在Y循环中计算是独立的,因此都好下OPENMP加速。

     
使用SSE优化能将上述过程提速2倍增以上。

     
使用SSE优化能拿上述过程提速2倍增以上。

     
另外一个问题,在地方的流程2的首先步着,对boxfilter的半径r也是进行了跟比例之紧缩的,注意到boxfilter的半径通常情况下我们都是故底整数,如果缩小后的r’也进行取整的口舌,举例来说,对于s
=4的情况下,半径为8、9、10、11即时四栽状态最后获的导向滤波结果就了同了,似乎马上不相符我们本着算法严谨性的要求,所以我们设支持一种浮点半径的boxfilter。

     
另外一个题目,在面的流程2的率先步着,对boxfilter的半径r也是进行了与比例之压缩的,注意到boxfilter的半径通常情况下我们且是故的平头,如果缩小后的r’也拓展取整的说话,举例来说,对于s
=4的情事下,半径为8、9、10、11当即四种状况最终收获的导向滤波结果虽了一致了,似乎就不抱我们对算法严谨性的求,所以我们只要支持一种植浮点半径的boxfilter。

   
 普通意义的boxfilter肯定是无能为力支撑浮点半径的(这不同让高斯歪曲),一种植变更之主意尽管是沾浮点半径前后的星星点点独整形半径值做模糊,然后再度线性插值,举个例子,如果下取样后的半径为4.4,则分级计算R1
= boxfilter(4)以及R2 = boxfilter(5),最后合成得到结果R:

   
 普通意义之boxfilter肯定是无力回天支撑浮点半径的(这不同让高斯歪曲),一种变更之法子尽管是获得浮点半径前后的简单独整形半径值做模糊,然后再度线性插值,举个例子,如果下取样后底半径为4.4,则分级计算R1
= boxfilter(4)以及R2 = boxfilter(5),最后合成得到结果R:

               R = R1 * (1 – 0.4) + R2
* 0.4;

               R = R1 * (1 – 0.4) + R2
* 0.4;

   
 如此处理后,在大多数气象下(除了下取样后底半径为整数,比如原本半径为12,s=4,这是r’=3),计算量又会稍为增加一些,需要计算小图的12赖boxfilter了,不过何必纠结者了吗。

   
 如此处理后,在大部情景下(除了下取样后的半径为整数,比如原半径为12,s=4,这是r’=3),计算量又见面聊增加某些,需要算小图的12涂鸦boxfilter了,不过何必纠结这个了吧。

   
 关于上述浮点版本的Boxfilter,其实还有平等种植更好的实现方式。我于13实行代码实现最快速最快速之积分图像算法受也供了扳平段子实现方框模糊的代码,当然十分代码还无是不过优秀的,因为中间的pixlecount需要每个像素都重新计算,其实当半径较小时中有些的像素的pixlecount为固定值,因此得以将边缘有的像素特殊处理,对于本例,是急需开展的浮点版本的算法,那对于中等有的
/ pixlecount操作就应当可以变成 *Invpixlecount,其中Invpixlecount =
1.0f/pixlecount,变除法为乘法,而且这有些算还可以好爱的之所以SSE实现。我测试了,改进后的实现同解析opencv中Box
Filter的兑现并提出更加快的方案(源码共享) 
这首文好章的快慢不相上下,但此出个优势就是是可以互相的。另外,最要紧之一点时常,当要计算上述浮点版半径版本的boxfilter时,积分图是休待再行重新计算的,而积分图的计所占据的耗时起码发生一半横。因此,这个场所下积分图版本的盒子滤波会再次起优势。

   
 关于上述浮点版本的Boxfilter,其实还有一样种更好之落实方式。我在13执行代码实现最高效最快捷的积分图像算法吃为提供了同等段子实现方框模糊的代码,当然非常代码还不是极端精彩的,因为里面的pixlecount需要每个像素都重新计算,其实当半径较小时中有的像素的pixlecount为固定值,因此可以将边缘有的像素特殊处理,对于本例,是索要展开的浮点版本的算法,那对中有些的
/ pixlecount操作就当好改为 *Invpixlecount,其中Invpixlecount =
1.0f/pixlecount,变除法为乘法,而且就有的计算还好很易之故SSE实现。我测试了,改进后底落实与解析opencv中Box
Filter的实现并提出进一步加速的方案(源码共享) 
这篇文好章的速不相上下,但此间发生只优势就是好并行的。另外,最重点的少数时不时,当要算上述浮点版半径版本的boxfilter时,积分图是不待再重复计算的,而积分图的盘算所占据的耗时起码发生一半横。因此,这个场所下积分图版本的盒子滤波会再次发出优势。

   
 在内存占用方面,也得举行大量之优化工作,哪怕是指向下取样图进行处理,第一,导向前必须把图像的字节数据归一化为0到1之内的浮点数据,很显眼,我们设下采样大小的归一化数据,那么这进程尽管应当怪自然之一直由原来大小图像投射到下取样的浮点数据,而毫不再次在中间转来转去, 这个下采样的内存占用大小为(W
* H )/(S * S) * channel * sizeof(float)
.第二,导向的中等的每过程用到了大气之中档变量,像原作者使用matlab的代码为了参数算法清楚,就是为每个中间数据分配内存,但是实际操作中,为省资源,必须加以优化,我们注意观察,就见面发觉有点变量用完就无见面更用了,当导向图和原图不同时,我总了独自需要4
* (W * H )/(S * S) * channel *
sizeof(float)大小的内存,如果导向图和原图相同,则只有待2 * (W * H )/(S
* S) * channel *
sizeof(float),这个数量或者含有下采样图的内存占用的吧。考虑以备值滤波里还得平等卖附加大小的内存,以及尾声混合时的为涨价的
2 * (H / S) * W * channel *
sizeof(float)的内存,当S=4时加起吧就是是原来图多一点点底内存。

   
 在内存占用方面,也得以开大量之优化工作,哪怕是对下取样图进行处理,第一,导向前必须将图像的字节数据归一化为0暨1中间的浮点数据,很肯定,我们如果下采样大小的归一化数据,那么这进程尽管相应怪当然的直接由老大小图像投射到下取样的浮点数据,而毫不还在中间转来转去, 这个下采样的内存占用大小也(W
* H )/(S * S) * channel * sizeof(float)
.第二,导向的中游的各个过程用到了大气之中变量,像原作者使用matlab的代码为了参数算法清楚,就是也每个中间数据分配内存,但是实际操作中,为节约资源,必须加以优化,我们注意观察,就会见发现有些变量用了就不见面再度用了,当导向图和原图不同时,我总了不过需要4
* (W * H )/(S * S) * channel *
sizeof(float)大小的内存,如果导向图和原图相同,则单纯待2 * (W * H )/(S
* S) * channel *
sizeof(float),这个数量或者含有下采样图的内存占用的也罢。考虑于都值滤波里还欲同客附加大小的内存,以及最终混合时的为涨价的
2 * (H / S) * W * channel *
sizeof(float)的内存,当S=4时加起也就是本图多一点点的内存。

   

   

   
 在同样尊I5的记录簿上,采用默认设置,以自我也导向图处理3000*2000的24各类图像需要横55ms,如果是灰度图大概是20ms,这个跟优化后的
boxblur速度基本一致,如果开启动多线程,比如开始两独线程,还会取速25%左右,再多吗不论帮助了。

   
 在平雅I5的记录簿及,采用默认设置,以己也导向图处理3000*2000的24位图像需要盖55ms,如果是灰度图大概是20ms,这个跟优化后底
boxblur速度基本一致,如果起启动多线程,比如开始两个线程,还会提速25%横,再多吗不论帮助了。

     

     

   
 共享下一个C#做的Demo,以便供应有趣味的冤家参考比较: http://files.cnblogs.com/files/Imageshop/SSE_Optimization_Demo.rar

   
 共享下一个C#开的Demo,以便供应有趣味之爱人参考比较: http://files.cnblogs.com/files/Imageshop/SSE_Optimization_Demo.rar

 

 

图片 11

图片 12

 

 

 

 

   
 本文纯属计流水账,未举行详细分析。

   
 本文纯属计流水账,未开详细分析。

图片 13

图片 14

 

 

 

 

     

     

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图