hand.py 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import cv2
  2. import numpy as np
  3. import torch
  4. from scipy.ndimage.filters import gaussian_filter
  5. from skimage.measure import label
  6. from src import util
  7. from src.model import handpose_model
  8. class Hand(object):
  9. def __init__(self, model_path):
  10. self.model = handpose_model()
  11. if torch.cuda.is_available():
  12. self.model = self.model.cuda()
  13. model_dict = util.transfer(self.model, torch.load(model_path))
  14. self.model.load_state_dict(model_dict)
  15. self.model.eval()
  16. def __call__(self, oriImg):
  17. scale_search = [0.5, 1.0, 1.5, 2.0]
  18. # scale_search = [0.5]
  19. boxsize = 368
  20. stride = 8
  21. padValue = 128
  22. thre = 0.05
  23. multiplier = [x * boxsize / oriImg.shape[0] for x in scale_search]
  24. heatmap_avg = np.zeros((oriImg.shape[0], oriImg.shape[1], 22))
  25. # paf_avg = np.zeros((oriImg.shape[0], oriImg.shape[1], 38))
  26. for m in range(len(multiplier)):
  27. scale = multiplier[m]
  28. imageToTest = cv2.resize(oriImg, (0, 0), fx=scale, fy=scale, interpolation=cv2.INTER_CUBIC)
  29. imageToTest_padded, pad = util.padRightDownCorner(imageToTest, stride, padValue)
  30. im = np.transpose(np.float32(imageToTest_padded[:, :, :, np.newaxis]), (3, 2, 0, 1)) / 256 - 0.5
  31. im = np.ascontiguousarray(im)
  32. data = torch.from_numpy(im).float()
  33. if torch.cuda.is_available():
  34. data = data.cuda()
  35. # data = data.permute([2, 0, 1]).unsqueeze(0).float()
  36. with torch.no_grad():
  37. output = self.model(data).cpu().numpy()
  38. # output = self.model(data).numpy()q
  39. # extract outputs, resize, and remove padding
  40. heatmap = np.transpose(np.squeeze(output), (1, 2, 0)) # output 1 is heatmaps
  41. heatmap = cv2.resize(heatmap, (0, 0), fx=stride, fy=stride, interpolation=cv2.INTER_CUBIC)
  42. heatmap = heatmap[:imageToTest_padded.shape[0] - pad[2], :imageToTest_padded.shape[1] - pad[3], :]
  43. heatmap = cv2.resize(heatmap, (oriImg.shape[1], oriImg.shape[0]), interpolation=cv2.INTER_CUBIC)
  44. heatmap_avg += heatmap / len(multiplier)
  45. all_peaks = []
  46. for part in range(21):
  47. map_ori = heatmap_avg[:, :, part]
  48. one_heatmap = gaussian_filter(map_ori, sigma=3)
  49. binary = np.ascontiguousarray(one_heatmap > thre, dtype=np.uint8)
  50. # 全部小于阈值
  51. if np.sum(binary) == 0:
  52. all_peaks.append([0, 0])
  53. continue
  54. label_img, label_numbers = label(binary, return_num=True, connectivity=binary.ndim)
  55. max_index = np.argmax([np.sum(map_ori[label_img == i]) for i in range(1, label_numbers + 1)]) + 1
  56. label_img[label_img != max_index] = 0
  57. map_ori[label_img == 0] = 0
  58. y, x = util.npmax(map_ori)
  59. all_peaks.append([x, y])
  60. return np.array(all_peaks)
  61. if __name__ == "__main__":
  62. hand_estimation = Hand('../model/hand_pose_model.pth')
  63. # test_image = '../images/hand.jpg'
  64. test_image = '../images/hand.jpg'
  65. oriImg = cv2.imread(test_image) # B,G,R order
  66. peaks = hand_estimation(oriImg)
  67. canvas = util.draw_handpose(oriImg, peaks, True)
  68. cv2.imshow('', canvas)
  69. cv2.waitKey(0)