您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

287 行
9.7KB

  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 cv2
  8. import matplotlib as plt
  9. import numpy as np
  10. import random as rd
  11. import os
  12. from datetime import datetime
  13. #The following function is used to determine the placement of
  14. #text, at the moment it is incomplete
  15. #function takes corners and text
  16. # and resturns top left corner that
  17. # centers text and the angle needed
  18. def posAndAngle(pts,text):
  19. #find left top most coordinate
  20. dist = np.inf
  21. left = pts[0]
  22. for cr in pts:
  23. if (cr[0]**2+cr[1]**2)**0.5 < dist:
  24. dist = (cr[0]**2+cr[1]**2)**0.5
  25. left = cr
  26. #first find angle
  27. return 1;
  28. def addElements(img):
  29. #get the number of elements
  30. allfiles = os.listdir("elements/black/")
  31. numFiles = len(allfiles)
  32. #get dimensions of main image
  33. imh,imw,imd = img.shape
  34. #randomize number of elements added
  35. numElements = rd.randint(2,4)
  36. #create a set to prevent element repetition
  37. usedels = set({})
  38. for num in range(numElements):
  39. file_name = "elements/black/ele_b"
  40. choice = rd.randint(1,numFiles)
  41. usedels.add(choice)
  42. #run again if element has been used already
  43. while choice not in usedels:
  44. choice = rd.randint(1,numFiles)
  45. file_name += str(choice) + ".png"
  46. element = cv2.imread(file_name,-1)
  47. if element is None:
  48. print(file_name+ " failed to load image")
  49. continue
  50. h,w,d = element.shape
  51. #adjust size if too big
  52. if h > imh*.5 or w > imw*.5:
  53. element = cv2.resize(element,(int(.5*w),int(.5*h)))
  54. h,w,d = element.shape
  55. #refuse to use this image, if this failed
  56. if h > imh or w > imw:
  57. print("Element too big, moving on")
  58. continue
  59. #get x coord and y coord on the image
  60. xpos = rd.randint(1,imw-w-1)
  61. ypos = rd.randint(1,imh-h-1)
  62. #make alpha channel
  63. alpha_s = element[:,:,2]/255.0
  64. alpha_1 = 1.0 - alpha_s
  65. for c in range(0,3):
  66. img[ypos:ypos+h,xpos:xpos+w,c] = (alpha_s*element[:,:,c]+alpha_1*img[ypos:ypos+h,xpos:xpos+w,c])
  67. def faceGlitch(img,face):
  68. #pixels segments of 40
  69. div = rd.randint(10,100)
  70. strp = int(round(face[3]/(div*1.0)))
  71. numGlitches = face[3]/strp
  72. for itr in range(0,numGlitches):
  73. rng = rd.randint(15,100)
  74. rightExt = face[0]+face[2]+rng
  75. leftExt = face[0]+face[2]-rng
  76. #make sure extremes don't go out of bounds
  77. if leftExt < 0:
  78. leftExt = 0
  79. if rightExt >= width:
  80. rightExt = width-20
  81. #randomize static direction
  82. #1 moves left, 2 moves right
  83. dec = rd.randint(1,2)
  84. if dec%2 == 0:
  85. img[face[1]+(itr*strp):face[1]+(itr*strp+strp),(face[0]+rng):rightExt] = img[face[1]+(itr*strp):face[1]+(itr*strp+strp),face[0]:face[0]+face[2]]
  86. else:
  87. backBound = face[0]-rng
  88. diff = 0
  89. if backBound < 0:
  90. diff = abs(backBound)
  91. backBound = 0
  92. img[face[1]+(itr*strp):face[1]+(itr*strp+strp),(backBound):leftExt] = img[face[1]+(itr*strp):face[1]+(itr*strp+strp),face[0]:face[0]+face[2]-diff]
  93. def faceDrag(img,face):
  94. h,w,d = img.shape
  95. #0 is horizontal 1 is veritical
  96. ornt = rd.randint(0,2)
  97. if ornt == 0:
  98. line = rd.randint(face[1]+25,face[1]+face[3]-25)
  99. #0 is up 1 is down
  100. dir = rd.randint(0,2)
  101. if dir == 0:
  102. img[0:line,face[0]:face[0]+face[2]] = img[line,face[0]:face[0]+face[2]]
  103. else:
  104. img[line:h,face[0]:face[0]+face[2]] = img[line,face[0]:face[0]+face[2]]
  105. else:
  106. line = rd.randint(face[0]+25,face[0]+face[2]-25)
  107. #0 is left 1 is right
  108. dir = rd.randint(0,2)
  109. if dir == 0:
  110. img[face[1]:face[1]+face[3],0:line] = img[face[1]:face[1]+face[3],line:line+1]
  111. else:
  112. img[face[1]:face[1]+face[3],line:w] = img[face[1]:face[1]+face[3],line:line+1]
  113. def eyeCensor(img,eyes):
  114. if len(eyes) < 2:
  115. print("Failed to generate censor, less than two eyes present")
  116. return
  117. cenH = 40
  118. #get centroids of eyes
  119. c1 = np.array([eyes[0][0] + eyes[0][2]/2.0,eyes[0][1] + eyes[0][3]/2.0])
  120. c2 = np.array([eyes[1][0] + eyes[1][2]/2.0,eyes[1][1] + eyes[1][3]/2.0])
  121. #find the corners of the bar
  122. #find vector of the two centroids
  123. vec = c1-c2
  124. #unitize vector
  125. vec = vec/(vec[0]**2.0+vec[1]**2.0)**0.5
  126. #perpendicular vector
  127. perVec = np.array([vec[1],vec[0]*(-1)])
  128. #change these value to adjust height and width of
  129. #censor bar
  130. wEx = 40
  131. mag = 75
  132. cr1 = perVec*wEx+c1
  133. cr2 = c1 - perVec*wEx
  134. cr3 = perVec*wEx+c2
  135. cr4 = c2 - perVec*wEx
  136. cr1 += vec*mag
  137. cr2 += vec*mag
  138. cr3 -= vec*mag
  139. cr4 -= vec*mag
  140. #round all values
  141. pts = np.array([cr1,cr2,cr4,cr3])
  142. cv2.fillPoly(img,np.array([pts],dtype=np.int32),(0,0,0))
  143. #########################################################
  144. #The following code is incomplete. It's purpose is to randomly
  145. #add text to the censor bar
  146. #roll to see if to add text
  147. # textc = rd.randint(0,2)
  148. # textc = 1
  149. # if textc == 1:
  150. # text = open("elements/censor.txt","r")
  151. # allText = text.read()
  152. # possText = allText.split(";")
  153. # dec = rd.randint(0,len(possText))
  154. # use = possText[dec]
  155. # #calculate text position and angle
  156. # # info = posAndAngle(pts,use)
  157. # font = cv2.FONT_HERSHEY_SIMPLEX
  158. # cv2.putText(img,use,(int(cr1[0]),int(cr1[1])), font, 1,(255,255,255),2,cv2.LINE_AA)
  159. ############################################################
  160. def eyeDrag(img,eyes):
  161. #make sure there are only two eyes per face
  162. if len(eyes) > 2:
  163. eye1 = eyes[0]
  164. eye2 = eyes[0]
  165. size = 0
  166. for itr in range(0,len(eyes)):
  167. if eyes[itr][2]*eyes[itr][3] > size:
  168. size = eyes[itr][2]*eyes[itr][3]
  169. eye1 = eyes[itr]
  170. size = 0
  171. for itr in range(0,len(eyes)):
  172. if eyes[itr][2]*eyes[itr][3] > size and not np.array_equal(eyes[itr],eye1):
  173. size = eyes[itr][2]*eyes[itr][3]
  174. eye2 = eyes[itr]
  175. eyes = [eye1,eye2]
  176. #there should only be two eyes now
  177. for eye in eyes:
  178. #find width of eye
  179. iwid = eye[2]
  180. strp = int(round(iwid/20.))
  181. numGlitches = eye[2]/strp
  182. line = rd.randint(1,eye[3])
  183. line += eye[1]
  184. line = eye[1] + eye[3]/2
  185. for itr in range(0,numGlitches):
  186. drop = rd.randint(10,200)
  187. img[line:line+drop,eye[0]+itr*strp:eye[0]+itr*strp+strp] = img[line,eye[0]+itr*strp:eye[0]+itr*strp+strp]
  188. if __name__ == "__main__":
  189. #seed the random generator
  190. rd.seed(datetime.now())
  191. #load files for facial and eye cascade
  192. face_cascade = cv2.CascadeClassifier('cascade/haarcascade_frontalface_default.xml')
  193. eye_cascade = cv2.CascadeClassifier('cascade/haarcascade_eye.xml')
  194. #load main image from local file
  195. img = cv2.imread("testImgs/testface9.png")
  196. height,width,depth = img.shape
  197. #turn image gray for detecting face and eyes
  198. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  199. #find all the faces in the image
  200. faces = face_cascade.detectMultiScale(gray, 1.3, 5)
  201. #go through each face
  202. for face in faces:
  203. y = face[1]
  204. x = face [0]
  205. w = face [2]
  206. h = face [3]
  207. roi_gray = gray[y:y+h, x:x+w]
  208. roi_color = img[y:y+h, x:x+w]
  209. #find each eye. Modify second and third parameter if
  210. #feature detection is poor
  211. eyes = eye_cascade.detectMultiScale(roi_gray, 1.2, 6)
  212. for eye in eyes:
  213. eye[0] += face[0]
  214. eye[1] += face[1]
  215. #randomize which face modification will be performed
  216. faceMod = rd.randint(1,4)
  217. if faceMod >= 4 and len(eyes) == 0:
  218. faceMod = rd.randint(0,4)
  219. #0 - no mod
  220. #1 - face glitch
  221. #2 - face drag
  222. #3 - eye drag
  223. #4 - eye sensor
  224. if faceMod == 1:
  225. faceGlitch(img,face)
  226. elif faceMod == 2:
  227. faceDrag(img,face)
  228. elif faceMod == 3:
  229. eyeDrag(img,eyes)
  230. elif faceMod == 4:
  231. eyeCensor(img,eyes)
  232. # Add elements to image
  233. addElements(img)
  234. #randomize if high contrast is used
  235. choice = rd.randint(0,1)
  236. if choice == 1:
  237. #edit alpha and beta to adjust contrast levels
  238. img = cv2.convertScaleAbs(img, alpha=1.2, beta=35)
  239. #randomize if high noise is used
  240. choice = rd.randint(0,1)
  241. if choice == 1:
  242. row,col,ch= img.shape
  243. mean = 0
  244. #edit var to modify the amount of noise in the image
  245. var = 15
  246. sigma = var**1
  247. gauss = np.random.normal(mean,sigma,(row,col,ch))
  248. gauss = gauss.reshape(row,col,ch)
  249. noisy = (img + gauss)
  250. cv2.normalize(noisy, noisy, 0, 1, cv2.NORM_MINMAX)
  251. img = noisy
  252. #The following code is useful to determine if faces and eyes
  253. #are being read correctly. Uncommenting will draw boxes around
  254. #found features.
  255. # for (x,y,w,h) in faces:
  256. # cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
  257. # roi_gray = gray[y:y+h, x:x+w]
  258. # roi_color = img[y:y+h, x:x+w]
  259. # #edit the second and third parameter if feature detection is poor
  260. # eyes = eye_cascade.detectMultiScale(roi_gray, 1.2, 6)
  261. # for (ex,ey,ew,eh) in eyes:
  262. # cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
  263. cv2.namedWindow("pic",cv2.WINDOW_NORMAL)
  264. cv2.imshow("pic",img)
  265. cv2.waitKey(0)