该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门、OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子、图像增强技术、图像分割等,后期结合深度学习研究图像识别、图像分类应用。希望文章对您有所帮助,如果有不足之处,还请海涵~
这篇文章将详细讲解利用数据增强方法实现图像数据集的扩充。通常,在某些情况下我们会缺失数据集或需要自主构建数据集,此时数据增强将发挥重要作用,本文以水书图像为例,通过五大类方法扩充数据集。本文以代码和方法为主,原理知识整个系列的众多文章已经介绍过。
希望对您有所帮助!让我们开始吧,且看且珍惜。
该系列在github所有源代码:
学Python近十年,认识了很多大佬和朋友,感恩。深知自己很菜,得拼命努力前行,编程也没有什么捷径,干就对了。希望未来能更透彻学习和撰写文章,同时非常感谢参考文献中的大佬们的文章和分享,共勉。 - https://blog.csdn.net/eastmount
水书是水族古文字及其著编典籍的汉译统称,是除纳西族东巴文以外世界上最后“活着”的象形文字,收集整理、研究解读水族文字对了解水族历史文化、研究少数民族原始宗教和文化信仰、从中窥探中国古文字奥秘有着重要意义。
由于水书是靠数量稀少的水书先生代代手抄传承,且记录水书的载体除纸张外还有大量刺绣、碑刻、木刻等其他原生载 体、金石载体,随着时代的发展,大量水书古籍文献和文字图像正在损毁和流失。另一方面,水书传承者的数量随着时间推移正在急剧减少,据统计,全国有近千名水书先生,但绝大部分已在60岁以上,大量散落民间的水书古籍无法被收集进行专业修复和妥善保存。传统水书收集整理和水族文字研究在人力、物力和技术上有一定的局限性,对大量散落民间的水书进行系统采集整理和文字提取识别难度巨大,无法满足信息化时代对濒危水族文字抢救提出的新要求。
当前,国内外学者开始高度重视对濒危水书的抢救工作,发掘、收集和整理了大批水书文献资料。这一时期,除了传统的对水书自身的研究和挖掘,学者们也开始思考水族文字抢救工作中存在的问题和困难,并不断探索解决方案,如罗春寒的《水书的抢救及存在问题浅议》、潘朝霖的《水文急剧消亡的原因探 析》、康蔼德和潘兴文的《水 语 调 查 研 究》等。随着计算机技术的发展和普及,水书研究进入信息化时代,运用计算机辅助水书输入、整理研究开始走入学术视野,如韦宗林的《水族古文字计算机输入法》、董芳的《水书文字规范标准建设与信息化的研究》、罗刚的《计 算 机 水 书 语 料库建设的探讨》、戴丹的《水书水字可视化输入中的模式 匹配》。经过各级部门和专家学者不遗余力的努力,目前国内水书的整理和研究已颇具成效。但传统的水族文字采集、整理和保护方式还存在以下几个方面的不足:
随着计算机视觉和图像处理技术的迅速发展,图像分割与图像识别方法已广泛应用于各行各业,比如车牌识别、人脸识别、身份证识等。图像分割是将图像分成若干具有独特性质的区域并提取感兴趣目标的技术,它是图像处理和图像分析的关键步骤。图像识别是通过算法和函数提取像素中的某些特征,并对图像进行识别和分类的过程。
为了更好地运用现代计算机图像处理和图像分割等技术来辅助濒危水族文字的抢救工作,保护水族文化,修复水书文物图像,本文提出了一种基于图像增强及区域检测的水族文字提取与分割算法。该研究具有重要的理论研究意义和良好的实际应用价值,可以广泛应用于水族文字提取、水族文字识别和水族文化传承领域。
作者构造了如下图的初始数据集,共计12个水族文字,您可以猜猜它们的含义。
PS:我写的水书看着还不错,丑萌丑萌的 O(∩_∩)O
初始数据集如下图所示,大家猜中了吗?
很显然,紧靠人工撰写无法完成水族文字识别任务。那怎么解决呢?
此外,在真实场景中,我们会遇到很多缺乏图像数据的情况,数据增强的方法非常适用且有效。因此,本文主要介绍数据增强扩充水书图像数据集的案例。
数据增强也叫数据扩增,意思是在不实质性的增加数据的情况下,让有限的数据产生等价于更多数据的价值。
常见方法如下:
图像几何变换不改变图像的像素值,在图像平面上进行像素变换。适当的几何变换可以最大程度地消除由于成像角度、透视关系乃至镜头自身原因所造成的几何失真所产生的负面影响。几何变换常常作为图像处理应用的预处理步骤,是图像归一化的核心工作之一。比如图像旋转原理如下:
原理参考作者前文:
该部分关键代码如下:
# -*- coding: utf-8 -*-
"""
2022-12-24
By: Eastmount CSDN xiuzhang
"""
import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
#-----------------------------------------------------------------------
#几何变换-镜像、翻转、旋转、缩放
def JH_Transformation(img,img_path):
rows, cols, channel = img.shape
#print(rows,cols,channel)
#镜像处理
jx = cv2.flip(img, 1)
#旋转30度 (旋转中心,旋转度数,scale)
M = cv2.getRotationMatrix2D((cols/2, rows/2), 30, 1)
rotated30 = cv2.warpAffine(img, M, (cols, rows), borderValue=(255,255,255))
#旋转45度 (旋转中心,旋转度数,scale)
M = cv2.getRotationMatrix2D((cols/2, rows/2), 45, 1)
rotated45 = cv2.warpAffine(img, M, (cols, rows), borderValue=(255,255,255))
#旋转90度 (旋转中心,旋转度数,scale)
M = cv2.getRotationMatrix2D((cols/2, rows/2), 90, 1)
rotated90 = cv2.warpAffine(img, M, (cols, rows), borderValue=(255,255,255))
#旋转330度 (旋转中心,旋转度数,scale)
M = cv2.getRotationMatrix2D((cols/2, rows/2), 330, 1)
rotated330 = cv2.warpAffine(img, M, (cols, rows), borderValue=(255,255,255))
#旋转180度
M = cv2.getRotationMatrix2D((cols/2, rows/2), 180, 1)
rotated180 = cv2.warpAffine(img, M, (cols, rows), borderValue=(255,255,255))
#缩小
sx = cv2.resize(img, (int(cols*0.8), int(rows*0.8)))
#放大
fd = cv2.resize(img, (int(cols*1.2), int(rows*1.2)))
#显示图像
titles = ['Source', 'JX', 'XZ30', 'XZ45', 'XZ90', 'XZ330', 'XZ180', 'SX', 'FD']
images = [img, jx, rotated30, rotated45, rotated90, rotated330, rotated180, sx, fd]
for i in range(9):
plt.subplot(3,3,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
#保存图像
cv2.imwrite(img_path[0:-4] + '_jx.png', jx)
cv2.imwrite(img_path[0:-4] + '_rotated30.png', rotated30)
cv2.imwrite(img_path[0:-4] + '_rotated45.png', rotated45)
cv2.imwrite(img_path[0:-4] + '_rotated90.png', rotated90)
cv2.imwrite(img_path[0:-4] + '_rotated330.png', rotated330)
cv2.imwrite(img_path[0:-4] + '_rotated180.png', rotated180)
cv2.imwrite(img_path[0:-4] + '_sx.png', sx)
cv2.imwrite(img_path[0:-4] + '_fd.png', fd)
#-----------------------------------------------------------------------
#读取指定文件夹下的所有图像
def main():
file_path = "data"
for img_name in os.listdir(file_path):
img_path = file_path + "\\" + img_name
res_path = "data_add" + "\\" + img_name
img = cv2.imread(img_path)
#1.几何变换-镜像、翻转、旋转、缩放
JH_Transformation(img,res_path)
if __name__ == "__main__":
main()
输出结果如下图所示:
图像亮度变换类似于图像加法或减法运算。第一种是调用Numpy库实现,目标图像像素为两张图像的像素之和;第二种是通过OpenCV调用add()函数实现。第二种方法的函数原型如下:
注意,当两幅图像的像素值相加结果小于等于255时,则输出图像直接赋值该结果,如120+48赋值为168;如果相加值大于255,则输出图像的像素结果设置为255,如(255+64) 赋值为255。原理参考作者前文:
该部分关键代码如下:
#-----------------------------------------------------------------------
#亮度变换-增强、减弱
def Brighter_Transformation(img, percetage):
img_copy = img.copy()
w = img.shape[1]
h = img.shape[0]
for xi in range(0, w):
for xj in range(0, h):
img_copy[xj, xi, 0] = np.clip(int(img[xj, xi, 0] * percetage), a_max=255, a_min=0)
img_copy[xj, xi, 1] = np.clip(int(img[xj, xi, 1] * percetage), a_max=255, a_min=0)
img_copy[xj, xi, 2] = np.clip(int(img[xj, xi, 2] * percetage), a_max=255, a_min=0)
return img_copy
def Darker_Transformation(img, percetage):
img_copy = img.copy()
w = img.shape[1]
h = img.shape[0]
for xi in range(0, w):
for xj in range(0, h):
img_copy[xj, xi, 0] = int(img[xj, xi, 0] * percetage)
img_copy[xj, xi, 1] = int(img[xj, xi, 1] * percetage)
img_copy[xj, xi, 2] = int(img[xj, xi, 2] * percetage)
return img_copy
def LD_Transformation(img,img_path):
rows, cols, channel = img.shape
#增强1.1、1.5、2.0、2.5、3.0
zq_11 = Brighter_Transformation(img,1.1)
zq_15 = Brighter_Transformation(img,1.5)
zq_20 = Brighter_Transformation(img,2.0)
zq_25 = Brighter_Transformation(img,2.5)
zq_30 = Brighter_Transformation(img,3.0)
#减弱0.9、0.8、0.5
jr_09 = Darker_Transformation(img,0.9)
jr_08 = Darker_Transformation(img,0.8)
jr_07 = Darker_Transformation(img,0.7)
#显示图像
titles = ['Source', 'ZQ1.1', 'ZQ1.5', 'ZQ2.0', 'ZQ2.5', 'ZQ3.0', 'JR0.9', 'JR0.8', 'JR0.7']
images = [img, zq_11, zq_15, zq_20, zq_25, zq_30, jr_09, jr_08, jr_07]
for i in range(9):
plt.subplot(3,3,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
#保存图像
cv2.imwrite(img_path[0:-4] + '_zq_11.png', zq_11)
cv2.imwrite(img_path[0:-4] + '_zq_15.png', zq_15)
cv2.imwrite(img_path[0:-4] + '_zq_20.png', zq_20)
cv2.imwrite(img_path[0:-4] + '_zq_25.png', zq_25)
cv2.imwrite(img_path[0:-4] + '_zq_30.png', zq_30)
cv2.imwrite(img_path[0:-4] + '_jr_09.png', jr_09)
cv2.imwrite(img_path[0:-4] + '_jr_08.png', jr_08)
cv2.imwrite(img_path[0:-4] + '_jr_07.png', jr_07)
输出结果如下图所示:
该部分关键代码如下:
#-----------------------------------------------------------------------
#颜色通道变换
def Channel_Transformation(img,img_path):
rows, cols, channel = img.shape
img = Brighter_Transformation(img,1.5) #边缘增强
color_map = [
cv2.COLORMAP_AUTUMN,
cv2.COLORMAP_BONE,
cv2.COLORMAP_JET,
cv2.COLORMAP_WINTER,
cv2.COLORMAP_PARULA,
cv2.COLORMAP_OCEAN,
cv2.COLORMAP_SUMMER,
cv2.COLORMAP_SPRING,
cv2.COLORMAP_COOL,
cv2.COLORMAP_PINK,
cv2.COLORMAP_HOT,
cv2.COLORMAP_PARULA,
cv2.COLORMAP_MAGMA,
cv2.COLORMAP_INFERNO,
cv2.COLORMAP_PLASMA,
cv2.COLORMAP_TWILIGHT,
cv2.COLORMAP_TWILIGHT_SHIFTED
]
rgb_img_01 = cv2.applyColorMap(img, color_map[0])
rgb_img_02 = cv2.applyColorMap(img, color_map[1])
rgb_img_03 = cv2.applyColorMap(img, color_map[9])
rgb_img_04 = cv2.applyColorMap(img, color_map[3])
rgb_img_05 = cv2.applyColorMap(img, color_map[13])
rgb_img_06 = cv2.applyColorMap(img, color_map[5])
rgb_img_07 = cv2.applyColorMap(img, color_map[12])
rgb_img_08 = cv2.applyColorMap(img, color_map[10])
# 通道分离
b = cv2.split(img)[0]
g = np.zeros((rows,cols), dtype=img.dtype)
r = np.zeros((rows,cols), dtype=img.dtype)
mb = cv2.merge([b, g, r])
g = cv2.split(img)[1]
b = np.zeros((rows,cols), dtype=img.dtype)
r = np.zeros((rows,cols), dtype=img.dtype)
mg = cv2.merge([b, g, r])
r = cv2.split(img)[2]
b = np.zeros((rows,cols), dtype=img.dtype)
g = np.zeros((rows,cols), dtype=img.dtype)
mr = cv2.merge([b, g, r])
#显示图像
titles = ['Source', 'RGB-1', 'RGB-2', 'RGB-3', 'RGB-4',
'RGB-5', 'RGB-6', 'RGB-7', 'RGB-8', 'B', 'G', 'R']
images = [img, rgb_img_01, rgb_img_02, rgb_img_03, rgb_img_04,
rgb_img_05, rgb_img_06, rgb_img_07, rgb_img_08, mb, mg, mr]
for i in range(12):
plt.subplot(4,3,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
#保存图像
cv2.imwrite(img_path[0:-4] + '_rgb_img_01.png', rgb_img_01)
cv2.imwrite(img_path[0:-4] + '_rgb_img_02.png', rgb_img_02)
cv2.imwrite(img_path[0:-4] + '_rgb_img_03.png', rgb_img_03)
cv2.imwrite(img_path[0:-4] + '_rgb_img_04.png', rgb_img_04)
cv2.imwrite(img_path[0:-4] + '_rgb_img_05.png', rgb_img_05)
cv2.imwrite(img_path[0:-4] + '_rgb_img_06.png', rgb_img_06)
cv2.imwrite(img_path[0:-4] + '_rgb_img_07.png', rgb_img_07)
cv2.imwrite(img_path[0:-4] + '_rgb_img_08.png', rgb_img_08)
cv2.imwrite(img_path[0:-4] + '_mb.png', mb)
cv2.imwrite(img_path[0:-4] + '_mg.png', mg)
cv2.imwrite(img_path[0:-4] + '_mr.png', mr)
输出结果如下图所示:
该部分关键代码如下:
#-----------------------------------------------------------------------
#添加高斯噪声和椒盐噪声
def GaussianNoise(img, percetage):
gn = img.copy()
w = img.shape[1]
h = img.shape[0]
G_NoiseNum = int(percetage * img.shape[0] * img.shape[1])
for i in range(G_NoiseNum):
lx = np.random.randint(0, h)
ly = np.random.randint(0, w)
gn[lx][ly][np.random.randint(3)] = np.random.randn(1)[0]
return gn
def SaltNoise(img, percetage):
sn = img.copy()
SP_NoiseNum = int(percetage * img.shape[0] * img.shape[1])
for i in range(SP_NoiseNum):
randR = np.random.randint(0, img.shape[0] - 1)
randG = np.random.randint(0, img.shape[1] - 1)
randB = np.random.randint(0, 3)
if np.random.randint(0, 1) == 0:
sn[randR, randG, randB] = 0
else:
sn[randR, randG, randB] = 255
return sn
def Gaussian_Salt_Noise(img,res_path):
rows, cols, channel = img.shape
img = Brighter_Transformation(img,1.5) #边缘增强
#高斯噪声
gn_005 = GaussianNoise(img, 0.05)
gn_010 = GaussianNoise(img, 0.10)
gn_015 = GaussianNoise(img, 0.15)
gn_020 = GaussianNoise(img, 0.20)
#椒盐噪声
sn_005 = SaltNoise(img, 0.05)
sn_010 = SaltNoise(img, 0.10)
sn_015 = SaltNoise(img, 0.15)
sn_020 = SaltNoise(img, 0.20)
#显示图像
titles = ['Source', 'Gaussian-0.05', 'Gaussian-0.10', 'Gaussian-0.15', 'Gaussian-0.20',
'Salt-0.05', 'Salt-0.10', 'Salt-0.15', 'Salt-0.20']
images = [img, gn_005, gn_010, gn_015, gn_020, sn_005, sn_010, sn_015, sn_020]
for i in range(9):
plt.subplot(3,3,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
#保存图像
cv2.imwrite(img_path[0:-4] + '_gn_005.png', gn_005)
cv2.imwrite(img_path[0:-4] + '_gn_010.png', gn_010)
cv2.imwrite(img_path[0:-4] + '_gn_015.png', gn_015)
cv2.imwrite(img_path[0:-4] + '_gn_020.png', gn_020)
cv2.imwrite(img_path[0:-4] + '_sn_005.png', sn_005)
cv2.imwrite(img_path[0:-4] + '_sn_010.png', sn_010)
cv2.imwrite(img_path[0:-4] + '_sn_015.png', sn_015)
cv2.imwrite(img_path[0:-4] + '_sn_020.png', sn_020)
输出结果如下图所示:
该部分关键代码如下:
#-----------------------------------------------------------------------
#模拟怀旧和噪声添加
def Salt(img, num):
wn = img.copy()
rows, cols, chn = wn.shape
for i in range(num):
x = np.random.randint(0, rows)
y = np.random.randint(0, cols)
wn[x,y,:] = 210
return wn
def Fog_Noise(img, percetage):
mask_img = img.copy()
mask_img[:, :] = (166, 178, 180) #雾的颜色 (146,182,213)
#调整雾的浓度 round(random.uniform(0.03, 0.28), 2)
res = cv2.addWeighted(img, percetage, mask_img, 1-percetage, 0)
return res
def Fog_Salt_Noise(img,img_path):
rows, cols, channel = img.shape
img = Brighter_Transformation(img,1.5) #边缘增强
#白点噪声
wn_100 = Salt(img, 100)
wn_150 = Salt(img, 150)
wn_200 = Salt(img, 200)
wn_250 = Salt(img, 250)
#模拟怀旧
fog_06 = Fog_Noise(img, 0.6)
fog_07 = Fog_Noise(img, 0.7)
fog_08 = Fog_Noise(img, 0.8)
fog_09 = Fog_Noise(img, 0.9)
#显示图像
titles = ['Source', 'wn-100', 'wn-150', 'wn-200', 'wn-250',
'fog_06', 'fog_07', 'fog_08', 'fog_09']
images = [img, wn_100, wn_150, wn_200, wn_250,
fog_06, fog_07, fog_08, fog_09]
for i in range(9):
plt.subplot(3,3 ,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
#保存图像
cv2.imwrite(img_path[0:-4] + '_wn_100.png', wn_100)
cv2.imwrite(img_path[0:-4] + '_wn_150.png', wn_150)
cv2.imwrite(img_path[0:-4] + '_wn_200.png', wn_200)
cv2.imwrite(img_path[0:-4] + '_wn_250.png', wn_250)
cv2.imwrite(img_path[0:-4] + '_fog_06.png', fog_06)
cv2.imwrite(img_path[0:-4] + '_fog_07.png', fog_07)
cv2.imwrite(img_path[0:-4] + '_fog_08.png', fog_08)
cv2.imwrite(img_path[0:-4] + '_fog_09.png', fog_09)
输出结果如下图所示:
本文的最终代码如下所示,通过定义函数实现了五大类别的数据增强。希望对您有所帮助。
# -*- coding: utf-8 -*-
"""
2022-12-24
By: Eastmount CSDN xiuzhang
"""
import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
import random
#-----------------------------------------------------------------------
#几何变换-镜像、翻转、旋转、缩放
def JH_Transformation(img,img_path):
rows, cols, channel = img.shape
#print(rows,cols,channel)
#镜像处理
jx = cv2.flip(img, 1)
#旋转30度 (旋转中心,旋转度数,scale)
M = cv2.getRotationMatrix2D((cols/2, rows/2), 30, 1)
rotated30 = cv2.warpAffine(img, M, (cols, rows), borderValue=(255,255,255))
#旋转45度 (旋转中心,旋转度数,scale)
M = cv2.getRotationMatrix2D((cols/2, rows/2), 45, 1)
rotated45 = cv2.warpAffine(img, M, (cols, rows), borderValue=(255,255,255))
#旋转90度 (旋转中心,旋转度数,scale)
M = cv2.getRotationMatrix2D((cols/2, rows/2), 90, 1)
rotated90 = cv2.warpAffine(img, M, (cols, rows), borderValue=(255,255,255))
#旋转330度 (旋转中心,旋转度数,scale)
M = cv2.getRotationMatrix2D((cols/2, rows/2), 330, 1)
rotated330 = cv2.warpAffine(img, M, (cols, rows), borderValue=(255,255,255))
#旋转180度
M = cv2.getRotationMatrix2D((cols/2, rows/2), 180, 1)
rotated180 = cv2.warpAffine(img, M, (cols, rows), borderValue=(255,255,255))
#缩小
sx = cv2.resize(img, (int(cols*0.8), int(rows*0.8)))
#放大
fd = cv2.resize(img, (int(cols*1.2), int(rows*1.2)))
"""
#显示图像
titles = ['Source', 'JX', 'XZ30', 'XZ45', 'XZ90', 'XZ330', 'XZ180', 'SX', 'FD']
images = [img, jx, rotated30, rotated45, rotated90, rotated330, rotated180, sx, fd]
for i in range(9):
plt.subplot(3,3,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
"""
#保存图像
cv2.imwrite(img_path[0:-4] + '_jx.png', jx)
cv2.imwrite(img_path[0:-4] + '_rotated30.png', rotated30)
cv2.imwrite(img_path[0:-4] + '_rotated45.png', rotated45)
cv2.imwrite(img_path[0:-4] + '_rotated90.png', rotated90)
cv2.imwrite(img_path[0:-4] + '_rotated330.png', rotated330)
cv2.imwrite(img_path[0:-4] + '_rotated180.png', rotated180)
cv2.imwrite(img_path[0:-4] + '_sx.png', sx)
cv2.imwrite(img_path[0:-4] + '_fd.png', fd)
#-----------------------------------------------------------------------
#亮度变换-增强、减弱
def Brighter_Transformation(img, percetage):
img_copy = img.copy()
w = img.shape[1]
h = img.shape[0]
for xi in range(0, w):
for xj in range(0, h):
img_copy[xj, xi, 0] = np.clip(int(img[xj, xi, 0] * percetage), a_max=255, a_min=0)
img_copy[xj, xi, 1] = np.clip(int(img[xj, xi, 1] * percetage), a_max=255, a_min=0)
img_copy[xj, xi, 2] = np.clip(int(img[xj, xi, 2] * percetage), a_max=255, a_min=0)
return img_copy
def Darker_Transformation(img, percetage):
img_copy = img.copy()
w = img.shape[1]
h = img.shape[0]
for xi in range(0, w):
for xj in range(0, h):
img_copy[xj, xi, 0] = int(img[xj, xi, 0] * percetage)
img_copy[xj, xi, 1] = int(img[xj, xi, 1] * percetage)
img_copy[xj, xi, 2] = int(img[xj, xi, 2] * percetage)
return img_copy
def LD_Transformation(img,img_path):
rows, cols, channel = img.shape
#增强1.1、1.5、2.0、2.5、3.0
zq_11 = Brighter_Transformation(img,1.1)
zq_15 = Brighter_Transformation(img,1.5)
zq_18 = Brighter_Transformation(img,1.8)
zq_20 = Brighter_Transformation(img,2.0)
zq_25 = Brighter_Transformation(img,2.5)
#减弱0.9、0.8、0.5
jr_09 = Darker_Transformation(img,0.9)
jr_08 = Darker_Transformation(img,0.8)
jr_07 = Darker_Transformation(img,0.7)
"""
#显示图像
titles = ['Source', 'ZQ1.1', 'ZQ1.5', 'ZQ1.8', 'ZQ2.0', 'ZQ2.5', 'JR0.9', 'JR0.8', 'JR0.7']
images = [img, zq_11, zq_15, zq_18, zq_20, zq_25, jr_09, jr_08, jr_07]
for i in range(9):
plt.subplot(3,3,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
"""
#保存图像
cv2.imwrite(img_path[0:-4] + '_zq_11.png', zq_11)
cv2.imwrite(img_path[0:-4] + '_zq_15.png', zq_15)
cv2.imwrite(img_path[0:-4] + '_zq_18.png', zq_18)
cv2.imwrite(img_path[0:-4] + '_zq_20.png', zq_20)
cv2.imwrite(img_path[0:-4] + '_zq_25.png', zq_25)
cv2.imwrite(img_path[0:-4] + '_jr_09.png', jr_09)
cv2.imwrite(img_path[0:-4] + '_jr_08.png', jr_08)
cv2.imwrite(img_path[0:-4] + '_jr_07.png', jr_07)
#-----------------------------------------------------------------------
#颜色通道变换
def Channel_Transformation(img,img_path):
rows, cols, channel = img.shape
img = Brighter_Transformation(img,1.5) #边缘增强
color_map = [
cv2.COLORMAP_AUTUMN,
cv2.COLORMAP_BONE,
cv2.COLORMAP_JET,
cv2.COLORMAP_WINTER,
cv2.COLORMAP_PARULA,
cv2.COLORMAP_OCEAN,
cv2.COLORMAP_SUMMER,
cv2.COLORMAP_SPRING,
cv2.COLORMAP_COOL,
cv2.COLORMAP_PINK,
cv2.COLORMAP_HOT,
cv2.COLORMAP_PARULA,
cv2.COLORMAP_MAGMA,
cv2.COLORMAP_INFERNO,
cv2.COLORMAP_PLASMA,
cv2.COLORMAP_TWILIGHT,
cv2.COLORMAP_TWILIGHT_SHIFTED
]
rgb_img_01 = cv2.applyColorMap(img, color_map[0])
rgb_img_02 = cv2.applyColorMap(img, color_map[1])
rgb_img_03 = cv2.applyColorMap(img, color_map[9])
rgb_img_04 = cv2.applyColorMap(img, color_map[3])
rgb_img_05 = cv2.applyColorMap(img, color_map[13])
rgb_img_06 = cv2.applyColorMap(img, color_map[5])
rgb_img_07 = cv2.applyColorMap(img, color_map[12])
rgb_img_08 = cv2.applyColorMap(img, color_map[10])
# 通道分离
b = cv2.split(img)[0]
g = np.zeros((rows,cols), dtype=img.dtype)
r = np.zeros((rows,cols), dtype=img.dtype)
mb = cv2.merge([b, g, r])
g = cv2.split(img)[1]
b = np.zeros((rows,cols), dtype=img.dtype)
r = np.zeros((rows,cols), dtype=img.dtype)
mg = cv2.merge([b, g, r])
r = cv2.split(img)[2]
b = np.zeros((rows,cols), dtype=img.dtype)
g = np.zeros((rows,cols), dtype=img.dtype)
mr = cv2.merge([b, g, r])
"""
#显示图像
titles = ['Source', 'RGB-1', 'RGB-2', 'RGB-3', 'RGB-4',
'RGB-5', 'RGB-6', 'RGB-7', 'RGB-8', 'B', 'G', 'R']
images = [img, rgb_img_01, rgb_img_02, rgb_img_03, rgb_img_04,
rgb_img_05, rgb_img_06, rgb_img_07, rgb_img_08, mb, mg, mr]
for i in range(12):
plt.subplot(4,3,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
"""
#保存图像
cv2.imwrite(img_path[0:-4] + '_rgb_img_01.png', rgb_img_01)
cv2.imwrite(img_path[0:-4] + '_rgb_img_02.png', rgb_img_02)
cv2.imwrite(img_path[0:-4] + '_rgb_img_03.png', rgb_img_03)
cv2.imwrite(img_path[0:-4] + '_rgb_img_04.png', rgb_img_04)
cv2.imwrite(img_path[0:-4] + '_rgb_img_05.png', rgb_img_05)
cv2.imwrite(img_path[0:-4] + '_rgb_img_06.png', rgb_img_06)
cv2.imwrite(img_path[0:-4] + '_rgb_img_07.png', rgb_img_07)
cv2.imwrite(img_path[0:-4] + '_rgb_img_08.png', rgb_img_08)
cv2.imwrite(img_path[0:-4] + '_mb.png', mb)
cv2.imwrite(img_path[0:-4] + '_mg.png', mg)
cv2.imwrite(img_path[0:-4] + '_mr.png', mr)
#-----------------------------------------------------------------------
#添加高斯噪声和椒盐噪声
def GaussianNoise(img, percetage):
gn = img.copy()
w = img.shape[1]
h = img.shape[0]
G_NoiseNum = int(percetage * img.shape[0] * img.shape[1])
for i in range(G_NoiseNum):
lx = np.random.randint(0, h)
ly = np.random.randint(0, w)
gn[lx][ly][np.random.randint(3)] = np.random.randn(1)[0]
return gn
def SaltNoise(img, percetage):
sn = img.copy()
SP_NoiseNum = int(percetage * img.shape[0] * img.shape[1])
for i in range(SP_NoiseNum):
randR = np.random.randint(0, img.shape[0] - 1)
randG = np.random.randint(0, img.shape[1] - 1)
randB = np.random.randint(0, 3)
if np.random.randint(0, 1) == 0:
sn[randR, randG, randB] = 0
else:
sn[randR, randG, randB] = 255
return sn
def Gaussian_Salt_Noise(img,img_path):
rows, cols, channel = img.shape
img = Brighter_Transformation(img,1.5) #边缘增强
#高斯噪声
gn_005 = GaussianNoise(img, 0.05)
gn_010 = GaussianNoise(img, 0.10)
gn_015 = GaussianNoise(img, 0.15)
gn_020 = GaussianNoise(img, 0.20)
#椒盐噪声
sn_005 = SaltNoise(img, 0.05)
sn_010 = SaltNoise(img, 0.10)
sn_015 = SaltNoise(img, 0.15)
sn_020 = SaltNoise(img, 0.20)
"""
#显示图像
titles = ['Source', 'Gaussian-0.05', 'Gaussian-0.10', 'Gaussian-0.15', 'Gaussian-0.20',
'Salt-0.05', 'Salt-0.10', 'Salt-0.15', 'Salt-0.20']
images = [img, gn_005, gn_010, gn_015, gn_020, sn_005, sn_010, sn_015, sn_020]
for i in range(9):
plt.subplot(3,3,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
"""
#保存图像
cv2.imwrite(img_path[0:-4] + '_gn_005.png', gn_005)
cv2.imwrite(img_path[0:-4] + '_gn_010.png', gn_010)
cv2.imwrite(img_path[0:-4] + '_gn_015.png', gn_015)
cv2.imwrite(img_path[0:-4] + '_gn_020.png', gn_020)
cv2.imwrite(img_path[0:-4] + '_sn_005.png', sn_005)
cv2.imwrite(img_path[0:-4] + '_sn_010.png', sn_010)
cv2.imwrite(img_path[0:-4] + '_sn_015.png', sn_015)
cv2.imwrite(img_path[0:-4] + '_sn_020.png', sn_020)
#-----------------------------------------------------------------------
#模拟怀旧和噪声添加
def Salt(img, num):
wn = img.copy()
rows, cols, chn = wn.shape
for i in range(num):
x = np.random.randint(0, rows)
y = np.random.randint(0, cols)
wn[x,y,:] = 210
return wn
def Fog_Noise(img, percetage):
mask_img = img.copy()
mask_img[:, :] = (166, 178, 180) #雾的颜色 (146,182,213)
#调整雾的浓度 round(random.uniform(0.03, 0.28), 2)
res = cv2.addWeighted(img, percetage, mask_img, 1-percetage, 0)
return res
def Fog_Salt_Noise(img,img_path):
rows, cols, channel = img.shape
img = Brighter_Transformation(img,1.5) #边缘增强
#白点噪声
wn_100 = Salt(img, 100)
wn_150 = Salt(img, 150)
wn_200 = Salt(img, 200)
wn_250 = Salt(img, 250)
#模拟怀旧
fog_06 = Fog_Noise(img, 0.6)
fog_07 = Fog_Noise(img, 0.7)
fog_08 = Fog_Noise(img, 0.8)
fog_09 = Fog_Noise(img, 0.9)
"""
#显示图像
titles = ['Source', 'wn-100', 'wn-150', 'wn-200', 'wn-250',
'fog_06', 'fog_07', 'fog_08', 'fog_09']
images = [img, wn_100, wn_150, wn_200, wn_250,
fog_06, fog_07, fog_08, fog_09]
for i in range(9):
plt.subplot(3,3 ,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
"""
#保存图像
cv2.imwrite(img_path[0:-4] + '_wn_100.png', wn_100)
cv2.imwrite(img_path[0:-4] + '_wn_150.png', wn_150)
cv2.imwrite(img_path[0:-4] + '_wn_200.png', wn_200)
cv2.imwrite(img_path[0:-4] + '_wn_250.png', wn_250)
cv2.imwrite(img_path[0:-4] + '_fog_06.png', fog_06)
cv2.imwrite(img_path[0:-4] + '_fog_07.png', fog_07)
cv2.imwrite(img_path[0:-4] + '_fog_08.png', fog_08)
cv2.imwrite(img_path[0:-4] + '_fog_09.png', fog_09)
#-----------------------------------------------------------------------
#读取指定文件夹下的所有图像
def main():
file_path = "data"
for img_name in os.listdir(file_path):
img_path = file_path + "\\" + img_name
res_path = "data_add" + "\\" + img_name
img = cv2.imread(img_path)
#1.几何变换-镜像、翻转、旋转、缩放
JH_Transformation(img,res_path)
#2.亮度变换-增强、减弱
LD_Transformation(img,res_path)
#3.颜色通道变换
Channel_Transformation(img,res_path)
#4.添加高斯噪声和椒盐噪声
Gaussian_Salt_Noise(img,res_path)
#5.模拟怀旧和噪声添加
Fog_Salt_Noise(img,res_path)
if __name__ == "__main__":
main()
最终结果如下图所示,加原图共5280张图像。
后续可以按照同水族文字进行划分,并生成对应的训练集、测试集和验证集。
建议读者先自行尝试,结合作者前文GAN的博客,后面有时间我也会详细撰写一篇文章。
写到这里,这篇文章就介绍结束了,希望对您有所帮助,也希望大家多多关注非物质文化遗产,包括水族文字,作者多年致力于利用AI技术保护和抢救濒危少数民族文字和语音,典型的是水书、侗族大歌、清水江文献古籍等。后续也会陆续开源相关代码和文章,靠一两个人真心挺难的,但贵在喜欢,贵在有趣,尽管每年只能前进一点点,但趴着也要前行,希望能为家乡贡献一丝丝力量,加油!感恩同行,感兴趣的也希望能一起交流。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有