You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
6.5KB

  1. # The following code was developed by Tim Chinenov
  2. # The script turns a random image into a Vaporwave themed
  3. # image. The program was written in opencv 3.3.1 and python 2.7
  4. # To run the program call the following command in terminal
  5. # python main.py
  6. # To change the image being used, modify code on line 208
  7. import sys
  8. import cv2
  9. import logging
  10. import numpy as np
  11. import random as rd
  12. import os
  13. from functools import partial
  14. import mods
  15. from datetime import datetime
  16. ESCAPE_KEY = 27
  17. logging.basicConfig(level=logging.INFO,
  18. format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
  19. datefmt='%m-%d %H:%M')
  20. logger = logging.getLogger("main")
  21. logger.setLevel(logging.INFO)
  22. # The following function is used to determine the placement of
  23. # text, at the moment it is incomplete
  24. # function takes corners and text
  25. # and resturns top left corner that
  26. # centers text and the angle needed
  27. def pos_and_angle(pts):
  28. # find left top most coordinate
  29. dist = np.inf
  30. # left = pts[0]
  31. for cr in pts:
  32. if (cr[0] ** 2 + cr[1] ** 2) ** 0.5 < dist:
  33. dist = (cr[0] ** 2 + cr[1] ** 2) ** 0.5
  34. # left = cr
  35. # first find angle
  36. return 1
  37. def add_elements(img):
  38. min_elements = 2
  39. max_elements = 4
  40. base_dir = "elements/black/"
  41. all_files = os.listdir(base_dir)
  42. rd.shuffle(all_files)
  43. # randomize number of elements added
  44. num_elements = rd.randint(min_elements, max_elements)
  45. # create a set to prevent element repetition
  46. added_counter = 0
  47. logger.info("Adding %d elements" % (num_elements, ))
  48. for file_name in map(partial(os.path.join, base_dir), all_files):
  49. if added_counter == num_elements:
  50. return
  51. success = add_single_element(img, file_name)
  52. if success:
  53. added_counter += 1
  54. def add_single_element(img, file_name):
  55. imh, imw, imd = img.shape
  56. element = cv2.imread(file_name, -1)
  57. if element is None:
  58. logger.warning("Could not read file %s" % (file_name,))
  59. return False
  60. original_height, original_width, original_depth = element.shape
  61. # adjust size if too big
  62. if original_height > imh * .5 or original_width > imw * .5:
  63. element = cv2.resize(element, (int(.5 * original_width), int(.5 * original_height)))
  64. resized_height, resized_width, _ = element.shape
  65. # refuse to use this image, if this failed
  66. if resized_height > imh or resized_width > imw:
  67. logger.warning("Element %s too big, moving on" % (file_name,))
  68. return False
  69. # get x coord and y coord on the image
  70. from_x_pos = rd.randint(1, imw - resized_width - 1)
  71. from_y_pos = rd.randint(1, imh - resized_height - 1)
  72. # make alpha channel
  73. alpha_s = element[:, :, 2] / 255.0
  74. alpha_1 = 1.0 - alpha_s
  75. for c in range(0, 3):
  76. to_y_pos = from_y_pos + resized_height
  77. to_x_pos = from_x_pos + resized_width
  78. with_alpha_s = alpha_s * element[:, :, c]
  79. with_alpha_1 = alpha_1 * img[from_y_pos:to_y_pos, from_x_pos:to_x_pos, c]
  80. img[from_y_pos:to_y_pos, from_x_pos:to_x_pos, c] = with_alpha_s + with_alpha_1
  81. return True
  82. def main():
  83. # seed the random generator
  84. rd.seed(datetime.now())
  85. # load files for facial and eye cascade
  86. img = vaporize()
  87. cv2.namedWindow("pic", cv2.WINDOW_NORMAL)
  88. cv2.imshow("pic", img)
  89. while cv2.getWindowProperty("pic", cv2.WND_PROP_VISIBLE):
  90. key_code = cv2.waitKey(100)
  91. if key_code == ESCAPE_KEY:
  92. break
  93. elif key_code != -1:
  94. import time
  95. start = time.time()
  96. img = vaporize()
  97. cv2.imshow("pic", img)
  98. end = time.time()
  99. logger.info("Vaporizing and rendering took: %f seconds" % (end-start,))
  100. cv2.destroyAllWindows()
  101. sys.exit()
  102. def vaporize(image_path="testImgs/testface9.png"):
  103. face_cascade = cv2.CascadeClassifier('cascade/haarcascade_frontalface_default.xml')
  104. eye_cascade = cv2.CascadeClassifier('cascade/haarcascade_eye.xml')
  105. # load main image from local file
  106. img = cv2.imread(image_path)
  107. # height, width, depth = img.shape
  108. # turn image gray for detecting face and eyes
  109. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  110. # find all the faces in the image
  111. faces = face_cascade.detectMultiScale(gray, 1.3, 5)
  112. # go through each face
  113. for face in faces:
  114. y = face[1]
  115. x = face[0]
  116. w = face[2]
  117. h = face[3]
  118. roi_gray = gray[y:y + h, x:x + w]
  119. # roi_color = img[y:y + h, x:x + w]
  120. # find each eye. Modify second and third parameter if
  121. # feature detection is poor
  122. eyes = eye_cascade.detectMultiScale(roi_gray, 1.2, 6)
  123. for eye in eyes:
  124. eye[0] += face[0]
  125. eye[1] += face[1]
  126. # randomize which face modification will be performed
  127. eyes_present = len(eyes) >= 2
  128. mod_function, operates_on = mods.determine_face_mod(eyes_present)
  129. if operates_on == mods.EYES:
  130. mod_function(img, eyes)
  131. elif operates_on == mods.FACE:
  132. mod_function(img, face)
  133. # Add elements to image
  134. add_elements(img)
  135. # if there are no faces, just add more elements!
  136. if len(faces) < 1:
  137. add_elements(img)
  138. # randomize if high contrast is used
  139. choice = rd.randint(0, 1)
  140. if choice == 1:
  141. # edit alpha and beta to adjust contrast levels
  142. img = cv2.convertScaleAbs(img, alpha=1.2, beta=35)
  143. # randomize if high noise is used
  144. choice = rd.randint(0, 1)
  145. if choice == 1:
  146. row, col, ch = img.shape
  147. mean = 0
  148. # edit var to modify the amount of noise in the image
  149. var = 15
  150. sigma = var ** 1
  151. gauss = np.random.normal(mean, sigma, (row, col, ch))
  152. gauss = gauss.reshape(row, col, ch)
  153. noisy = (img + gauss)
  154. cv2.normalize(noisy, noisy, 0, 1, cv2.NORM_MINMAX)
  155. img = noisy
  156. # The following code is useful to determine if faces and eyes
  157. # are being read correctly. Uncommenting will draw boxes around
  158. # found features.
  159. # for (x,y,w,h) in faces:
  160. # cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
  161. # roi_gray = gray[y:y+h, x:x+w]
  162. # roi_color = img[y:y+h, x:x+w]
  163. # #edit the second and third parameter if feature detection is poor
  164. # eyes = eye_cascade.detectMultiScale(roi_gray, 1.2, 6)
  165. # for (ex,ey,ew,eh) in eyes:
  166. # cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
  167. return img
  168. if __name__ == "__main__":
  169. main()