python目标检测 训练数据预处理及加载代码

分手后的思念是犯贱 2022-11-30 15:50 227阅读 0赞

数据预处理

  1. def letterbox_image(img, inp_dim):
  2. '''resize image with unchanged aspect ratio using padding
  3. Parameters
  4. ----------
  5. img : numpy.ndarray
  6. Image
  7. inp_dim: tuple(int)
  8. shape of the reszied image
  9. Returns
  10. -------
  11. numpy.ndarray:
  12. Resized image
  13. '''
  14. inp_dim = (inp_dim, inp_dim)
  15. img_w, img_h = img.shape[1], img.shape[0]
  16. w, h = inp_dim
  17. new_w = int(img_w * min(w/img_w, h/img_h))
  18. new_h = int(img_h * min(w/img_w, h/img_h))
  19. resized_image = cv2.resize(img, (new_w,new_h)) # 按照target_szie/(长边)为scale进行resize,然后填充空白区域
  20. canvas = np.full((inp_dim[1], inp_dim[0], 3), 0)
  21. canvas[(h-new_h)//2:(h-new_h)//2 + new_h,(w-new_w)//2:(w-new_w)//2 + new_w, :] = resized_image
  22. return canvas
  23. class Resize(object):
  24. """Resize the image in accordance to `image_letter_box` function in darknet
  25. The aspect ratio is maintained. The longer side is resized to the input
  26. size of the network, while the remaining space on the shorter side is filled
  27. with black color. **This should be the last transform**
  28. Parameters
  29. ----------
  30. inp_dim : tuple(int)
  31. tuple containing the size to which the image will be resized.
  32. Returns
  33. -------
  34. numpy.ndaaray
  35. Sheared image in the numpy format of shape `HxWxC`
  36. numpy.ndarray
  37. Resized bounding box co-ordinates of the format `n x 4` where n is
  38. number of bounding boxes and 4 represents `x1,y1,x2,y2` of the box
  39. """
  40. def __init__(self, inp_dim):
  41. self.inp_dim = inp_dim
  42. def __call__(self, img, bboxes):
  43. w,h = img.shape[1], img.shape[0]
  44. img = letterbox_image(img, self.inp_dim) # 按照target_szie/(长边)为scale进行resize,然后填充空白区域
  45. scale = min(self.inp_dim/h, self.inp_dim/w)
  46. bboxes[:,:4] *= (scale)
  47. new_w = scale*w
  48. new_h = scale*h
  49. inp_dim = self.inp_dim
  50. del_h = (inp_dim - new_h)/2
  51. del_w = (inp_dim - new_w)/2
  52. add_matrix = np.array([[del_w, del_h, del_w, del_h]]).astype(int)
  53. bboxes[:,:4] += add_matrix # 根据空白区域补充
  54. img = img.astype(np.uint8)
  55. return img, bboxes
  56. class RandomHorizontalFlip(object):
  57. """Randomly horizontally flips the Image with the probability *p*
  58. Parameters
  59. ----------
  60. p: float
  61. The probability with which the image is flipped
  62. Returns
  63. -------
  64. numpy.ndaaray
  65. Flipped image in the numpy format of shape `HxWxC`
  66. numpy.ndarray
  67. Tranformed bounding box co-ordinates of the format `n x 4` where n is
  68. number of bounding boxes and 4 represents `x1,y1,x2,y2` of the box
  69. """
  70. def __init__(self, p=0.5):
  71. self.p = p
  72. def __call__(self, img, bboxes):
  73. img_center = np.array(img.shape[:2])[::-1]/2 # 得到图像中心坐标(x,y)
  74. img_center = np.hstack((img_center, img_center))
  75. if random.random() < self.p:
  76. img = img[:, ::-1, :] # 图像水平翻转
  77. bboxes[:, [0, 2]] += 2*(img_center[[0, 2]] - bboxes[:, [0, 2]]) # 将box(x1,y1,x2,y2)的x坐标翻转,
  78. box_w = abs(bboxes[:, 0] - bboxes[:, 2])
  79. bboxes[:, 0] -= box_w # 翻转后的坐标,x1>x2;该操作交换坐标,使得x1<x2
  80. bboxes[:, 2] += box_w
  81. return img, bboxes
  82. class RandomScale(object):
  83. """Randomly scales an image
  84. Bounding boxes which have an area of less than 25% in the remaining in the
  85. transformed image is dropped. The resolution is maintained, and the remaining
  86. area if any is filled by black color.
  87. Parameters
  88. ----------
  89. scale: float or tuple(float)
  90. if **float**, the image is scaled by a factor drawn
  91. randomly from a range (1 - `scale` , 1 + `scale`). If **tuple**,
  92. the `scale` is drawn randomly from values specified by the
  93. tuple
  94. Returns
  95. -------
  96. numpy.ndaaray
  97. Scaled image in the numpy format of shape `HxWxC`
  98. numpy.ndarray
  99. Tranformed bounding box co-ordinates of the format `n x 4` where n is
  100. number of bounding boxes and 4 represents `x1,y1,x2,y2` of the box
  101. """
  102. def __init__(self, scale = 0.2, diff = False):
  103. self.scale = scale
  104. if type(self.scale) == tuple:
  105. assert len(self.scale) == 2, "Invalid range"
  106. assert self.scale[0] > -1, "Scale factor can't be less than -1"
  107. assert self.scale[1] > -1, "Scale factor can't be less than -1"
  108. else:
  109. assert self.scale > 0, "Please input a positive float"
  110. self.scale = (max(-1, -self.scale), self.scale)
  111. self.diff = diff
  112. def __call__(self, img, bboxes):
  113. #Chose a random digit to scale by
  114. img_shape = img.shape
  115. if self.diff:
  116. scale_x = random.uniform(*self.scale)
  117. scale_y = random.uniform(*self.scale)
  118. else:
  119. scale_x = random.uniform(*self.scale)
  120. scale_y = scale_x
  121. resize_scale_x = 1 + scale_x
  122. resize_scale_y = 1 + scale_y
  123. # The logic of the Scale transformation is fairly simple.
  124. # We use the OpenCV function cv2.resize to scale our image, and scale our bounding boxes by the scale factor(s).
  125. img= cv2.resize(img, None, fx = resize_scale_x, fy = resize_scale_y)
  126. bboxes[:,:4] *= [resize_scale_x, resize_scale_y, resize_scale_x, resize_scale_y]
  127. canvas = np.zeros(img_shape, dtype = np.uint8) # 原始图像大小
  128. y_lim = int(min(resize_scale_y,1)*img_shape[0])
  129. x_lim = int(min(resize_scale_x,1)*img_shape[1])
  130. canvas[:y_lim,:x_lim,:] = img[:y_lim,:x_lim,:] # 有可能变大或者变小,如果变大,取其中一部分,变小,黑色填充
  131. img = canvas
  132. bboxes = clip_box(bboxes, [0,0,1 + img_shape[1], img_shape[0]], 0.25) # 对变换后的box:处理超出边界和面积小于阈值drop操作;
  133. return img, bboxes
  134. class RandomTranslate(object): # 随机平移
  135. """Randomly Translates the image
  136. Bounding boxes which have an area of less than 25% in the remaining in the
  137. transformed image is dropped. The resolution is maintained, and the remaining
  138. area if any is filled by black color.
  139. Parameters
  140. ----------
  141. translate: float or tuple(float)
  142. if **float**, the image is translated by a factor drawn
  143. randomly from a range (1 - `translate` , 1 + `translate`). If **tuple**,
  144. `translate` is drawn randomly from values specified by the
  145. tuple
  146. Returns
  147. -------
  148. numpy.ndaaray
  149. Translated image in the numpy format of shape `HxWxC`
  150. numpy.ndarray
  151. Tranformed bounding box co-ordinates of the format `n x 4` where n is
  152. number of bounding boxes and 4 represents `x1,y1,x2,y2` of the box
  153. """
  154. def __init__(self, translate = 0.2, diff = False):
  155. self.translate = translate
  156. if type(self.translate) == tuple:
  157. assert len(self.translate) == 2, "Invalid range"
  158. assert self.translate[0] > 0 & self.translate[0] < 1
  159. assert self.translate[1] > 0 & self.translate[1] < 1
  160. else:
  161. assert self.translate > 0 and self.translate < 1
  162. self.translate = (-self.translate, self.translate) # 必须在(0-1)之间
  163. self.diff = diff
  164. def __call__(self, img, bboxes):
  165. #Chose a random digit to scale by
  166. img_shape = img.shape
  167. #translate the image
  168. #percentage of the dimension of the image to translate
  169. translate_factor_x = random.uniform(*self.translate)
  170. translate_factor_y = random.uniform(*self.translate)
  171. if not self.diff:
  172. translate_factor_y = translate_factor_x
  173. canvas = np.zeros(img_shape).astype(np.uint8)
  174. corner_x = int(translate_factor_x*img.shape[1])
  175. corner_y = int(translate_factor_y*img.shape[0])
  176. #change the origin to the top-left corner of the translated box # 相当于做一个平移操作,做超过边界处理等
  177. orig_box_cords = [max(0,corner_y), max(corner_x,0), min(img_shape[0], corner_y + img.shape[0]), min(img_shape[1],corner_x + img.shape[1])]
  178. mask = img[max(-corner_y, 0):min(img.shape[0], -corner_y + img_shape[0]), max(-corner_x, 0):min(img.shape[1], -corner_x + img_shape[1]),:]
  179. canvas[orig_box_cords[0]:orig_box_cords[2], orig_box_cords[1]:orig_box_cords[3],:] = mask
  180. img = canvas
  181. bboxes[:,:4] += [corner_x, corner_y, corner_x, corner_y] # box做一个平移操作
  182. bboxes = clip_box(bboxes, [0,0,img_shape[1], img_shape[0]], 0.25)
  183. return img, bboxes
  184. class RandomRotate(object):
  185. """Randomly rotates an image
  186. Bounding boxes which have an area of less than 25% in the remaining in the
  187. transformed image is dropped. The resolution is maintained, and the remaining
  188. area if any is filled by black color.
  189. Parameters
  190. ----------
  191. angle: float or tuple(float)
  192. if **float**, the image is rotated by a factor drawn
  193. randomly from a range (-`angle`, `angle`). If **tuple**,
  194. the `angle` is drawn randomly from values specified by the
  195. tuple
  196. Returns
  197. -------
  198. numpy.ndaaray
  199. Rotated image in the numpy format of shape `HxWxC`
  200. numpy.ndarray
  201. Tranformed bounding box co-ordinates of the format `n x 4` where n is
  202. number of bounding boxes and 4 represents `x1,y1,x2,y2` of the box
  203. """
  204. def __init__(self, angle = 10):
  205. self.angle = angle
  206. if type(self.angle) == tuple:
  207. assert len(self.angle) == 2, "Invalid range"
  208. else:
  209. self.angle = (-self.angle, self.angle)
  210. def __call__(self, img, bboxes):
  211. angle = random.uniform(*self.angle)
  212. w,h = img.shape[1], img.shape[0]
  213. cx, cy = w//2, h//2
  214. img = rotate_im(img, angle) # 旋转后,为了保证整图信息,仿射后的图像变大,先求仿射矩阵,然后变换整图;
  215. corners = get_corners(bboxes) # 得到四个角点
  216. corners = np.hstack((corners, bboxes[:,4:]))
  217. corners[:,:8] = rotate_box(corners[:,:8], angle, cx, cy, h, w) # 根据仿射矩阵得到box旋转后的坐标
  218. new_bbox = get_enclosing_box(corners) # we have to find the tightest rectangle parallel to the sides of the image containing the tilted rectangular box.
  219. scale_factor_x = img.shape[1] / w
  220. scale_factor_y = img.shape[0] / h
  221. img = cv2.resize(img, (w,h)) # 旋转后变大的图像恢复到原图像大小;
  222. new_bbox[:,:4] /= [scale_factor_x, scale_factor_y, scale_factor_x, scale_factor_y]
  223. bboxes = new_bbox
  224. bboxes = clip_box(bboxes, [0,0,w, h], 0.25)
  225. return img, bboxes
  226. class RandomShear(object): # 旋转的特殊情况
  227. """Randomly shears an image in horizontal direction
  228. Bounding boxes which have an area of less than 25% in the remaining in the
  229. transformed image is dropped. The resolution is maintained, and the remaining
  230. area if any is filled by black color.
  231. Parameters
  232. ----------
  233. shear_factor: float or tuple(float)
  234. if **float**, the image is sheared horizontally by a factor drawn
  235. randomly from a range (-`shear_factor`, `shear_factor`). If **tuple**,
  236. the `shear_factor` is drawn randomly from values specified by the
  237. tuple
  238. Returns
  239. -------
  240. numpy.ndaaray
  241. Sheared image in the numpy format of shape `HxWxC`
  242. numpy.ndarray
  243. Tranformed bounding box co-ordinates of the format `n x 4` where n is
  244. number of bounding boxes and 4 represents `x1,y1,x2,y2` of the box
  245. """
  246. def __init__(self, shear_factor = 0.2):
  247. self.shear_factor = shear_factor
  248. if type(self.shear_factor) == tuple:
  249. assert len(self.shear_factor) == 2, "Invalid range for scaling factor"
  250. else:
  251. self.shear_factor = (-self.shear_factor, self.shear_factor)
  252. shear_factor = random.uniform(*self.shear_factor)
  253. def __call__(self, img, bboxes):
  254. shear_factor = random.uniform(*self.shear_factor)
  255. w,h = img.shape[1], img.shape[0]
  256. if shear_factor < 0:
  257. img, bboxes = HorizontalFlip()(img, bboxes) # 一种巧妙的方法,来避免...
  258. M = np.array([[1, abs(shear_factor), 0],[0,1,0]])
  259. nW = img.shape[1] + abs(shear_factor*img.shape[0])
  260. bboxes[:,[0,2]] += ((bboxes[:,[1,3]]) * abs(shear_factor) ).astype(int)
  261. img = cv2.warpAffine(img, M, (int(nW), img.shape[0])) # 只进行水平变换
  262. if shear_factor < 0:
  263. img, bboxes = HorizontalFlip()(img, bboxes)
  264. img = cv2.resize(img, (w,h))
  265. scale_factor_x = nW / w
  266. bboxes[:,:4] /= [scale_factor_x, 1, scale_factor_x, 1]
  267. return img, bboxes

数据加载

1.解析图片

  1. def parse_data(data):
  2. img = np.array(cv2.imread(data))
  3. h, w, c = img.shape
  4. assert c == 3
  5. img = cv2.resize(img, (scale_size, scale_size))
  6. img = img.astype(np.float32)
  7. shift = (scale_size - crop_size) // 2
  8. img = img[shift: shift + crop_size, shift: shift + crop_size, :]
  9. # Flip image at random if flag is selected
  10. if np.random.random() < 0.5: # self.horizontal_flip and
  11. img = cv2.flip(img, 1)
  12. img = (img - np.array(127.5)) / 127.5
  13. return img
  14. def parse_data_without_augmentation(data):
  15. img = np.array(cv2.imread(data))
  16. h, w, c = img.shape
  17. assert c == 3
  18. img = cv2.resize(img, (crop_size, crop_size))
  19. img = img.astype(np.float32)
  20. img = (img - np.array(127.5)) / 127.5
  21. return img

2.多进程加载

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # @Time : 2019/3/10 11:15
  4. # @Author : Whu_DSP
  5. # @File : dped_dataloader.py
  6. import multiprocessing as mtp
  7. import os
  8. import cv2
  9. import numpy as np
  10. from scipy import misc
  11. def parse_data(filename):
  12. I = np.asarray(misc.imread(filename))
  13. I = np.float16(I) / 255
  14. return I
  15. class Dataloader:
  16. def __init__(self, dped_dir, type_phone, batch_size, is_training, im_shape):
  17. self.works = mtp.Pool(10)
  18. self.dped_dir = dped_dir
  19. self.phone_type = type_phone
  20. self.batch_size = batch_size
  21. self.is_training = is_training
  22. self.im_shape = im_shape
  23. self.image_list, self.dslr_list = self._get_data_file_list()
  24. self.num_images = len(self.image_list)
  25. self._cur = 0
  26. self._perm = None
  27. self._shuffle_index() # init order
  28. def _get_data_file_list(self):
  29. if self.is_training:
  30. directory_phone = os.path.join(self.dped_dir, str(self.phone_type), 'training_data', str(self.phone_type))
  31. directory_dslr = os.path.join(self.dped_dir, str(self.phone_type), 'training_data', 'canon')
  32. else:
  33. directory_phone = os.path.join(self.dped_dir, str(self.phone_type), 'test_data', 'patches',
  34. str(self.phone_type))
  35. directory_dslr = os.path.join(self.dped_dir, str(self.phone_type), 'test_data', 'patches', 'canon')
  36. # num_images = len([name for name in os.listdir(directory_phone) if os.path.isfile(os.path.join(directory_phone, name))])
  37. image_list = [os.path.join(directory_phone, name) for name in os.listdir(directory_phone)]
  38. dslr_list = [os.path.join(directory_dslr, name) for name in os.listdir(directory_dslr)]
  39. return image_list, dslr_list
  40. def _shuffle_index(self):
  41. '''randomly permute the train order'''
  42. self._perm = np.random.permutation(np.arange(self.num_images))
  43. self._cur = 0
  44. def _get_next_minbatch_index(self):
  45. """return the indices for the next minibatch"""
  46. if self._cur + self.batch_size > self.num_images:
  47. self._shuffle_index()
  48. next_index = self._perm[self._cur:self._cur + self.batch_size]
  49. self._cur += self.batch_size
  50. return next_index
  51. def get_minibatch(self, minibatch_db):
  52. """return minibatch datas for train/test"""
  53. if self.is_training:
  54. jobs = self.works.map(parse_data, minibatch_db)
  55. else:
  56. jobs = self.works.map(parse_data, minibatch_db)
  57. index = 0
  58. images_data = np.zeros([self.batch_size, self.im_shape[0], self.im_shape[1], 3])
  59. for index_job in range(len(jobs)):
  60. images_data[index, :, :, :] = jobs[index_job]
  61. index += 1
  62. return images_data
  63. def next_batch(self):
  64. """Get next batch images and labels"""
  65. db_index = self._get_next_minbatch_index()
  66. minibatch_db = []
  67. for i in range(len(db_index)):
  68. minibatch_db.append(self.image_list[db_index[i]])
  69. minibatch_db_t = []
  70. for i in range(len(db_index)):
  71. minibatch_db_t.append(self.dslr_list[db_index[i]])
  72. images_data = self.get_minibatch(minibatch_db)
  73. dslr_data = self.get_minibatch(minibatch_db_t)
  74. return images_data, dslr_data
  75. if __name__ == "__main__":
  76. data_dir = "F:\\ranjiewen\\TF_EnhanceDPED\\data\\dped"
  77. train_loader = Dataloader(data_dir, "iphone", 32, True,[100,100])
  78. test_loader = Dataloader(data_dir, "iphone", 32, False, [100, 100])
  79. for i in range(10):
  80. image_batch,label_batch = train_loader.next_batch()
  81. print(image_batch.shape,label_batch.shape)
  82. print("-------------------------------------------")
  83. image_batch,label_batch = test_loader.next_batch()
  84. print(image_batch.shape,label_batch.shape)

其他增强方式

  • 对图像进行缩放并进行长和宽的扭曲
  • 对图像进行翻转
  • 对图像进行色域扭曲

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTE4MDg2NzM_size_16_color_FFFFFF_t_70

  1. from PIL import Image, ImageDraw
  2. import numpy as np
  3. from matplotlib.colors import rgb_to_hsv, hsv_to_rgb
  4. """
  5. 数据增强的方式:
  6. 数据增强其实就是让图片变得更加多样,数据增强是非常重要的提高目标检测算法鲁棒性的手段。
  7. 可以通过改变亮度,图像扭曲等方式使得图像变得更加多种多样,改变后的图片放入神经网络进行训练可以提高网络的鲁棒性,降低各方面额外因素对识别的影响.
  8. """
  9. def rand(a=0, b=1): # 生成一个取值范围为[a,b)的随机数
  10. return np.random.rand() * (b - a) + a
  11. # get_random_data数据增强
  12. def get_random_data(annotation_line, input_shape, random=True, max_boxes=20, jitter=.5, hue=.1, sat=1.5, val=1.5, proc_img=True):
  13. """
  14. 实时数据增强的随机预处理
  15. random preprocessing for real-time data augmentation
  16. :param annotation_line: 数据集中的某一行对应的图片
  17. :param input_shape: yolo网络输入图片的大小416*416
  18. :param random:
  19. :param max_boxes:
  20. :param jitter:控制图片的宽高的扭曲比率,jitter=.5表示在0.5到1.5之间进行扭曲
  21. :param hue: 代表hsv色域中三个通道中的色调进行扭曲,色调(H)=.1
  22. :param sat: 代表hsv色域中三个通道中的饱和度进行扭曲,饱和度(S)=1.5
  23. :param val: 代表hsv色域中三个通道中的明度进行扭曲,明度(V)=1.5
  24. :param proc_img:
  25. :return:
  26. """
  27. line = annotation_line.split()
  28. image = Image.open(line[0])
  29. iw, ih = image.size # 原图片大小
  30. h, w = input_shape # 模型输入图片的大小
  31. box = np.array([np.array(list(map(int, box.split(',')))) for box in line[1:]]) # 对该行的图片中的目标框进行一个划分
  32. # 对图像进行缩放并且进行长和宽的扭曲
  33. # 扭曲后的图片大小可能会大于416*416的大小,但是在加灰条的时候会修正为416*416
  34. new_ar = w/h * rand(1-jitter, 1+jitter)/rand(1-jitter, 1+jitter) # 表原图片的宽高的扭曲比率,jitter=0,则原图的宽高的比率不变,否则对图片的宽和高进行一定的扭曲
  35. scale = rand(.25, 2) # scale控制对原图片的缩放比率,rand(.25, 2)表示在0.25到2之间缩放,图片可能会放大可能会缩小,rand(.25, 1)会把原始的图片进行缩小,图片的边缘加上灰条,可以训练网络对我们小目标的检测能力。rand(1,2)则是一定放大图像
  36. if new_ar < 1:
  37. nh = int(scale * h)
  38. nw = int(nh * new_ar)
  39. else:
  40. nw = int(scale * w)
  41. nh = int(nw / new_ar)
  42. image = image.resize((nw, nh), Image.BICUBIC)
  43. # print(nw,nh) # 扭曲后的图片的宽和高
  44. # 将图像多余的部分加上灰条,一定保证图片的大小为w,h = 416,416
  45. dx = int(rand(0, w - nw))
  46. dy = int(rand(0, h - nh))
  47. new_image = Image.new('RGB', (w, h), (128, 128, 128)) # (128, 128, 128)代表灰色
  48. new_image.paste(image, (dx, dy))
  49. image = new_image
  50. # 是否翻转图像
  51. flip = rand() < .5 # 有50%的几率发生翻转
  52. if flip: image = image.transpose(Image.FLIP_LEFT_RIGHT) # 左右翻转
  53. # 色域扭曲
  54. # 色域扭曲是发生在这个hsv这样的色域上,hsv色域是有色调H、饱和度S、明度V三者控制,调整这3个值调整色域扭曲的比率
  55. hue = rand(-hue, hue)
  56. sat = rand(1, sat) if rand()<.5 else 1/rand(1, sat)
  57. val = rand(1, val) if rand()<.5 else 1/rand(1, val)
  58. x = rgb_to_hsv(np.array(image) / 255.) # 将图片从RGB图像调整到hsv色域上之后,再对其色域进行扭曲
  59. x[..., 0] += hue
  60. x[..., 0][x[..., 0] > 1] -= 1
  61. x[..., 0][x[..., 0] < 0] += 1
  62. x[..., 1] *= sat
  63. x[..., 2] *= val
  64. x[x > 1] = 1
  65. x[x < 0] = 0
  66. image_data = hsv_to_rgb(x) # numpy array, 0 to 1
  67. # 将box进行调整
  68. # 对原图片进项扭曲后,也要对原图片中的框框也进行相应的调整
  69. box_data = np.zeros((max_boxes, 5))
  70. if len(box) > 0:
  71. np.random.shuffle(box)
  72. # 扭曲调整
  73. box[:, [0, 2]] = box[:, [0, 2]] * nw / iw + dx
  74. box[:, [1, 3]] = box[:, [1, 3]] * nh / ih + dy
  75. # 旋转调整
  76. if flip: box[:, [0, 2]] = w - box[:, [2, 0]]
  77. # 因为调整后不再图像中的目标框的调整
  78. box[:, 0:2][box[:, 0:2] < 0] = 0
  79. box[:, 2][box[:, 2] > w] = w
  80. box[:, 3][box[:, 3] > h] = h
  81. box_w = box[:, 2] - box[:, 0]
  82. box_h = box[:, 3] - box[:, 1]
  83. box = box[np.logical_and(box_w > 1, box_h > 1)] # discard invalid box
  84. if len(box) > max_boxes: box = box[:max_boxes]
  85. box_data[:len(box)] = box
  86. return image_data, box_data
  87. # 原图片绘制展示
  88. def normal_(annotation_line, input_shape):
  89. """
  90. random preprocessing for real-time data augmentation
  91. :param annotation_line: 选取的数据集第a行所对应的图片进行数据增强
  92. :param input_shape: 输入的大小
  93. :return:
  94. """
  95. line = annotation_line.split() # 以空格进行分割
  96. # 获取该行对应的图片
  97. image = Image.open(line[0])
  98. # 获取该图片上的每一个目标框
  99. box = np.array([np.array(list(map(int, box.split(',')))) for box in line[1:]])
  100. return image, box
  101. if __name__ == "__main__":
  102. with open("2007_train.txt") as f:
  103. lines = f.readlines()
  104. a = np.random.randint(0, len(lines))
  105. line = lines[a] # 选取的数据集第a行所对应的图片进行数据增强
  106. image_data, box_data = normal_(line, [416, 416])
  107. img = image_data
  108. # 原图片绘制展示
  109. #数据集的第a行图片的展现
  110. for j in range(len(box_data)):
  111. thickness = 3
  112. left, top, right, bottom = box_data[j][0:4]
  113. draw = ImageDraw.Draw(img)
  114. for i in range(thickness):
  115. draw.rectangle([left + i, top + i, right - i, bottom - i], outline=(255, 255, 255))
  116. img.show()
  117. #对图片进行数据增强后的展示
  118. image_data, box_data = get_random_data(line, [416, 416])
  119. print(box_data)
  120. img = Image.fromarray((image_data * 255).astype(np.uint8))
  121. for j in range(len(box_data)):
  122. thickness = 3
  123. left, top, right, bottom = box_data[j][0:4]
  124. #创建绘制对象
  125. draw = ImageDraw.Draw(img)
  126. for i in range(thickness):
  127. draw.rectangle([left + i, top + i, right - i, bottom - i], outline=(255, 255, 255))
  128. img.show()

发表评论

表情:
评论列表 (有 0 条评论,227人围观)

还没有评论,来说两句吧...

相关阅读