image.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. Created on Thu Sep 9 23:11:51 2020
  5. image
  6. @author: chineseocr
  7. """
  8. import json
  9. import base64
  10. import random
  11. import numpy as np
  12. import six
  13. import cv2
  14. from PIL import Image
  15. Image.MAX_IMAGE_PIXELS = 2300000000
  16. from numpy import cos,sin,pi
  17. from matplotlib.colors import rgb_to_hsv, hsv_to_rgb
  18. def plot_lines(img,lines,linetype=2):
  19. tmp = np.copy(img)
  20. for line in lines:
  21. p1,p2 = line
  22. cv2.line(tmp,(int(p1[0]),int(p1[1])),(int(p2[0]),int(p2[1])),(0,0,0),linetype,lineType=cv2.LINE_AA)
  23. return Image.fromarray(tmp)
  24. def base64_to_PIL(string):
  25. try:
  26. # my own train data
  27. string = bytes(string, 'utf-8')
  28. base64_data = base64.b64decode(string)
  29. # with open('temp.jpg', 'wb') as f:
  30. # f.write(base64_data)
  31. # print("base64_to_PIL")
  32. buf = six.BytesIO()
  33. buf.write(base64_data)
  34. buf.seek(0)
  35. img = Image.open(buf).convert('RGB')
  36. return img
  37. except Exception as e:
  38. print(e)
  39. return None
  40. def read_json(p):
  41. with open(p) as f:
  42. jsonData = json.loads(f.read())
  43. shapes = jsonData.get('shapes')
  44. imageData = jsonData.get('imageData')
  45. lines = []
  46. labels = []
  47. for shape in shapes:
  48. lines.append(shape['points'])
  49. [x0, y0], [x1, y1] = shape['points']
  50. label = shape['label']
  51. if label == '0':
  52. if abs(y1-y0) > 500:
  53. label = '1'
  54. # else:
  55. # print("image read_json y<50", x0, y0, x1, y1, label)
  56. elif label == '1':
  57. if abs(x1-x0) > 500:
  58. label = '0'
  59. # else:
  60. # print("image read_json x<50", x0, y0, x1, y1, label)
  61. labels.append(label)
  62. img = base64_to_PIL(imageData)
  63. return img, lines, labels
  64. def rotate(x, y, angle, cx, cy):
  65. """
  66. 点(x,y) 绕(cx,cy)点旋转
  67. """
  68. angle = angle*pi/180
  69. x_new = (x-cx)*cos(angle) - (y-cy)*sin(angle)+cx
  70. y_new = (x-cx)*sin(angle) + (y-cy)*cos(angle)+cy
  71. return x_new, y_new
  72. def box_rotate(box, angle=0, imgH=0, imgW=0):
  73. """
  74. 对坐标进行旋转 逆时针方向 0\90\180\270,
  75. """
  76. x1, y1, x2, y2, x3, y3, x4, y4 = box[:8]
  77. if angle == 90:
  78. x1_, y1_ = y2, imgW-x2
  79. x2_, y2_ = y3, imgW-x3
  80. x3_, y3_ = y4, imgW-x4
  81. x4_, y4_ = y1, imgW-x1
  82. elif angle == 180:
  83. x1_, y1_ = imgW-x3, imgH-y3
  84. x2_, y2_ = imgW-x4, imgH-y4
  85. x3_, y3_ = imgW-x1, imgH-y1
  86. x4_, y4_ = imgW-x2, imgH-y2
  87. elif angle == 270:
  88. x1_, y1_ = imgH-y4, x4
  89. x2_, y2_ = imgH-y1, x1
  90. x3_, y3_ = imgH-y2, x2
  91. x4_, y4_ = imgH-y3, x3
  92. else:
  93. x1_, y1_, x2_, y2_, x3_, y3_, x4_, y4_ = x1, y1, x2, y2, x3, y3, x4, y4
  94. return (x1_, y1_, x2_, y2_, x3_, y3_, x4_, y4_)
  95. def angle_transpose(p, angle, w, h):
  96. x, y = p
  97. if angle == 90:
  98. x, y = y, w-x
  99. elif angle == 180:
  100. x, y = w-x, h-y
  101. elif angle == 270:
  102. x, y = h-y, x
  103. return x, y
  104. def img_argument(img, lines, labels, size=(512, 512)):
  105. w, h = img.size
  106. # 80%几率进行旋转-5~5度
  107. if np.random.randint(0, 100) > 80:
  108. degree = np.random.uniform(-5, 5)
  109. else:
  110. degree = 0
  111. # degree = np.random.uniform(-5,5)
  112. # 旋转线条
  113. newlines = []
  114. for line in lines:
  115. p1, p2 = line
  116. p1 = rotate(p1[0], p1[1], degree, w/2, h/2)
  117. p2 = rotate(p2[0], p2[1], degree, w/2, h/2)
  118. newlines.append([p1, p2])
  119. # img = img.rotate(-degree,center=(w/2,h/2),resample=Image.BILINEAR,fillcolor=(128,128,128))
  120. # 旋转图片
  121. img = img.rotate(-degree, center=(w/2, h/2), resample=Image.BILINEAR)
  122. # 随机选择90度倍数旋转
  123. angle = np.random.choice([0, 90, 180, 270], 1)[0]
  124. newlables = []
  125. # 旋转线条
  126. for i in range(len(newlines)):
  127. p1, p2 = newlines[i]
  128. p1 = angle_transpose(p1, angle, w, h)
  129. p2 = angle_transpose(p2, angle, w, h)
  130. newlines[i] = [p1, p2]
  131. # 旋转角度为90,270度时,横竖线的Label互换
  132. if angle in [90, 270]:
  133. if labels[i] == '0':
  134. newlables.append('1')
  135. else:
  136. newlables.append('0')
  137. else:
  138. newlables.append(labels[i])
  139. # 旋转图片
  140. if angle == 90:
  141. img = img.transpose(Image.ROTATE_90)
  142. elif angle == 180:
  143. img = img.transpose(Image.ROTATE_180)
  144. elif angle == 270:
  145. img = img.transpose(Image.ROTATE_270)
  146. return img, newlines, newlables
  147. def fill_lines(img, lines, linetype=2):
  148. tmp = np.copy(img)
  149. for line in lines:
  150. p1, p2 = line
  151. cv2.line(tmp, (int(p1[0]), int(p1[1])), (int(p2[0]), int(p2[1])),
  152. 255, linetype, lineType=cv2.LINE_AA)
  153. return tmp
  154. def get_img_label_origin(p,size,linetype=1):
  155. img,lines,labels = read_json(p)
  156. img,lines=img_resize_origin(img,lines,target_size=512,max_size=1024)
  157. img,lines,labels =img_argument(img,lines,labels,size)
  158. img,lines,labels=get_random_data(img,lines,labels, size=size)
  159. lines = np.array(lines)
  160. labels = np.array(labels)
  161. labelImg0 = np.zeros(size[::-1],dtype='uint8')
  162. labelImg1 = np.zeros(size[::-1],dtype='uint8')
  163. ind = np.where(labels=='0')[0]
  164. labelImg0 = fill_lines(labelImg0,lines[ind],linetype=linetype)
  165. ind = np.where(labels=='1')[0]
  166. labelImg1 = fill_lines(labelImg1,lines[ind],linetype=linetype)
  167. labelY = np.zeros((size[1],size[0],2),dtype='uint8')
  168. labelY[:,:,0] = labelImg0
  169. labelY[:,:,1] = labelImg1
  170. cv2.imshow("get_img_label", labelImg1)
  171. cv2.waitKey(0)
  172. cv2.imshow("get_img_label", labelImg0)
  173. cv2.waitKey(0)
  174. labelY = labelY>0
  175. return np.array(img),lines,labelY
  176. def gen_origin(paths,batchsize=2,linetype=2):
  177. num =len(paths)
  178. i=0
  179. while True:
  180. #sizes = [512,512,512,512,640,1024] ##多尺度训练
  181. #size = np.random.choice(sizes,1)[0]
  182. size = 640
  183. X = np.zeros((batchsize,size,size,3))
  184. Y = np.zeros((batchsize,size,size,2))
  185. for j in range(batchsize):
  186. if i>=num:
  187. i=0
  188. np.random.shuffle(paths)
  189. p = paths[i]
  190. i+=1
  191. #linetype=2
  192. img,lines,labelImg=get_img_label_origin(p,size=(size,size),linetype=linetype)
  193. cv2.imshow("gen", img)
  194. cv2.waitKey(0)
  195. print("gen image size", img.shape)
  196. X[j] = img
  197. Y[j] = labelImg
  198. yield X,Y
  199. def get_img_label(p, size, linetype=1):
  200. # 读取json格式数据
  201. img, lines, labels = read_json(p)
  202. # if img.size[1] > 1200:
  203. # return np.array([]), np.array([]), np.array([]), np.array([])
  204. height, width = size
  205. # width, height = img.size
  206. # size = np.array(img).shape[:-1]
  207. # print("get_img_label origin image_PIL size", img.size)
  208. # 图片缩放
  209. img, lines = img_resize(img, lines, (height, width))
  210. # img, lines = img_resize(img, lines, target_size=size, max_size=1024)
  211. # print("get_img_label train image_PIL size", img.size)
  212. # print("get_img_label train image_np shape", np.array(img).shape)
  213. # 图片增强(各种角度旋转)
  214. # img, lines, labels = img_argument(img, lines, labels, size)
  215. # print("shape3", np.array(img).shape)
  216. # 图片轻微缩放 + 图片失真
  217. # img, lines, labels = get_random_data(img, lines, labels, size=size)
  218. lines = np.array(lines)
  219. labels = np.array(labels)
  220. # size (640, 640) 将size的两个值倒过来
  221. # labelImg0 = np.zeros(size[::-1], dtype='uint8')
  222. # labelImg1 = np.zeros(size[::-1], dtype='uint8')
  223. labelImg0 = np.zeros((height, width), dtype='uint8')
  224. labelImg1 = np.zeros((height, width), dtype='uint8')
  225. # print("get_img_label np zero shape", labelImg0.shape, (height, width))
  226. # 在空图片上画线
  227. ind = np.where(labels == '0')[0]
  228. labelImg0 = fill_lines(labelImg0, lines[ind], linetype=linetype)
  229. ind = np.where(labels == '1')[0]
  230. labelImg1 = fill_lines(labelImg1, lines[ind], linetype=linetype)
  231. # print("label image shape", labelImg0.shape, labelImg1.shape)
  232. # 将只有横竖线的图片堆叠
  233. labelY = np.zeros((height, width, 2), dtype='uint8')
  234. labelY[:, :, 0] = labelImg0
  235. labelY[:, :, 1] = labelImg1
  236. # cv2.imshow("img", np.array(img))
  237. # cv2.imshow("get_img_label", labelImg1)
  238. # cv2.imshow("get_img_label1", labelImg0)
  239. # cv2.waitKey(0)
  240. # print("get_img_label label col size", labelImg1.shape)
  241. # print("get_img_label label row size", labelImg0.shape)
  242. # 对每个像素点进行二分类
  243. labelY = labelY > 0
  244. return np.array(img), lines, labelY, (height, width)
  245. def get_img_label1(p, linetype=1):
  246. # 读取json格式数据
  247. img, lines, labels = read_json(p)
  248. width, height = img.size
  249. lines = np.array(lines)
  250. labels = np.array(labels)
  251. labelImg0 = np.zeros((height, width), dtype='uint8')
  252. labelImg1 = np.zeros((height, width), dtype='uint8')
  253. # 在空图片上画线
  254. ind = np.where(labels == '0')[0]
  255. labelImg0 = fill_lines(labelImg0, lines[ind], linetype=linetype)
  256. ind = np.where(labels == '1')[0]
  257. labelImg1 = fill_lines(labelImg1, lines[ind], linetype=linetype)
  258. # 将只有横竖线的图片堆叠
  259. labelY = np.zeros((height, width, 2), dtype='uint8')
  260. labelY[:, :, 0] = labelImg0
  261. labelY[:, :, 1] = labelImg1
  262. cv2.imshow("get_img_label", labelImg1)
  263. cv2.waitKey(0)
  264. cv2.imshow("get_img_label", labelImg0)
  265. cv2.waitKey(0)
  266. # 对每个像素点进行二分类
  267. labelY = labelY > 0
  268. return np.array(img), lines, labelY, (height, width)
  269. def rand(a=0., b=1.):
  270. # rand(): [0-1)
  271. return np.random.rand()*(b-a) + a
  272. def get_random_data(image, lines, labels, size=(1024, 1024), jitter=.3,
  273. hue=.1, sat=1.5, val=1.5):
  274. """
  275. random preprocessing for real-time data augmentation
  276. """
  277. iw, ih = image.size
  278. # resize image
  279. w, h = size
  280. new_ar = w/h * rand(1-jitter, 1+jitter) / rand(1-jitter, 1+jitter)
  281. # scale = rand(.2, 2)
  282. scale = rand(0.2, 3)
  283. if new_ar < 1:
  284. nh = int(scale*h)
  285. nw = int(nh*new_ar)
  286. else:
  287. nw = int(scale*w)
  288. nh = int(nw/new_ar)
  289. image = image.resize((nw, nh), Image.BICUBIC)
  290. # 将原图粘贴到另一张空白图上
  291. dx = int(rand(0, w-nw))
  292. dy = int(rand(0, h-nh))
  293. new_image = Image.new('RGB', (w, h), (128, 128, 128))
  294. new_image.paste(image, (dx, dy))
  295. image = new_image
  296. # 图片失真
  297. hue = rand(-hue, hue)
  298. sat = rand(1, sat) if rand() < .5 else 1/rand(1, sat)
  299. val = rand(1, val) if rand() < .5 else 1/rand(1, val)
  300. x = rgb_to_hsv(np.array(image)/255.)
  301. x[..., 0] += hue
  302. x[..., 0][x[..., 0] > 1] -= 1
  303. x[..., 0][x[..., 0] < 0] += 1
  304. x[..., 1] *= sat
  305. x[..., 2] *= val
  306. x[x > 1] = 1
  307. x[x < 0] = 0
  308. # numpy array, 0 to 1
  309. image_data = hsv_to_rgb(x)
  310. N = len(lines)
  311. for i in range(N):
  312. p1, p2 = lines[i]
  313. p1 = p1[0]*nw/iw+dx, p1[1]*nh/ih + dy
  314. p2 = p2[0]*nw/iw+dx, p2[1]*nh/ih + dy
  315. lines[i] = [p1, p2]
  316. return image_data, lines, labels
  317. def gen2(paths, batchsize=2, linetype=2):
  318. num = len(paths)
  319. i = 0
  320. while True:
  321. # 多尺度训练
  322. sizes = [1152, 1024, 1280, 896, 768, 640, 1024]
  323. # size = np.random.choice(sizes, 1)[0]
  324. # height = np.random.choice(sizes, 1)[0]
  325. # width = int(height/1.4)
  326. heights = [1024, 896, 768, 640]
  327. widths = [768, 640, 512, 384]
  328. height = np.random.choice(heights, 1)[0]
  329. width = np.random.choice(widths, 1)[0]
  330. # height = 1024
  331. # width = 768
  332. # size = (1024, 512)
  333. X = np.zeros((batchsize, height, width, 3))
  334. Y = np.zeros((batchsize, height, width, 2))
  335. for j in range(batchsize):
  336. if i >= num:
  337. i = 0
  338. np.random.shuffle(paths)
  339. p = paths[i]
  340. i += 1
  341. # linetype=2
  342. print("gen input size", (width, height))
  343. img, lines, labelImg = get_img_label(p, size=(width, height),
  344. linetype=linetype)
  345. # 高斯模糊
  346. # sigmaX = random.randint(1, 10)
  347. # sigmaY = random.randint(1, 10)
  348. # img = cv2.GaussianBlur(img, (5, 5), sigmaX, sigmaY)
  349. cv2.imshow("gen", img)
  350. cv2.waitKey(0)
  351. print("gen image size", img.shape)
  352. X[j] = img
  353. Y[j] = labelImg
  354. yield X, Y
  355. def gen(paths, batchsize=2, linetype=2, is_test=False):
  356. num = len(paths)
  357. i = 0
  358. while True:
  359. # 多尺度训练
  360. sizes = [1152, 1024, 1280, 896, 768, 640, 1024]
  361. # size = np.random.choice(sizes, 1)[0]
  362. # height = np.random.choice(sizes, 1)[0]
  363. # width = int(height/1.4)
  364. # heights = [1024, 896, 768, 640, 512, 384, 256, 128]
  365. # widths = [1024, 896, 768, 640, 512, 384, 256, 128]
  366. # heights = [3008, 2944, 2880, 2816, 2752, 2688, 2624, 2560, 2496, 2432, 2368,
  367. # 2304, 2240, 2176, 2112, 2048, 1984, 1920, 1856, 1792, 1728, 1664,
  368. # 1600, 1536, 1472, 1408, 1344, 1280, 1216, 1152, 1088, 1024, 960,
  369. # 896, 832, 768, 704, 640, 576, 512]
  370. # widths = [2048, 1984, 1920, 1856, 1792, 1728, 1664,
  371. # 1600, 1536, 1472, 1408, 1344, 1280, 1216, 1152, 1088, 1024, 960,
  372. # 896, 832, 768, 704, 640, 576, 512]
  373. heights = [1280, 1216, 1152, 1088, 1024, 960,
  374. 896, 832, 768, 704, 640, 576, 512]
  375. widths = [1088, 1024, 960, 896, 832, 768, 704, 640, 576, 512]
  376. height = np.random.choice(heights, 1)[0]
  377. width = np.random.choice(widths, 1)[0]
  378. # height = 1024
  379. # width = 768
  380. # size = (1024, 512)
  381. # print("gen batch shape", height, width)
  382. X = np.zeros((batchsize, height, width, 3))
  383. Y = np.zeros((batchsize, height, width, 2))
  384. for j in range(batchsize):
  385. if i >= num:
  386. i = 0
  387. np.random.shuffle(paths)
  388. p = paths[i]
  389. i += 1
  390. # linetype=2
  391. # print("gen input size", (height, width))
  392. img, lines, labels = read_json(p)
  393. img_np = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
  394. # limit pixels 89478485
  395. if img_np.shape[0] * img_np.shape[1] * img_np.shape[2] >= 89478485:
  396. print("image too large, limit 89478485 pixels", img_np.shape)
  397. new_i = random.randint(0, num-1)
  398. if i != new_i:
  399. p = paths[new_i]
  400. if is_test:
  401. height, width = get_best_predict_size(img_np)
  402. X = np.zeros((batchsize, height, width, 3))
  403. Y = np.zeros((batchsize, height, width, 2))
  404. img, lines, labelImg, size = get_img_label(p, size=(height, width),
  405. linetype=linetype)
  406. # if not img.any():
  407. # print("image too large, jump")
  408. # continue
  409. # limit pixels 89478485
  410. # if img.shape[0] * img.shape[1] * img.shape[2] >= 89478485:
  411. # print("image too large, limit 89478485 pixels", img.shape)
  412. # continue
  413. # height, width = size
  414. # X = np.zeros((batchsize, height, width, 3))
  415. # Y = np.zeros((batchsize, height, width, 2))
  416. # if_blur = np.random.choice([0, 1], 1)[0]
  417. # if if_blur and "8" in p:
  418. # # 高斯模糊
  419. # sigmaX = random.randint(1, 3)
  420. # sigmaY = random.randint(1, 3)
  421. # img = cv2.GaussianBlur(img, (5, 5), sigmaX, sigmaY)
  422. # cv2.imshow("gen", img)
  423. # cv2.waitKey(0)
  424. # print("gen image size", img.shape)
  425. # cv2.imshow("gen", labelImg[:, :, 0])
  426. # cv2.waitKey(0)
  427. # print("gen label image size", labelImg[:, :, 0])
  428. X[j] = img
  429. Y[j] = labelImg
  430. # print("X.shape", X.shape)
  431. yield X, Y, img_np
  432. def get_best_predict_size(image_np, times=64):
  433. sizes = []
  434. for i in range(1, 100):
  435. if i*times <= 1300:
  436. sizes.append(i*times)
  437. sizes.sort(key=lambda x: x, reverse=True)
  438. min_len = 10000
  439. best_height = sizes[0]
  440. for height in sizes:
  441. if abs(image_np.shape[0] - height) < min_len:
  442. min_len = abs(image_np.shape[0] - height)
  443. best_height = height
  444. min_len = 10000
  445. best_width = sizes[0]
  446. for width in sizes:
  447. if abs(image_np.shape[1] - width) < min_len:
  448. min_len = abs(image_np.shape[1] - width)
  449. best_width = width
  450. return best_height, best_width
  451. def gen1(paths, batchsize=2, linetype=2):
  452. num = len(paths)
  453. i = 0
  454. while True:
  455. batchsize = 1
  456. for j in range(batchsize):
  457. if i >= num:
  458. i = 0
  459. np.random.shuffle(paths)
  460. p = paths[i]
  461. i += 1
  462. img, lines, labelImg, size = get_img_label(p, linetype=linetype)
  463. height, width = size
  464. X = np.zeros((batchsize, height, width, 3))
  465. Y = np.zeros((batchsize, height, width, 2))
  466. if_blur = np.random.choice([0, 1], 1)[0]
  467. if if_blur:
  468. # 高斯模糊
  469. sigmaX = random.randint(1, 3)
  470. sigmaY = random.randint(1, 3)
  471. img = cv2.GaussianBlur(img, (5, 5), sigmaX, sigmaY)
  472. print("gen image size", img.shape)
  473. cv2.imshow("gen", img)
  474. cv2.waitKey(0)
  475. # cv2.imshow("gen", labelImg[:, :, 0])
  476. # cv2.waitKey(0)
  477. # print("gen label image size", labelImg[:, :, 0].shape)
  478. X[j] = img
  479. Y[j] = labelImg
  480. yield X, Y
  481. def img_resize(im, lines, target_size, max_size=None):
  482. w, h = im.size
  483. h_t, w_t = target_size
  484. # print("img_resize", im.size, target_size)
  485. # im_size_min = np.min(im.size)
  486. # im_size_max = np.max(im.size)
  487. im_scale_w = float(w_t)/float(w)
  488. im_scale_h = float(h_t)/float(h)
  489. im = im.resize((int(w_t), int(h_t)), Image.BICUBIC)
  490. N = len(lines)
  491. for i in range(N):
  492. p1, p2 = lines[i]
  493. p1 = p1[0]*im_scale_w, p1[1]*im_scale_h
  494. p2 = p2[0]*im_scale_w, p2[1]*im_scale_h
  495. lines[i] = [p1, p2]
  496. return im, lines
  497. def img_resize_origin(im,lines,target_size=600,max_size=1500):
  498. w,h = im.size
  499. im_size_min = np.min(im.size)
  500. im_size_max = np.max(im.size)
  501. im_scale = float(target_size)/float(im_size_min)
  502. if max_size is not None:
  503. if np.round(im_scale * im_size_max) > max_size:
  504. im_scale = float(max_size)/float(im_size_max)
  505. im = im.resize((int(w*im_scale),int(h*im_scale)),Image.BICUBIC)
  506. N = len(lines)
  507. for i in range(N):
  508. p1,p2 = lines[i]
  509. p1 = p1[0]*im_scale,p1[1]*im_scale
  510. p2 = p2[0]*im_scale,p2[1]*im_scale
  511. lines[i] = [p1,p2]
  512. return im, lines
  513. def img_resize_by_padding_crop(im, lines, target_size):
  514. w, h = im.size
  515. h_t, w_t = target_size
  516. # print("img_resize_by_padding_crop", im.size, target_size)
  517. # PIL -> CV2
  518. img = cv2.cvtColor(np.asarray(im), cv2.COLOR_RGB2BGR)
  519. # print("img_resize_by_padding_crop image_np shape0", img.shape)
  520. # 图像边缘扩充/裁剪
  521. change_w_flag = 0
  522. change_h_flag = 0
  523. if w_t >= w and h_t >= h:
  524. change_height = int((h_t - h)/2)
  525. change_width = int((w_t - w)/2)
  526. img = cv2.copyMakeBorder(img, change_height, change_height, change_width,
  527. change_width, cv2.BORDER_CONSTANT, value=(255, 255, 255))
  528. change_w_flag = 1
  529. change_h_flag = 1
  530. # print("img_resize_by_padding_crop 1 1")
  531. elif w_t >= w:
  532. change_width = int((w_t - w)/2)
  533. change_height = int((h - h_t)/2)
  534. img = cv2.copyMakeBorder(img, 0, 0, change_width,
  535. change_width, cv2.BORDER_CONSTANT, value=(255, 255, 255))
  536. img = img[change_height:h-change_height, :]
  537. change_w_flag = 1
  538. change_h_flag = -1
  539. # print("img_resize_by_padding_crop 1 -1")
  540. elif h_t >= h:
  541. change_height = int((h_t - h)/2)
  542. change_width = int((w - w_t)/2)
  543. img = cv2.copyMakeBorder(img, change_height, change_height, 0,
  544. 0, cv2.BORDER_CONSTANT, value=(255, 255, 255))
  545. img = img[:, change_width:w-change_width]
  546. change_w_flag = -1
  547. change_h_flag = 1
  548. # print("img_resize_by_padding_crop -1 1")
  549. else:
  550. if abs(h - h_t) % 2 != 0:
  551. change_height = int((h - h_t)/2)
  552. change_height += 1
  553. else:
  554. change_height = int((h - h_t)/2)
  555. if abs(w - w_t) % 2 != 0:
  556. change_width = int((w - w_t)/2)
  557. change_width += 1
  558. else:
  559. change_width = int((w - w_t)/2)
  560. img = img[change_height:h-change_height, change_width:w-change_width]
  561. change_w_flag = -1
  562. change_h_flag = -1
  563. # print("img_resize_by_padding_crop -1 -1")
  564. # print("img_resize_by_padding_crop image_np shape1", img.shape)
  565. # image shape 和 target大小不同
  566. if img.shape[0] < h_t:
  567. img = cv2.copyMakeBorder(img, h_t-img.shape[0], 0, 0,
  568. 0, cv2.BORDER_CONSTANT, value=(255, 255, 255))
  569. if img.shape[1] < w_t:
  570. img = cv2.copyMakeBorder(img, 0, 0, w_t-img.shape[1],
  571. 0, cv2.BORDER_CONSTANT, value=(255, 255, 255))
  572. if img.shape[0] > h_t:
  573. img = img[:h_t, :, :]
  574. if img.shape[1] > w_t:
  575. img = img[:, :w_t, :]
  576. # print("img_resize_by_padding_crop image_np shape2", img.shape)
  577. # CV2 -> PIL
  578. im = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
  579. N = len(lines)
  580. for i in range(N):
  581. p1, p2 = lines[i]
  582. p1 = p1[0] + change_w_flag * change_width, p1[1] + change_h_flag * change_height
  583. p2 = p2[0] + change_w_flag * change_width, p2[1] + change_h_flag * change_height
  584. lines[i] = [p1, p2]
  585. return im, lines
  586. if __name__ == '__main__':
  587. img, lines, labels = read_json("C:/Table_Label/clean_data/4500_fef19096cb171226c3be271fed4dd739.json")
  588. img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
  589. cv2.namedWindow("img", 0)
  590. cv2.resizeWindow("img", 1000, 800)
  591. cv2.imshow("img", img)
  592. cv2.waitKey(0)