当前位置:   article > 正文

人工智能 | 深度学习——图像数据处理_深度学习中8位图像标准化处理

深度学习中8位图像标准化处理

目录

0.图像数据情况

1.图像数据处理

1.1.图像扩增

1.1.1.图像平移

1.1.2.图像翻转 

 1.1.3.随机角度旋转

1.1.4.变色

​ 1.1.5.图像亮度+对比度 调节

1.2.图像预处理

1.2.1.灰度图转换

1.2.2.图像梯度运算

1.2.3.图像滤波

1.2.4.图像二值化

1.2.5.腐蚀+膨胀

1.2.6.边缘检测

2.Python代码


0.图像数据情况

【图像数据】

(1)4张电商网站的商品主图,图像大小[800, 800, 3]

(2)4张电商网站的用户评论晒图,图像大小不一,一般小于[100, 100, 3]

【python类库】

(1)os\re\numpy

(2)PIL.Image:(第三方图像处理库)中的“图像类包装器”,负责图像加载、图像保存、图像转换、图像展示等(读取的图像为<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=800x800 at 0x1D10ECB7668>格式

(3)PIL.ImageChops:(第三方图像处理库)中的“图像编辑器”

(4)PIL.ImageEnhance:(第三方图像处理库)中的“图像增强器”

(5)cv2:opencv库(读取的图像为矩阵形式

1.图像数据处理

1.1.图像扩增

【扩增方法如下】

1.1.1.图像平移

 特别的,在平移的过程中应当注意,最好不要将图像的主体位置平移出了可见区域,不然会影响后续的边缘检测。

1.1.2.图像翻转 

 1.1.3.随机角度旋转

1.1.4.变色

 1.1.5.图像亮度+对比度 调节

 注意,亮度与对比度调节方式类似,只不过控制的参数不同。

1.2.图像预处理

【图像预处理流程】

① 导入图像  →  ② 灰度图转换  →  ④ 去噪(图像滤波)→ ③ 图像梯度运算  →  ⑤ 图像二值化  →  ⑥ 图像滤波  →  ⑦ 腐蚀 + 膨胀  →  ⑧ 边缘检测  →  ⑨ 图像裁剪(转换成RGB)  →  ⑩ 图像重构

1.2.1.灰度图转换

【灰度转换原因】

① 自然界中,颜色本身非常容易受到光照的影响,rgb变化很大,反而梯度信息能提供更本质的信息

② 三通道转为一通道后,运算量大大减少(三维数据 → 二维数组)

③ opencv的很多函数只支持单通道

【灰度转换函数】

  • PIL.Image.convert(mode)
  • mode: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F(参考博客)
  • cv2.cvtColor(src, code, dst=None, dstCn=None)
  • src:图像矩阵
  • code:颜色空间转换代码(请参见 #ColorConversionCodes

1.2.2.图像梯度运算

【梯度运算原因】

①图像中的真实边界点处的梯度强度大于其左右领域的梯度强度值。因此,在图像分割时,可以将基于梯度的边缘检测和阀值分割相结合

【图像梯度运算函数】

  • cv2.Sobel(src, ddepth, dx, dy, dst=None, ksize=None, scale=None, delta=None, borderType=None)
  • src:图像矩阵(一般为灰度图像)
  • ddepth:输出图像深度,请参见@ref filter_depths "combinations";(如果是8位输入图像,则会导致导数截断
  • dx:导数x的阶(一般为一阶导)
  • dy:导数y的阶(一般为一阶导)
  • ksize:扩展Sobel内核的大小;它必须是1、3、5或7
  • borderType:像素外推法,见 #BorderTypes

1.2.3.图像滤波

【图像滤波的原因】

① 保留图像细节特征的条件下对目标图像的噪声进行抑制

【图像滤波运算函数】

  • 【线性滤波】
  • → 2D滤波
  • cv2.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]])
  • ddepth:输出图像深度(-1使用src.depth())
  • kernel:模糊核大小(set形式:核越大,图像越模糊(缺陷))
  • 均值滤波(核 - 归一化)
  • cv2.blur(src, ksize, dst=None, anchor=None, borderType=None)
  • src:图像矩阵(一般为灰度图像)
  • ksize:模糊核大小(set形式:核越大,图像越模糊(缺陷))
  • anchor:锚点;默认值点(-1,-1)表示锚点位于内核
  • 方框滤波(核 - 非归一化)
  • cv2.boxFilter(src, ddepth, ksize, dst=None, anchor=None, normalize=None, borderType=None)
  • ddepth:输出图像深度(-1使用src.depth())
  • normalize:指定内核是否按其区域归一化(1表示归一化)
  • 其他参数同“均值滤波”
  • 高斯滤波
  • cv2.GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)
  • ksize:高斯核大小。ksize.width和ksize.height可以不同但必须是正数和奇数
  • sigmaX:X方向高斯核标准差
  • sigmaY:Y方向上的高斯核标准差;如果sigmaY为零,则设置为等于sigmaX;如果两个sigma均为零,则分别从ksize.width和ksize.height计算
  • 其他参数同“均值滤波”
  • 【非线性滤波】
  • 中值滤波
  • cv2.medianBlur(src, ksize, dst=None)
  • 参数同“均值滤波”
  • 双边滤波
  • cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)
  • src:图像矩阵(一般为灰度图像)
  • d:滤波过程中使用的每个像素邻域的直径。如果是非正的,则从sigmaSpace计算
  • sigmaColor:空间高斯函数标准差
  • sigmaSpace:灰度值相似性高斯函数标准差(参考博客
  • 形态学滤波
  • cv2.morphologyEx(src, op, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None) -> dst
  • src:图像矩阵。通道的数量可以是任意的。深度应该是一个CV_8U, CV_16U, CV_16S, CV_32F或CV_64F
  • op:形态操作的类型。参考 # MorphTypes
  • kenel:用于膨胀的结构元素;如果elemenat=Mat(),则用3 x 3矩形结构元素。可用getStructuringElement创建
  • anchor:锚在构件内的位置;默认值(-1,-1)表示锚点位于元素中心
  • iterations:应用侵蚀的次数

1.2.4.图像二值化

【图像二值化原因】

①凸显待裁剪的目标轮廓

②大大减少运算量,提高模型运行效率

(#compare, #inRange, #threshold, #adaptiveThreshold, #Canny,)

【图像二值化运算函数】

  • 全局阙值
  • cv2.threshold(src, thresh, maxval, type, dst=None)
  • src:图像矩阵(一般为灰度图像)
  • thresh:二值化阙值
  • maxval:与#THRESH_BINARY和#THRESH_BINARY_INV阈值类型一起使用的最大值
  • type:阙值类型(查看#ThresholdTypes) cv2.THRESH_BINARY / cv2.THRESH_BINARY_INV / cv2.THRESH_TRUNC / cv2.THRESH_TOZERO / cv2.THRESH_TOZERO_INV
  • 局部阙值
  • cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
  • src:图像矩阵(一般为灰度图像)
  • maxValue:分配给满足条件的像素的非零值
  • adaptiveMethod:要使用的自适应阈值算法,请参见#AdaptiveThresholdTypes(CV_ADAPTIVE_THRESH_MEAN_C、CV_ADAPTIVE_THRESH_GAUSSIAN_C
  • thresholdType:阙值类型(CV_THRESH_BINARY, CV_THRESH_BINARY_INV:意思同上)

1.2.5.腐蚀+膨胀

【图像腐蚀及膨胀的原因】参考博客

①腐蚀:让暗的区域变大

②膨胀:让亮的区域变大

【腐蚀+膨胀运算函数】

  • 腐蚀
  • cv2.erode(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
  • src:二值图像矩阵
  • kernel:腐蚀核;如果“element=Mat()”,则使用“3 x 3”矩形结构元素。内核可以使用 # getStructuringElement。特别的,腐蚀核的形状和元素值对最终的腐蚀结果影响较大。
  • anchor:锚定在元素中的位置;默认值(-1,-1)表示锚定位于元素中心
  • iterations:腐蚀的次数
  • 膨胀
  • cv2.dilate(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
  • 参数理解同上

1.2.6.边缘检测

【边缘检测的原因】

①去除图像中的无用部分,提高图像识别模型性能

【边缘检测运算函数】

  • 轮廓查找
  • cv2.findContours(image, mode, method, contours=None, hierarchy=None, offset=None) -> contours, hierarchy
  • image:二值图像矩阵
  • mode:轮廓检索模式。参照 # RetrievalModes
  • method:轮廓近似的方法。参照  # ContourApproximationModes
  • contour:检测到的轮廓,每个轮廓都是以点向量的形式进行存储即使用point类型的vector表示
  • hierarchy:可选的输出向量(std::vector),包含了图像的拓扑信息,作为轮廓数量的表示hierarchy包含了很多元素,每个轮廓contours[i]对应hierarchy中hierarchy[i][0]~hierarchy[i][3],分别表示后一个轮廓,前一个轮廓,父轮廓,内嵌轮廓的索引,如果没有对应项,则相应的hierarchy[i]设置为负数。
  • offset:轮廓点可选偏移量,有默认值Point(),对ROI图像中找出的轮廓并要在整个图像中进行分析时使用
  • 计算各轮廓对应面积
  • cv2.contourArea(contour, oriented=None) -> retval
  • contour:二维点(轮廓顶点)的输入向量,存储在std::vector或Mat中。(cv2.findContours的返回值)
  • oriented:面向区域标志。如果为真,则函数根据轮廓方向(顺时针或逆时针)返回一个有符号的面积值。使用此功能,您可以通过取面积的符号来确定轮廓的方向。默认情况下,参数为false,这意味着返回绝对值。
  • → 查找包含输入的最小区域的旋转矩形
  • cv2.minAreaRect(points) -> retval
  • points:二维点的输入向量,存储在std::vector\<\>或Mat中(也就是sort(,key=cv2.contourArea(),)之后的结果)
  • 获得最小外接旋转矩形的4个顶点
  • cv2.boxPoints(box, points=None) -> points
  • box:cv2.minAreaRect的返回值(输入旋转矩形)
  • points:矩形的四个顶点的输出数组
  • 画线
  • cv2.rectangle(img, pt1, pt2, color, thickness=None, lineType=None, shift=None) -> img
  • img:图像矩阵(RGB:线可为彩色;GRAY:线为黑白色)
  • pt1:矩形顶点(对角线顶点之一)
  • pt2:与pt1相对的矩形的顶点(对角线顶点之二)
  • color:矩形颜色(三维列表[r,g,b])
  • thickness:线宽。像#FILLED这样的负值表示函数必须绘制一个填充矩形
  • lineType:线的类型. 参考 #LineTypes
  • shift:点坐标中的小数位数

2.Python代码

  1. # ! /usr/bin/env python
  2. # coding:utf-8
  3. # python interpreter:3.6.2
  4. # author: admin_maxin
  5. import io, os
  6. import numpy as np
  7. import cv2
  8. import re
  9. from PIL import Image, ImageEnhance, ImageChops
  10. class PicExpansion:
  11. # =====================================图像扩增
  12. def __init__(self, path):
  13. """
  14. 初始化图片文件路径
  15. :param path: 初始路径
  16. """
  17. self.path = path # 起始路径
  18. self.sub = [] # 子文件夹下文件的个数
  19. self.num = 0 # 文件总数
  20. def get_Imgs_Paths(self, *suffix):
  21. """
  22. 批量获取图片名称
  23. :return:文件夹下的所有图像名称列表
  24. """
  25. trees = os.walk(self.path)
  26. pathArray = []
  27. # 获取所有文件的绝对路径
  28. # [str1, str2, ...]
  29. for root, dirs, files in trees:
  30. self.sub.append(len(files))
  31. for fn in files:
  32. if os.path.splitext(fn)[1] in suffix: # 判断图片文件的格式
  33. fname = os.path.join(root, fn)
  34. pathArray.append(fname)
  35. self.num = sum(self.sub)
  36. return pathArray
  37. def reSize(self, filepaths, *suffix):
  38. """
  39. 原始图像大小调整
  40. :param filepaths:
  41. :return:
  42. """
  43. for i in range(self.num):
  44. img = Image.open(filepaths[i])
  45. img2 = img.resize(suffix)
  46. img2.save(filepaths[i])
  47. return None
  48. def move(self, filepath):
  49. """
  50. 图像平移
  51. :return:
  52. """
  53. img = Image.open(filepath)
  54. tmp = min(img.height, img.width)/10
  55. return ImageChops.offset(img, np.random.randint(0, tmp, 1))
  56. def flip(self, filepath):
  57. """
  58. 图像翻转
  59. :return:
  60. """
  61. img = Image.open(filepath)
  62. return img.transpose(Image.FLIP_LEFT_RIGHT)
  63. def rotation(self, filepath):
  64. """
  65. 随机角度旋转
  66. :param filepaths:
  67. :return:
  68. """
  69. img = Image.open(filepath)
  70. return img.rotate(angle=np.random.randint(0, 360, 1))
  71. def changeColor(self, filepath):
  72. """
  73. 随机颜色
  74. :param filepaths:
  75. :return:
  76. """
  77. img = cv2.imread(filepath)
  78. img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
  79. img_hsv[:, :, 0] = (img_hsv[:, :, 0] + np.random.randint(1, 180)) % 180
  80. img_hsv[:, :, 1] = (img_hsv[:, :, 1] + np.random.randint(1, 255)) % 255
  81. img_hsv[:, :, 2] = (img_hsv[:, :, 2] + np.random.randint(1, 255)) % 255
  82. return cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR)
  83. def changeBright_and_contrast(self, filepath, alpha=1, beta=0):
  84. """
  85. 调整图像亮度 + 对比图
  86. :param filepath:
  87. :param alpha: 对比度参数
  88. :param beta: 亮度参数
  89. :return:
  90. """
  91. img = Image.open(filepath)
  92. return Image.eval(img, lambda x: x*alpha + beta)
  93. # def deNoisingColored(self, filepath):
  94. # """
  95. # 去除彩色图像高斯噪声
  96. # :param filepath:
  97. # :return:
  98. # """
  99. # img = cv2.imread(filepath)
  100. # return cv2.fastNlMeansDenoisingColored(img, None, 10, 10, 7, 21)
  101. #
  102. # def local_threshold(self, filepath):
  103. # """
  104. # 灰度图二值化(局部阙值)
  105. # :param filepath:
  106. # :return:
  107. # """
  108. # img = cv2.imread(filepath)
  109. # img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  110. # ret, binary = cv2.threshold(img, 2*(np.max(img)-np.min(img))/5, 255, cv2.THRESH_BINARY)
  111. # return binary
  112. # =====================================图像预处理
  113. def box_detect(self, filepath):
  114. """
  115. 边缘检测及裁剪
  116. :param filepath:
  117. :return:
  118. """
  119. # 转换为灰度图
  120. img = cv2.imread(filepath)
  121. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  122. image = Image.open(filepath)
  123. # 留下具有高水平梯度和低垂直梯度的图像区域
  124. gradX = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
  125. gradY = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=0, dy=1, ksize=-1)
  126. gradient = cv2.addWeighted(gradX, 1, gradY, 2, 1)
  127. # gradient = cv2.subtract(gradX, gradY)
  128. # Sobel函数求完导数后会有负值,还有会大于255的值。而原图像是uint8,即8位无符号数,所以Sobel建立的图像位数不够,会有截断。
  129. # 因此要使用16位有符号的数据类型,即cv2.CV_16S。处理完图像后,再使用cv2.convertScaleAbs()函数将其转回原来的uint8格式,
  130. # 否则图像无法显示。
  131. gradient = cv2.convertScaleAbs(gradient)
  132. cv2.imwrite(str(np.random.randint(100, 200, 1))+".jpg", gradient)
  133. # 均值滤波
  134. blurred = cv2.blur(gradient, (9, 9))
  135. # ret, binary = cv2.threshold(img, 90, 255, cv2.THRESH_BINARY)
  136. # ret, binary = cv2.threshold(img, 160, 255, cv2.THRESH_BINARY)
  137. # 二值化
  138. (ret, thresh) = cv2.threshold(blurred, 2*(np.max(img)-np.min(img))/5, 255, cv2.THRESH_BINARY)
  139. # 图像滤波
  140. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25, 25)) # 返回指定形状及尺寸的结构元素
  141. closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) # 形态学滤波
  142. # 腐蚀与膨胀
  143. element = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3), (-1, -1))
  144. closed = cv2.erode(closed, element, iterations=4)
  145. closed = cv2.dilate(closed, element, iterations=4)
  146. # cv2.imwrite(str(np.random.randint(100, 200, 1))+".jpg", closed)
  147. # 边缘检测
  148. cnts, _ = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  149. cc = cv2.Canny(closed.copy(), 80, 150)
  150. ccc = cv2.Canny(closed.copy(), 50, 100)
  151. ret = np.hstack((cc, ccc))
  152. c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
  153. rect = cv2.minAreaRect(c) # 得到最小外接旋转矩形的(中心(x,y), (宽,高), 旋转角度)
  154. box = np.int0(cv2.boxPoints(rect)) # cv2.boxPoints:得到最小外接旋转矩形的四个顶点。用于绘制旋转矩形。
  155. # 裁剪
  156. Xs = [i[0] for i in box] # 获取4个顶点x坐标
  157. Ys = [i[1] for i in box] # 获取4个顶点y坐标
  158. x1 = min(Xs)
  159. x2 = max(Xs)
  160. y1 = min(Ys)
  161. y2 = max(Ys)
  162. hight = y2 - y1
  163. width = x2 - x1
  164. # # 给原图画线
  165. # out = cv2.rectangle(img, (x1, y1), (x1 + width, y1 + hight), (0, 0, 255), 20)
  166. # cv2.imwrite(str(np.random.randint(100, 200, 1)) + ".jpg", out)
  167. return cv2.resize(img[y1:y1 + hight, x1:x1 + width], (32, 32))
  168. if "__main__" == __name__:
  169. path = "E:\\picOriginal"
  170. test = PicExpansion(path)
  171. filepaths = test.get_Imgs_Paths(".jpg", ".png")
  172. # 图像增强方法的个数
  173. fuc = 2
  174. # 操作循环i次
  175. for i in range(1):
  176. # 分文件夹操作
  177. for j in range(1, len(test.sub)):
  178. tmp = 0
  179. # 遍历商品路径列表
  180. for k in range(test.num):
  181. cls = int(filepaths[k].split("\\")[-2])
  182. if cls == j:
  183. # tmp += 1
  184. # img = test.move(filepaths[k]) # 图像平移
  185. # img.save(filepaths[k].split("_")[0]+"_"+str(test.sub[j]+tmp)+".jpg")
  186. # tmp += 1
  187. # img = test.flip(filepaths[k]) # 图像翻转
  188. # img.save(filepaths[k].split("_")[0]+"_"+str(test.sub[j]+tmp)+".jpg")
  189. # tmp += 1
  190. # img = test.rotation(filepaths[k]) # 随机角度旋转
  191. # img.save(filepaths[k].split("_")[0]+"_"+str(test.sub[j]+tmp)+".jpg")
  192. # tmp += 1
  193. # img = test.changeColor(filepaths[k]) # 颜色变换
  194. # cv2.imwrite(filepaths[k].split("_")[0]+"_"+str(test.sub[j]+tmp)+".jpg", img)
  195. # tmp += 1
  196. # img = test.changeBright_and_contrast(filepaths[k], 1, beta=80) # 亮度调节
  197. # img.save(filepaths[k].split("_")[0]+"_"+str(test.sub[j]+tmp)+".jpg")
  198. # tmp += 1
  199. # img = test.changeBright_and_contrast(filepaths[k], 4, 0) # 对比度调节
  200. # img.save(filepaths[k].split("_")[0]+"_"+str(test.sub[j]+tmp)+".jpg")
  201. # tmp += 1
  202. # img = test.cvtColor_gray(filepaths[k]) # 灰度图转化
  203. # cv2.imwrite(filepaths[k].split("_")[0]+"_"+str(test.sub[j]+tmp)+".jpg", img)
  204. # tmp += 1
  205. # img = test.deNoisingColored(filepaths[k]) # 去除图像噪声
  206. # cv2.imwrite(filepaths[k].split("_")[0]+"_"+str(test.sub[j]+tmp)+".jpg", img)
  207. # tmp += 1
  208. # img = test.local_threshold(filepaths[k])
  209. # cv2.imwrite(filepaths[k].split("_")[0] + "_" + str(test.sub[j] + tmp) + ".jpg", img)
  210. tmp += 1
  211. img = test.box_detect(filepaths[k])
  212. # cv2.imwrite(filepaths[k].split("_")[0] + "_" + str(test.sub[j] + tmp) + ".jpg", img)
  213. test.sub[j] = test.sub[j] * (fuc + 1)

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/91059
推荐阅读
相关标签
  

闽ICP备14008679号