目录

一、基础理论

1、思想

2、原理

二、分水岭实战:硬币

步骤归纳

1、把原图像转二值图

2、开运算去噪

3、确定背景区域(膨胀)(得到背景/最大连通域)

4、确定前景区域(距离变换) (分离)(得到种子/前景)

5、找到未知区域(未知区域=背景-前景)

6、根据种子标记最大连通域

7、使用分水岭算法:合并种子和不确定区域、标记边界为-1

8、涂色并显示

总代码及效果(硬币)

三、分水岭实战:扑克牌

步骤归纳

1、锐化

2、开运算去噪

3、获取背景(全连通域)

3、确定前景区域(距离变换)(种子)

4、找未知区域(未知区域 = 确定的背景-确定的前景)

5、根据种子标记最大连通域

6、使用分水岭算法,合并不确定区域和种子,边界修改为-1

7、涂色并显示

总代码及效果(扑克牌)

四、分水岭实战:路面检测

1、 锐化

2、锐化之后再二值化

3、膨胀获取背景

4、距离变换获取前景

5、获取不确定区域(背景-前景)

6、显示标记情况

7、成功检测出路面的分水岭

总代码

参考资料


一、基础理论

1、思想

        防止同化。 

任何灰度图像都可以看作是一个地形表面,其中高强度表示山峰,低强度表示山谷。你开始用不同颜色的水(标签)填充每个孤立的山谷(局部最小值)。随着水位的上升,根据附近的山峰(坡度),来自不同山谷的水明显会开始合并颜色也不同为了避免这种情况,你要在水融合的地方建造屏障。你继续填满水,建造障碍,直到所有的山峰都在水下。然后你创建的屏障将返回你的分割结果。这就是Watershed背后的“思想”。你可以访问Watershed的CMM网页,了解它与一些动画的帮助。

但是这种方法会由于图像中的噪声或其他不规则性而产生过度分割的结果。因此OpenCV实现了一个基于标记的分水岭算法,你可以指定哪些是要合并的山谷点,哪些不是。这是一个交互式的图像分割

2、原理

我们所做的是:给我们知道的对象赋予不同的标签用一种颜色(或强度)标记我们确定为前景或对象的区域用另一种颜色标记我们确定为背景或非对象的区域最后用0标记我们不确定的区域,这是我们的标记。然后应用分水岭算法。然后我们的标记将使用我们给出的标签进行更新对象的边界值将为-1

靠近对象中心的区域是前景,而离对象中心很远的区域是背景,剩下的区域是不确定区域。

二、分水岭实战:硬币

首先看看原图:

步骤归纳

1、图像二值化 

2、开运算去噪

3、确定背景区域(膨胀)(得到背景/最大连通域)

4、确定前景区域(距离变换) (分离)(得到种子/前景)

5、找到未知区域(未知区域=背景-前景)

6、根据种子标记最大连通域

7、使用分水岭算法:合并种子和不确定区域、标记边界为-1

8、涂色并显示

1、把原图像转二值图

# 转二值图像
def ToBinary():global gray, binary# 灰度化gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)# 二值化ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)cv.imshow('binary', binary)

(为了方便后面的调用,这里把灰度图和二值图都设置为了global全局变量)

2、开运算去噪

开运算,去除噪声

# 1、开运算去噪opening = cv.morphologyEx(binary, cv.MORPH_OPEN, (3,3), iterations=2)cv.imshow('opening', opening)

3、确定背景区域(膨胀)(得到背景/最大连通域)

膨胀之后,对象扩大,背景减小,此时对象>原对象,此时背景 < 原背景,那么此时的背景自然可以确定为原背景的一部分。(离对象中心很远的是背景)

# 2、膨胀确定背景区域sure_bg = cv.dilate(opening, (3,3), iterations=3)cv.imshow('sure_bg', sure_bg)

4、确定前景区域(距离变换) (分离)(得到种子/前景)

原理:距离变换,在二值图中把对象缩小,得到的就是原图的一部分,可以确定为前景。类似于分离。(不分离的话,可以不用距离变换,只用腐蚀就够了)

为什么不能直接缩小?

直接缩小会让图片也跟着变化,我们要的只是把对象缩小,图片不变的。

distanceTransform函数计算非零像素到最近零像素点的最短距离。一般用于求解图像的骨骼(二值图)

def distanceTransform(src: Any,distanceType: Any,maskSize: Any,dst: Any = None,dstType: Any = None) -> None

distanceType :所用的求解距离的类型。

mask_size :距离变换掩模的大小,可以是 3 或 5。 对 CV_DIST_L1 或 CV_DIST_C 的情况,参数值被强制设定为 3, 因为 3×3 mask 给出 5×5 mask 一样的结果,而且速度还更快。

# 3、确定前景区域(距离变换)# 3-1、求对象最大宽度/长度(直径)dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 5)# 3-2、最长直径缩小一定程度,确定前景ret, sure_fg = cv.threshold(dist_transform, 0.7 * dist_transform.max(), 255, cv.THRESH_BINARY)#   前景          阈值函数                    阈值                        最大值 二值化方式sure_fg = np.uint8(sure_fg)cv.imshow('sure_fg', sure_fg)

sure_fg是种子 。(后面的标记需要根据种子获取标记

5、找到未知区域(未知区域=背景-前景)

未知区域 = 确定的背景 - 确定的前景 

# 4、找未知区域(未知区域 = 确定的背景-确定的前景)unknown = cv.subtract(sure_bg, sure_fg)cv.imshow('unknown', unknown)

6、根据种子标记最大连通域

根据种子标记最大连通域(大于1为内部区域,标记1为背景区域,0为未知区域)
# 5、根据种子标记最大连通域(大于1为内部区域,标记1为背景区域,0为未知区域)ret, markers = cv.connectedComponents(sure_fg)  #标记最大连通域markers = markers+1                             #最大连通域标记为1(背景)markers[unknown == 255] = 0                     #未知区域标记为0

 显示:连通域(背景)、不确定区域、种子(前景)

#显示各区域(连通域/背景、不确定区域、种子/前景)
def Show_Markers():mark = img.copy()mark[markers == 1] = (255, 0, 0)    #连通域/背景(蓝)mark[markers == 0] = (0, 255, 0)    #不确定区域(绿)mark[markers > 1] = (0, 0, 255)     #前景/种子(红)mark[markers == -1] = (0, 255, 0)   #边界(绿)cv.imshow('Markers', mark)

7、使用分水岭算法:合并种子和不确定区域、标记边界为-1

# 6、使用分水岭算法,边界修改为-1,边界涂红(-1)(分界:连通域背景 -- 未知区域+种子)markers = cv.watershed(img, markers)  # 分水岭算法(修改边界为-1)

8、涂色并显示

# 7、涂色并显示(边界(markers==-1)涂色)dst = img.copy()dst[markers == -1] = [0, 0, 255]                #边界(-1)涂色cv.imshow('dst', dst)

总代码及效果(硬币)

# 距离变换与分水岭算法
import numpy as np
import cv2 as cv# 转二值图像
def ToBinary():global gray, binary# 灰度化gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)# 二值化ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)cv.imshow('binary', binary)#显示各区域(连通域/背景、不确定区域、种子/前景)
def Show_Markers():mark = img.copy()mark[markers == 1] = (255, 0, 0)    #连通域/背景(蓝)mark[markers == 0] = (0, 255, 0)    #不确定区域(绿)mark[markers > 1] = (0, 0, 255)     #前景/种子(红)mark[markers == -1] = (0, 255, 0)   #边界(绿)cv.imshow('Markers', mark)# 分水岭找边界
def Watershed():global markers# 1、开运算去噪opening = cv.morphologyEx(binary, cv.MORPH_OPEN, (3,3), iterations=2)cv.imshow('opening', opening)# 2、确定背景区域(膨胀)sure_bg = cv.dilate(opening, (3,3), iterations=3)cv.imshow('sure_bg', sure_bg)# 3、确定前景区域(距离变换)(种子)# 3-1、求对象最大宽度/长度(直径)dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 5)# 3-2、最长直径按比例缩小,确定前景ret, sure_fg = cv.threshold(dist_transform, 0.7 * dist_transform.max(), 255, cv.THRESH_BINARY)#   前景          阈值函数                    阈值                        最大值 二值化方式sure_fg = np.uint8(sure_fg)cv.imshow('sure_fg', sure_fg)# 4、找未知区域(未知区域 = 确定的背景-确定的前景)unknown = cv.subtract(sure_bg, sure_fg)cv.imshow('unknown', unknown)# 5、根据种子标记最大连通域(大于1为内部区域,标记1为背景区域,0为未知区域)ret, markers = cv.connectedComponents(sure_fg)  #标记最大连通域markers = markers+1                             #背景标记为1(此为最大连通域)markers[unknown == 255] = 0                     #未知区域标记为0Show_Markers()          #显示各区域(连通域/背景、不确定区域、种子/前景)# 6、使用分水岭算法,合并不确定区域和种子,边界修改为-1,(分界:连通域背景 -- 未知区域+种子)markers = cv.watershed(img, markers)  # 分水岭算法(修改边界为-1)Show_Markers()          #显示各区域(连通域/背景、不确定区域、种子/前景)# 7、涂色并显示(边界(markers==-1)涂色)dst = img.copy()dst[markers == -1] = [0, 0, 255]                #边界(-1)涂色cv.imshow('dst', dst)if __name__ == '__main__':img = cv.imread('Resource/test19.jpg')cv.imshow('img', img)ToBinary()          #转二值图Watershed()         #分水岭找边界cv.waitKey(0)

三、分水岭实战:扑克牌

(这个是自实现,不那么规范)

原图:

步骤归纳

1、锐化

2、开运算去噪

3、获取背景(全连通域)

3、确定前景区域(距离变换)(种子)

4、找未知区域(未知区域 = 确定的背景-确定的前景)

5、根据种子标记最大连通域

6、使用分水岭算法,合并不确定区域和种子,边界修改为-1

7、涂色并显示

1、锐化

如果只是用硬币的代码,会出现这样的效果(只能分出外部的区域):

这里我们有必要在二值化前进行锐化

一开始使用的是卷积核:

kernel = np.array([[1, 1, 1],[1, -8, 1],[1, 1, 1]])

发现边缘还是不够明显,继续升级卷积核:

kernel = np.array([[2, 2, 2],[2, -16, 2],[2, 2, 2]])

现在可以看到,二值图像边缘已经比较清晰锐利了。

2、开运算去噪

# 1、开运算去噪opening = cv.morphologyEx(binary, cv.MORPH_OPEN, (3,3), iterations=2)cv.imshow('opening', opening)

3、获取背景(全连通域)

这里的扑克牌只是空架子,就不膨胀处理了,

# 2、确定背景区域(这里只是空架子,就不膨胀了)sure_bg = opening.copy()cv.imshow('sure_bg', sure_bg)

3、确定前景区域(距离变换)(种子)

# 3、确定前景区域(距离变换)(种子)# 3-1、求对象最大宽度/长度(直径)dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 3, 5)# 3-2、最长直径按比例缩小,确定前景ret, sure_fg = cv.threshold(dist_transform, 0.01 * dist_transform.max(), 255, cv.THRESH_BINARY)#   前景          阈值函数                    阈值                        最大值 二值化方式sure_fg = np.uint8(sure_fg)cv.imshow('sure_fg', sure_fg)

4、找未知区域(未知区域 = 确定的背景-确定的前景)

# 4、找未知区域(未知区域 = 确定的背景-确定的前景)unknown = cv.subtract(sure_bg, sure_fg)cv.imshow('unknown', unknown)

5、根据种子标记最大连通域

# 5、根据种子标记最大连通域(大于1为内部区域,标记1为背景区域,0为未知区域)ret, markers = cv.connectedComponents(sure_fg)  #标记最大连通域markers = markers+1                             #背景标记为1(此为最大连通域)markers[unknown == 255] = 0                     #未知区域标记为0Show_Markers()          #显示各区域(连通域/背景、不确定区域、种子/前景)

6、使用分水岭算法,合并不确定区域和种子,边界修改为-1

# 6、使用分水岭算法,合并不确定区域和种子,边界修改为-1(分界:连通域背景 -- 未知区域+种子)markers = cv.watershed(img, markers)  # 分水岭算法(修改边界为-1)Show_Markers()          #显示各区域(连通域/背景、不确定区域、种子/前景)

7、涂色并显示

# 7、涂色并显示(边界(markers==-1)涂色)dst = img.copy()dst[markers == -1] = [0, 255, 0]                #边界(-1)涂色cv.imshow('dst', dst)

总代码及效果(扑克牌)

# 距离变换与分水岭算法
import numpy as np
import cv2 as cv# 转二值图像
def ToBinary():global gray, binary# 1、锐化kernel = np.array([[2, 2, 2],[2, -16, 2],[2, 2, 2]])sharp = cv.filter2D(img, -1, kernel)cv.imshow('sharp', sharp)# 灰度化gray = cv.cvtColor(sharp, cv.COLOR_BGR2GRAY)cv.imshow('gray', gray)# 二值化ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)cv.imshow('binary', binary)#显示各区域(连通域/背景、不确定区域、种子/前景)
def Show_Markers():mark = img.copy()mark[markers == 1] = (255, 0, 0)    #连通域/背景(蓝)mark[markers == 0] = (0, 255, 0)    #不确定区域(绿)mark[markers > 1] = (0, 0, 255)     #前景/种子(红)mark[markers == -1] = (0, 255, 0)   #边界(绿)cv.imshow('Markers', mark)# 分水岭找边界
def Watershed():global markers# 1、开运算去噪opening = cv.morphologyEx(binary, cv.MORPH_OPEN, (3,3), iterations=2)cv.imshow('opening', opening)# 2、确定背景区域(这里只是空架子,就不膨胀了)sure_bg = opening.copy()cv.imshow('sure_bg', sure_bg)# 3、确定前景区域(距离变换)(种子)# 3-1、求对象最大宽度/长度(直径)dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 3, 5)# 3-2、最长直径按比例缩小,确定前景ret, sure_fg = cv.threshold(dist_transform, 0.01 * dist_transform.max(), 255, cv.THRESH_BINARY)#   前景          阈值函数                    阈值                        最大值 二值化方式sure_fg = np.uint8(sure_fg)cv.imshow('sure_fg', sure_fg)# 4、找未知区域(未知区域 = 确定的背景-确定的前景)unknown = cv.subtract(sure_bg, sure_fg)cv.imshow('unknown', unknown)# 5、根据种子标记最大连通域(大于1为内部区域,标记1为背景区域,0为未知区域)ret, markers = cv.connectedComponents(sure_fg)  #标记最大连通域markers = markers+1                             #背景标记为1(此为最大连通域)markers[unknown == 255] = 0                     #未知区域标记为0Show_Markers()          #显示各区域(连通域/背景、不确定区域、种子/前景)# 6、使用分水岭算法,合并不确定区域和种子,边界修改为-1(分界:连通域背景 -- 未知区域+种子)markers = cv.watershed(img, markers)  # 分水岭算法(修改边界为-1)Show_Markers()          #显示各区域(连通域/背景、不确定区域、种子/前景)# 7、涂色并显示(边界(markers==-1)涂色)dst = img.copy()dst[markers == -1] = [0, 255, 0]                #边界(-1)涂色cv.imshow('dst', dst)if __name__ == '__main__':img = cv.imread('Resource/test20.jpg')cv.imshow('img', img)ToBinary()          #转二值图Watershed()         #分水岭找边界cv.waitKey(0)

四、分水岭实战:路面检测

先锐化再进行处理,会适用于很多种情况。

这里和扑克牌的类似,都是边界不够明显,需要锐化处理的前面的扑克牌只有一个框架,没法膨胀,路面可以膨胀处理获取背景

原图:

1、 锐化

2、锐化之后再二值化

3、膨胀获取背景

和上面扑克牌不同的就是这里,这里的路面不是空架子,可以进行膨胀。

4、距离变换获取前景

5、获取不确定区域(背景-前景)

6、显示标记情况

7、成功检测出路面的分水岭

总代码

# 距离变换与分水岭算法(路面检测)
import numpy as np
import cv2 as cv# 转二值图像
def ToBinary():global gray, binary# 1、锐化kernel = np.array([[2, 2, 2],[2, -16, 2],[2, 2, 2]])sharp = cv.filter2D(img, -1, kernel)cv.imshow('sharp', sharp)# 灰度化gray = cv.cvtColor(sharp, cv.COLOR_BGR2GRAY)cv.imshow('gray', gray)# 二值化ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)cv.imshow('binary', binary)#显示各区域(连通域/背景、不确定区域、种子/前景)
def Show_Markers():mark = img.copy()mark[markers == 1] = (255, 0, 0)    #连通域/背景(蓝)mark[markers == 0] = (0, 255, 0)    #不确定区域(绿)mark[markers > 1] = (0, 0, 255)     #前景/种子(红)mark[markers == -1] = (0, 255, 0)   #边界(绿)cv.imshow('Markers', mark)# 分水岭找边界
def Watershed():global markers# 1、开运算去噪opening = cv.morphologyEx(binary, cv.MORPH_OPEN, (3,3), iterations=3)cv.imshow('opening', opening)# 2、确定背景区域(膨胀)sure_bg = cv.dilate(opening, (3,3), iterations=2)cv.imshow('sure_bg', sure_bg)# 3、确定前景区域(距离变换)(种子)# 3-1、求对象最大宽度/长度(直径)dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 3, 5)# 3-2、最长直径按比例缩小,确定前景ret, sure_fg = cv.threshold(dist_transform, 0.01 * dist_transform.max(), 255, cv.THRESH_BINARY)#   前景          阈值函数                    阈值                        最大值 二值化方式sure_fg = np.uint8(sure_fg)cv.imshow('sure_fg', sure_fg)# 4、找未知区域(未知区域 = 确定的背景-确定的前景)unknown = cv.subtract(sure_bg, sure_fg)cv.imshow('unknown', unknown)# 5、根据种子标记最大连通域(大于1为内部区域,标记1为背景区域,0为未知区域)ret, markers = cv.connectedComponents(sure_fg)  #标记最大连通域markers = markers+1                             #背景标记为1(此为最大连通域)markers[unknown == 255] = 0                     #未知区域标记为0Show_Markers()          #显示各区域(连通域/背景、不确定区域、种子/前景)# 6、使用分水岭算法,合并不确定区域和种子,边界修改为-1(分界:连通域背景 -- 未知区域+种子)markers = cv.watershed(img, markers)  # 分水岭算法(修改边界为-1)Show_Markers()          #显示各区域(连通域/背景、不确定区域、种子/前景)# 7、涂色并显示(边界(markers==-1)涂色)dst = img.copy()dst[markers == -1] = [0, 255, 0]                #边界(-1)涂色cv.imshow('dst', dst)if __name__ == '__main__':img = cv.imread('Resource/road.jpg')cv.imshow('img', img)ToBinary()          #转二值图Watershed()         #分水岭找边界cv.waitKey(0)

参考资料

http://woshicver.com/FifthSection/4_15_%E5%9B%BE%E5%83%8F%E5%88%86%E5%89%B2%E4%B8%8E%E5%88%86%E6%B0%B4%E5%B2%AD%E7%AE%97%E6%B3%95/

OpenCV(26)图像分割 -- 距离变换与分水岭算法(硬币检测、扑克牌检测、车道检测)相关推荐

  1. OpenCV3学习(7.2)——图像分割之二(分水岭算法watershed)

    分水岭算法原理 分水岭算法是一种图像区域分割法,在分割的过程中,它会把跟临近像素间的相似性作为重要的参考依据,从而将在空间位置上相近并且灰度值相近的像素点互相连接起来构成一个封闭的轮廓,封闭性是分水岭 ...

  2. 基于梯度方向、极化变换和聚类算法的图像主特征直线检测

    基于梯度方向.极化变换和聚类算法的图像主特征直线检测 基于机器学习和图像处理的直线检测 代码主要思路: 1)借助类LSD直线检测,提取图像各个方向梯度:2)对像素中的各个梯度方向做极化变换:3)对计划 ...

  3. opencv进阶学习笔记14:分水岭算法 实现图像分割

    基础版学习笔记目录: python3+opencv学习笔记汇总目录(适合基础入门学习) 进阶版笔记目录链接: python+opencv进阶版学习笔记目录(适合有一定基础) 分水岭算法原理 分水岭算法 ...

  4. OpenCV库中watershed函数(分水岭算法)的详细使用例程

    # 声明:如果有写的不对的地方欢迎指正! 一.分水岭算法 关于分水岭算法的具体原理我就不说了,网上搜一下很多.OpenCV中的watershed函数实现的分水岭算法是基于"标记"的 ...

  5. 单像素骨架提取算法c语言实现,【图像】骨架提取与分水岭算法

    1.骨架提取 骨架提取,也叫二值图像细化.这种算法能将一个连通区域细化成一个像素的宽度,用于特征提取和目标拓扑表示. morphology子模块提供了两个函数用于骨架提取,分别是Skeletonize ...

  6. OpenCV距离变换和分水岭算法的图像分割

    OpenCV距离变换和分水岭算法的图像分割 距离变换和分水岭算法的图像分割 目标 代码 说明/结果 距离变换和分水岭算法的图像分割 目标 在本教程中,您将学习如何: 使用OpenCV函数cv :: f ...

  7. 【OpenCV】数字图像的距离变换算法

    数字图像的距离变换算法 图像数字化 距离 距离变换 OpenCV代码实现 C++ Python 参考博客 图像数字化 通过传感器获得的图像是平面坐标(x,y)的连续函数f(x,y),它的值图像对应位置 ...

  8. OpenCV分水岭算法详解

    原理分析 分水岭算法主要用于图像分段,通常是把一副彩色图像灰度化,然后再求梯度图,最后在梯度图的基础上进行分水岭算法,求得分段图像的边缘线. 下面左边的灰度图,可以描述为右边的地形图,地形的高度是由灰 ...

  9. Python OpenCV分水岭算法分割和提取重叠或有衔接的图像中的对象

    本文将介绍如何使用分水岭算法对触摸和重叠的图像中的对象进行分割和提取. 参考:https://www.pyimagesearch.com/2015/11/02/watershed-opencv/ 分水 ...

最新文章

  1. 用友云平台,真正的云原生架构,加速云应用落地
  2. mysql没有err文件_xampp中的mysql启动时无法产生err文件
  3. c3p0数据源配置抛出Could not load driverClass com.mysql.jdbc.Driver的解决方案
  4. Kettle使用_24 Kettle输入输出组件汇总
  5. 垃圾代码还能出圈?手把手教你写垃圾代码,从入门到精通!
  6. 用于将类型从double转换为int的C#程序
  7. ASP.NET 2.0新特性视频教程下载
  8. Xiaomi Civi即将发布 雷军:宽度仅71.5mm 刚刚好的握持感
  9. window 下tomcat 内存设置,bat启动方式的
  10. 浅谈Spark中的宽依赖和窄依赖
  11. 源地址转换、目的地址装换
  12. 在java中重写方法应遵循规则的包括_蘑菇街2017校园招聘笔试题
  13. 整型到底占几个字节呢?
  14. BAT批处理脚本实例学习(五)局域网共享批处理安装软件
  15. 【马士兵】Python基础--01
  16. 37岁计算机博士博士后,应该说,这是我见过“最掏心”的人才招聘了:招博士、博士后!...
  17. 【工具】一款在线字数统计工具,统计单个字词组出现的频率
  18. 判断两条线段/直线相交,并求交点
  19. linux中vi修改文件内容,linux VI模式下批量修改文件内容
  20. 微信小说分销系统设计之使用百度Echarts地图统计功能统计微信粉丝地域分布情况...

热门文章

  1. Android 双屏开发 Presentation 的使用教程
  2. VM 下装ubuntu系统
  3. 获取DOM节点的几种方式
  4. Android程序员眼中世界上最遥远的距离
  5. C++中的explicitkeyword
  6. BaseTDI.sys 瑞星卡巴冲突,导致机器蓝屏
  7. 拒绝了我们的连接请求_职场上,我们该如何巧妙而优雅的拒绝同事忙的请求呢?...
  8. 3d stroke插件下载_推荐一款好用的PS 3D地图插件,PS插件3D Map Generator ,一键生成地图神器...
  9. java web 调用hadoop_Java及Web程序调用hadoop2.6
  10. html 关闭js控件,javascript – 用JS关闭html5视频控件