一、数据集缺点
1.数据集样本量少,总共只有117张样本图片,其中的缺陷样本图片数量更少。数据样本不足容易导致模型发生过拟合现象,泛化能力不强。
2.图片像素大小为512*512,计算量大。如果对图片大小进行压缩或者将图片转为灰度图片都可能导致有用特征信息的丢失。
二、数据预处理
针对以上缺点,最简单有效的方法是对数据集样本量进行扩充,一般采用几何变换的方式来增加训练集样本。常用的几何变换方法有旋转、缩放平移。
1.图片的旋转和缩放
用cv2.getRotationMatrix2D生成变换矩阵M,再用warpAffine对图片应用仿射变换。为了生成多张不同旋转方式的图片,可以设定旋转角度范围,和图像缩放范围,每次在范围内随机取值生成旋转后图片。代码如下(代码仅展示思路,不严谨)
#设置图像旋转参数
RotateOrign=(250,250) #表示旋转中心
RotateAngle=(60,90) #表示顺时针旋转60-90度
RotateScale=(0.8,1) #表示图片旋转后会缩放到原来的0.8-1倍
#定义旋转操作函数
def Rotate(image,rotateOrign,rotateAngle,rotateScale):
img=cv2.imread(image)
rows,cols=img.shape[:2]
M=cv2.getRotationMatrix2D(rotateOrign,rotateAngle,rotateScale) #变换矩阵M
dst=cv2.warpAffine(img,M,(rows,cols))
return dst
#生成图片
for item in imgList:
for num in range(generateImgNum): #generateImgNum:生成图片数量
RotateAngleTmp=random.uniform(RotateAngle[0],RotateAngle[1])
RotateScaleTmp=random.uniform(RotateScale[0],RotateScale[1])
outImg=Rotate(item,RotateOrign,RotateAngleTmp,RotateScaleTmp)
cv2.imwrite(path,outImg)
2.图片的平移
先定义平移矩阵M,再用warpAffine对图片应用仿射变换。
#图像平移参数
MoveX=(50,100) #向X方向移动多少像素单位
MoveY=(-50,50) #向Y方向移动多少像素单位
#定义平移操作函数
def Translate(image,moveX,moveY):
img=cv2.imread(image)
M=np.float32([[1,0,moveX],[0,1,moveY]])
dst=cv2.warpAffine(img,M,img.shape[:2])
return dst
#生成图片
for item in imgList:
for num in range(generateImgNum): #generateImgNum:生成图片数量
outImg=Translate(item,random.randint(MoveX[0],MoveX[1])
,random.randint(MoveY[0],MoveY[1]))
cv2.imwrite(path,outImg)
除了通过几何变换扩充数据集样本量之外,常见的数据预处理还有通过卷积操作从输入图像中提取特征。常见的卷积操作有高斯模糊和边缘检测。
3.高斯模糊
高斯模糊,也叫高斯平滑,通常用它来减少图片噪声以及降低细节层次(百度百科)
用cv2.GaussianBlur进行高斯模糊,其中高斯卷积核的尺寸必须是正数和奇数。
#高斯模糊参数
GaussianBlurkernelSize=5 #高斯卷积核的尺寸
GaussianBlurSigma=(0,2) #高斯核标准差范围
#定义高斯模糊函数
def GaussianBlur(image,kernelSize,sigma):
img=cv2.imread(image)
Gblur=cv2.GaussianBlur(img,(kernelSize,kernelSize),sigma)
return Gblur
#模糊图片
for item in imgList:
for num in range(generateImgNum): #generateImgNum:生成图片数量
GaussianBlurSigmaTmp=random.randint(GaussianBlurSigma[0],GaussianBlurSigma[1])
outImg=GaussianBlur(item,GaussianBlurkernelSize,GaussianBlurSigmaTmp)
cv2.imwrite(path,outImg)
4.边缘检测
边缘检测提取图片的边缘特征。Canny算法处理前后的图片(图片来自OpenCV文档):
边缘检测的几种常见算法:Sobel、Laplacian、Canny。
4.1 Sobel
依据:对像素点上下、左右邻点灰度加权差,在边缘处达到极值。先对x方向的梯度进行计算并取绝对值(有小于0的像素值),再对y方向的梯度进行计算并取绝对值,最后对图片混合加权。
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) #1,0表示计算方向为x
sobelx = cv2.convertScaleAbs(sobelx) #取绝对值
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3) #0,1表示计算方向为y
sobely = cv2.convertScaleAbs(sobely) #取绝对值
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0) #混合加权
4.2 Laplacian
依据:进行二阶导数计算,最大变化处的值为零即边缘是零值。直接用cv2.Laplacian进行边缘检测。
aplacian = cv2.Laplacian(img, cv2.CV_64F,ksize=3)
laplacian = cv2.convertScaleAbs(laplacian)
4.3 Canny
用cv2.Canny实现边缘检测。Canny算法中设置高阈值和低阈值,其中高阈值将要提取轮廓的物体与背景区分开来,低阈值用来平滑轮廓。
EdgeDetectionThreshold1=25 #低阈值
EdgeDetectionThreshold2=250 #高阈值
def EdgeDetection(image,threshold1,threshold2,):
img=cv2.imread(image)
edges=cv2.Canny(img,threshold1,threshold2)
return edges
for item in imgList:
outImg=EdgeDetection(item,EdgeDetectionThreshold1,EdgeDetectionThreshold2)
cv2.imwrite(path,outImg)
4.4 Canny算法的改进
参考文献:一种改进自适应阈值的Canny算法
OpenCV文档关于传统Canny算法的介绍:Canny Edge Detector
传统Canny算法的实现过程:
图像高斯滤波。平滑图像,消除噪声。
计算图像中每个像素点的梯度强度和方向。
应用非极大值抑制。删除不被视为边缘的一部分像素,只保留候选边缘。
应用双阈值检测来确定边缘。
Canny算法的改进:
采用双边滤波替代高斯滤波。 双边滤波的核函数是空间域核与像素范围域核的综合结果,同时考虑了空间域信息和灰度相似性,而高斯滤波只考虑了像素间的空间距离关系。双边过滤实现函数:cv2.bilateralFilter实现双边过滤,cv2.adaptiveBilateralFilter实现自适应双边滤。
采用最优阈值分割法求取高阈值,采用Otsu法确定低阈值。
————————————————
版权声明:本文为CSDN博主「伍六六」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_54000005/article/details/125410538