FullyConvolutionalResnet18.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import cv2
  2. import numpy as np
  3. import tensorflow as tf
  4. import torch
  5. from albumentations import (
  6. Compose,
  7. Normalize,
  8. )
  9. from pytorch2keras.converter import pytorch_to_keras
  10. from torch.autograd import Variable
  11. from PyTorchFullyConvolutionalResnet18 import FullyConvolutionalResnet18
  12. def converted_fully_convolutional_resnet18(
  13. input_tensor, pretrained_resnet=True,
  14. ):
  15. # define input tensor
  16. input_var = Variable(torch.FloatTensor(input_tensor))
  17. # get PyTorch ResNet18 model
  18. model_to_transfer = FullyConvolutionalResnet18(pretrained=pretrained_resnet)
  19. model_to_transfer.eval()
  20. # convert PyTorch model to Keras
  21. model = pytorch_to_keras(
  22. model_to_transfer,
  23. input_var,
  24. [input_var.shape[-3:]],
  25. change_ordering=True,
  26. verbose=False,
  27. name_policy="keep",
  28. )
  29. return model
  30. if __name__ == "__main__":
  31. # read ImageNet class ids to a list of labels
  32. with open("imagenet_classes.txt") as f:
  33. labels = [line.strip() for line in f.readlines()]
  34. # read image
  35. original_image = cv2.imread("camel.jpg")
  36. # convert original image to RGB format
  37. image = cv2.cvtColor(original_image, cv2.COLOR_BGR2RGB)
  38. # transform input image:
  39. transform = Compose(
  40. [
  41. Normalize(
  42. # subtract mean
  43. mean=(0.485, 0.456, 0.406),
  44. # divide by standard deviation
  45. std=(0.229, 0.224, 0.225),
  46. ),
  47. ],
  48. )
  49. # apply image transformations, (725, 1920, 3)
  50. image = transform(image=image)["image"]
  51. # NHWC: (1, 725, 1920, 3)
  52. predict_image = tf.expand_dims(image, 0)
  53. # NCHW: (1, 3, 725, 1920)
  54. image = np.transpose(tf.expand_dims(image, 0).numpy(), [0, 3, 1, 2])
  55. # get transferred torch ResNet18 with pre-trained ImageNet weights
  56. model = converted_fully_convolutional_resnet18(
  57. input_tensor=image, pretrained_resnet=True,
  58. )
  59. # Perform inference.
  60. # Instead of a 1×1000 vector, we will get a
  61. # 1×1000×n×m output ( i.e. a probability map
  62. # of size n × m for each 1000 class,
  63. # where n and m depend on the size of the image).
  64. preds = model.predict(predict_image)
  65. # NHWC: (1, 3, 8, 1000) back to NCHW: (1, 1000, 3, 8)
  66. preds = tf.transpose(preds, (0, 3, 1, 2))
  67. preds = tf.nn.softmax(preds, axis=1)
  68. print("Response map shape : ", preds.shape)
  69. # find the class with the maximum score in the n x m output map
  70. pred = tf.math.reduce_max(preds, axis=1)
  71. class_idx = tf.math.argmax(preds, axis=1)
  72. row_max = tf.math.reduce_max(pred, axis=1)
  73. row_idx = tf.math.argmax(pred, axis=1)
  74. col_idx = tf.math.argmax(row_max, axis=1)
  75. predicted_class = tf.gather_nd(
  76. class_idx, (0, tf.gather_nd(row_idx, (0, col_idx[0])), col_idx[0]),
  77. )
  78. # print top predicted class
  79. print("Predicted Class : ", labels[predicted_class], predicted_class)
  80. # find the n × m score map for the predicted class
  81. score_map = tf.expand_dims(preds[0, predicted_class, :, :], 0).numpy()
  82. score_map = score_map[0]
  83. # resize score map to the original image size
  84. score_map = cv2.resize(
  85. score_map, (original_image.shape[1], original_image.shape[0]),
  86. )
  87. # binarize score map
  88. _, score_map_for_contours = cv2.threshold(
  89. score_map, 0.25, 1, type=cv2.THRESH_BINARY,
  90. )
  91. score_map_for_contours = score_map_for_contours.astype(np.uint8).copy()
  92. # Find the contour of the binary blob
  93. contours, _ = cv2.findContours(
  94. score_map_for_contours, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE,
  95. )
  96. # find bounding box around the object.
  97. rect = cv2.boundingRect(contours[0])
  98. # apply score map as a mask to original image
  99. score_map = score_map - np.min(score_map[:])
  100. score_map = score_map / np.max(score_map[:])
  101. score_map = cv2.cvtColor(score_map, cv2.COLOR_GRAY2BGR)
  102. masked_image = (original_image * score_map).astype(np.uint8)
  103. # display bounding box
  104. cv2.rectangle(
  105. masked_image, rect[:2], (rect[0] + rect[2], rect[1] + rect[3]), (0, 0, 255), 2,
  106. )
  107. # display images
  108. cv2.imshow("Original Image", original_image)
  109. cv2.imshow("scaled_score_map", score_map)
  110. cv2.imshow("activations_and_bbox", masked_image)
  111. cv2.waitKey(0)