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.

201 lines
6.8KB

  1. import math
  2. import cv2
  3. import logging
  4. import numpy as np
  5. import random as rd
  6. NO_MOD = 0
  7. FACE_GLITCH = 1
  8. FACE_DRAG = 2
  9. EYE_CENSOR = 3
  10. EYE_DRAG = 4
  11. EYES = 100
  12. FACE = 101
  13. logger = logging.getLogger("mods")
  14. # The following function is used to determine the placement of
  15. # text, at the moment it is incomplete
  16. # function takes corners and text
  17. # and resturns top left corner that
  18. # centers text and the angle needed
  19. def pos_and_angle(pts):
  20. # find left top most coordinate
  21. dist = np.inf
  22. # left = pts[0]
  23. for cr in pts:
  24. if (cr[0] ** 2 + cr[1] ** 2) ** 0.5 < dist:
  25. dist = (cr[0] ** 2 + cr[1] ** 2) ** 0.5
  26. # left = cr
  27. # first find angle
  28. return 1
  29. def determine_face_mod(eyes_present):
  30. function_list = [
  31. (lambda x, y: x, FACE),
  32. (face_glitch, FACE),
  33. (face_drag, FACE),
  34. (eye_censor, EYES),
  35. (eye_drag, EYES)
  36. ]
  37. function_index = rd.randint(0, 4) if eyes_present else rd.randint(0, 2)
  38. return function_list[function_index]
  39. def eye_drag(img, eyes):
  40. # make sure there are only two eyes per face
  41. if len(eyes) > 2:
  42. eye1 = eyes[0]
  43. eye2 = eyes[0]
  44. size = 0
  45. for itr in range(0, len(eyes)):
  46. if eyes[itr][2] * eyes[itr][3] > size:
  47. size = eyes[itr][2] * eyes[itr][3]
  48. eye1 = eyes[itr]
  49. size = 0
  50. for itr in range(0, len(eyes)):
  51. if eyes[itr][2] * eyes[itr][3] > size and not np.array_equal(eyes[itr], eye1):
  52. size = eyes[itr][2] * eyes[itr][3]
  53. eye2 = eyes[itr]
  54. eyes = [eye1, eye2]
  55. # there should only be two eyes now
  56. for eye in eyes:
  57. # find width of eye
  58. iwid = eye[2]
  59. strp = int(round(iwid / 20.))
  60. num_glitches = int(eye[2] / strp)
  61. line = rd.randint(1, eye[3])
  62. line += eye[1]
  63. line = int(eye[1] + eye[3] / 2)
  64. for itr in range(0, num_glitches):
  65. # edit the second parameter to change eye drop chance
  66. drop = rd.randint(10, 200)
  67. # if the line drop is too low, shorten it
  68. if line + drop > img.shape[0]:
  69. drop = img.shape[0] - line
  70. img[line:line + drop, eye[0] + itr * strp:eye[0] + itr * strp + strp] = \
  71. img[line, eye[0] + itr * strp:eye[0] + itr * strp + strp]
  72. def eye_censor(img, eyes):
  73. if len(eyes) < 2:
  74. logger.warning("Failed to generate censor, less than two eyes present")
  75. return
  76. # cenH = 40
  77. # get centroids of eyes
  78. c1 = np.array([eyes[0][0] + eyes[0][2] / 2.0, eyes[0][1] + eyes[0][3] / 2.0])
  79. c2 = np.array([eyes[1][0] + eyes[1][2] / 2.0, eyes[1][1] + eyes[1][3] / 2.0])
  80. # find the corners of the bar
  81. # find vector of the two centroids
  82. vec = c1 - c2
  83. # unitize vector
  84. vec = vec / (vec[0] ** 2.0 + vec[1] ** 2.0) ** 0.5
  85. # perpendicular vector
  86. per_vec = np.array([vec[1], vec[0] * (-1)])
  87. # change these value to adjust height and width of
  88. # censor bar
  89. w_ex = 40
  90. mag = 75
  91. cr1 = per_vec * w_ex + c1
  92. cr2 = c1 - per_vec * w_ex
  93. cr3 = per_vec * w_ex + c2
  94. cr4 = c2 - per_vec * w_ex
  95. cr1 += vec * mag
  96. cr2 += vec * mag
  97. cr3 -= vec * mag
  98. cr4 -= vec * mag
  99. # round all values
  100. pts = np.array([cr1, cr2, cr4, cr3])
  101. cv2.fillPoly(img, np.array([pts], dtype=np.int32), (0, 0, 0))
  102. #########################################################
  103. # The following code is incomplete. It's purpose is to randomly
  104. # add text to the censor bar
  105. # roll to see if to add text
  106. # textc = rd.randint(0,2)
  107. # textc = 1
  108. # if textc == 1:
  109. # text = open("elements/censor.txt","r")
  110. # allText = text.read()
  111. # possText = allText.split(";")
  112. # dec = rd.randint(0,len(possText))
  113. # use = possText[dec]
  114. # #calculate text position and angle
  115. # # info = posAndAngle(pts,use)
  116. # font = cv2.FONT_HERSHEY_SIMPLEX
  117. # cv2.putText(img,use,(int(cr1[0]),int(cr1[1])), font, 1,(255,255,255),2,cv2.LINE_AA)
  118. ############################################################
  119. def face_drag(img, face):
  120. h, w, d = img.shape
  121. # 0 is horizontal 1 is veritical
  122. ornt = rd.randint(0, 2)
  123. if ornt == 0:
  124. line = rd.randint(face[1] + 25, face[1] + face[3] - 25)
  125. # 0 is up 1 is down
  126. direction = rd.randint(0, 2)
  127. if direction == 0:
  128. img[0:line, face[0]:face[0] + face[2]] = img[line, face[0]:face[0] + face[2]]
  129. else:
  130. img[line:h, face[0]:face[0] + face[2]] = img[line, face[0]:face[0] + face[2]]
  131. else:
  132. line = rd.randint(face[0] + 25, face[0] + face[2] - 25)
  133. # 0 is left 1 is right
  134. direction = rd.randint(0, 2)
  135. if direction == 0:
  136. img[face[1]:face[1] + face[3], 0:line] = img[face[1]:face[1] + face[3], line:line + 1]
  137. else:
  138. img[face[1]:face[1] + face[3], line:w] = img[face[1]:face[1] + face[3], line:line + 1]
  139. def face_glitch(img, face):
  140. height, width, d = img.shape
  141. # pixels segments of 40
  142. div = rd.randint(10, 100)
  143. strp = int(round(face[3] / (div * 1.0)))
  144. num_glitches = face[3] / strp
  145. if type(num_glitches) == np.float64:
  146. num_glitches = math.floor(num_glitches)
  147. for itr in range(0, num_glitches):
  148. # play with the second parameter to increase "glitchiness"
  149. rng = rd.randint(15, 100)
  150. right_ext = face[0] + face[2] + rng
  151. left_ext = face[0] + face[2] - rng
  152. # make sure extremes don't go out of bounds
  153. if left_ext < 0:
  154. left_ext = 0
  155. if right_ext >= width:
  156. right_ext = width
  157. # randomize static direction
  158. # 1 moves left, 2 moves right
  159. dec = rd.randint(1, 2)
  160. back_bound = face[0] + rng
  161. if dec % 2 == 0:
  162. diff = 0
  163. # make corrections if glitch falls outside of image
  164. if face[0] + face[2] + rng >= width:
  165. diff = face[0] + face[2] + rng - width
  166. img[face[1] + (itr * strp):face[1] + (itr * strp + strp), (face[0] + rng):right_ext] = \
  167. img[face[1] + (itr * strp):face[1] + (itr * strp + strp), face[0]:face[0] + face[2] - diff]
  168. else:
  169. diff = 0
  170. # make corrections if glitch falls outside of image
  171. if back_bound < 0:
  172. diff = abs(back_bound)
  173. back_bound = 0
  174. old = img[face[1] + (itr * strp):face[1] + (itr * strp + strp), back_bound:left_ext]
  175. new = img[face[1] + (itr * strp):face[1] + (itr * strp + strp), face[0]:face[0] + face[2] - diff]
  176. if old.shape != new.shape:
  177. logger.warning("Shape mismatch: %s vs %s" % (old.shape, new.shape, ))
  178. return
  179. img[face[1] + (itr * strp):face[1] + (itr * strp + strp), back_bound:left_ext] = \
  180. img[face[1] + (itr * strp):face[1] + (itr * strp + strp), face[0]:face[0] + face[2] - diff]