Advertisement
Guest User

ImageRecognitionPi

a guest
Oct 23rd, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.57 KB | None | 0 0
  1. from PIL import Image
  2. import numpy as np
  3. import time
  4. import cv2 # for the camera
  5. from gpiozero import LED
  6. import io
  7. from picamera import PiCamera
  8.  
  9. #returns all the x values for which the rgb values add up to 500 or more (white)
  10. def GetWhitesInImage(image, lineNumber):
  11. #cv2.imwrite("Photo.jpg", image)
  12. #rgb_im = image.convert('RGB')
  13. #print((image[0, 0]))
  14. rgb_im = image.RGB()
  15. #width = rgb_im.size[0]
  16. #r = np.zeros(width) # np.ones(rgb_im.size[0]) #create an array with the width of the image
  17. #g = np.zeros(width)
  18. #b = np.zeros(width)
  19.  
  20. #rgbList = []
  21. output = []
  22.  
  23. #Not only select white values on the sum of the rgb, also see if the r, g and b values are somewhat the same
  24.  
  25. #fill the array with the rgb values
  26. for i in range(0, width):
  27. #if i > 478:
  28. # print("WATCH THIS")
  29. r, g, b = rgb_im.getpixel((i,lineNumber))
  30. #b[i], r[i], g[i] = image[lineNumber, i]
  31. #b, r, g = image[lineNumber, i]
  32. #rgbList.append((int(r)+int(g)+int(b)))
  33. #if r[i] + g[i] + b[i] > 400: r < (g + b)*0.75 and
  34. if (int(r) + int(g) + int(b)) > whiteThreshold:
  35. output.append(i)
  36. return output
  37.  
  38.  
  39. #determines from the inputted array with x coords two sets of points that are the two lines
  40. def DetermineLines(whiteXCoords):
  41. #get the average of the values
  42. #average = np.average((whiteXCoords))
  43. #maybe use the middle instead of the average
  44.  
  45.  
  46. #divide the array into two arrays based on if the points lay below the average or above
  47. left = []
  48. right = []
  49. for i in whiteXCoords:
  50. #if i < average:
  51. if i > middle: #this is flipped because the cam will mirror the image
  52. left.append((i))
  53. else:
  54. right.append((i))
  55.  
  56. if len(left) == 0:
  57. left.append(0)
  58. if len(right) == 0:
  59. right.append(0)
  60.  
  61. #calculate the spread of each of the lines
  62. minLeft, maxLeft = np.min((left)), np.max((left))
  63. minRight, maxRight = np.min((right)), np.max((right))
  64.  
  65. #get the percentage of white pixels in the area
  66. percentLeft = np.size((left))/(maxLeft - minLeft + 1)
  67.  
  68. # if the percentage is above 0.8, it is a line, if it's lower it's not.
  69. # so determine what value affects the percentage the most and remove it
  70. #do this 10 times to see if the percentage improves
  71. while maxLeft - minLeft > 30:
  72. averageLeft = np.average((left))
  73.  
  74. # if the percentage is higher than 0.8 break
  75. # when on the track the percentage won't be 1 when on the track, on the metaforum floor it might be 1
  76. #so I removed the 1 constraint
  77. #if 1 > percentLeft > 0.8:
  78. if percentLeft > 0.8:
  79. break
  80.  
  81. # if the averageLeft - minLeft > maxLeft - averageLeft, then the lowest value is further away from the average
  82. # than the highest value. so remove that value
  83. if averageLeft - minLeft > maxLeft - averageLeft:
  84. left.remove(minLeft)
  85. minLeft = np.min(left)
  86. else:
  87. left.remove(maxLeft)
  88. maxLeft = np.max((left))
  89.  
  90. # one value is removed, the min and maxes are recalculated, recalculate the average
  91. percentLeft = np.size((left))/(maxLeft - minLeft + 1)
  92.  
  93.  
  94.  
  95. #get the percentage of white pixels in the area
  96. percentRight = np.size((right))/(maxRight - minRight + 1)
  97.  
  98. # if the percentage is above 0.8, it is a line, if it's lower it's not.
  99. # so determine what value affects the percentage the most and remove it
  100. # do this untill the group becomes too small
  101. while maxRight - minRight > 30:
  102. averageRight = np.average((right))
  103.  
  104. # if the percentage is higher than 0.8 break
  105. if 1 > percentRight > 0.8:
  106. break
  107.  
  108. # if the averageLeft - minLeft > maxLeft - averageLeft, then the lowest value is further away from the average
  109. # than the highest value. so remove that value
  110. if averageRight - minRight > maxRight - averageRight:
  111. right.remove(minRight)
  112. minRight = np.min(right)
  113. else:
  114. right.remove(maxRight)
  115. maxRight = np.max((right))
  116.  
  117. # one value is removed, the min and maxes are recalculated, recalculate the average
  118. percentRight = np.size((right)) / (maxRight - minRight + 1)
  119.  
  120.  
  121. leftLocation = minLeft + ((maxLeft - minLeft) / 2)
  122. rightLocation = minRight + ((maxRight - minRight) / 2)
  123.  
  124. if percentLeft < 0.8:
  125. leftLocation = 0
  126.  
  127. if percentRight < 0.8:
  128. rightLocation = 0
  129.  
  130. #if the percentages are too low, the location 0 is outputted, so the program knows the detection went wrong
  131. return leftLocation, rightLocation
  132.  
  133. def TakePicture():
  134. s, img = cam.read()
  135.  
  136. camera.capture(stream, format='jpeg')
  137. stream.seek(0)
  138. return Image.open(stream)
  139. if s:
  140. cv2.namedWindow("cam-test")#,CV_WINDOW_AUTOSIZE)
  141. #cv2.imshow("cam-test",img)
  142. #cv2.waitKey()
  143. #cv2.imwrite("Photo" + ".jpg", img)
  144. #cv2.destroyWindow("cam-test")
  145.  
  146. return (img)
  147. else:
  148. print("Image not taken")
  149. return
  150.  
  151.  
  152. imagePaths = ["Position0.png", "Position1.png", "Position2.png", "Position3.png", "Position4.png", "Position5.png",
  153. "Position6.png", "Position7.png", "Position8.png", "Position9.png", "Position10.png", "Position11.png",
  154. "Position12.png", "Position13.png", "Position14.png", "Position15.png", "Position16.png", "Position17.png",
  155. "Position18.png", "Position19.png", "Position20.png", "Position21.png", "Position22.png", "Position23.png",
  156. "Position24.png", "Position25.png", "Position26.png", "Position27.png", "Position28.png", "Position29.png",
  157. "Position30.png", "Position31.png", "Position32.png", "Position33.png", "Position34.png", "Position35.png",
  158. "Position36.png", "Position37.png", "Position38.png", "Position39.png", "Position40.png", "Position41.png",
  159. "Position42.png", "Position43.png", "Position44.png", "Position45.png", "Position46.png", "Position47.png",
  160. "Position48.png", "Position49.png", "Position50.png", "Position51.png", "Position52.png", "White.png"]
  161.  
  162. #position 9: on the left line
  163. #position 26: is the middle
  164. #position 44: on the right line
  165.  
  166. imageOrder = [ 26,25,24,23,22,21,20,19,18,17,
  167. 16,15,14,13,12,11,10,11,12,13,
  168. 14,15,16,17,18,19,20,21,22,23,
  169. 24,25,26,27,28,29,30,31,32,33,
  170. 34,35,36,37,38,39,40,41,42,43]
  171.  
  172. # initialize the camera
  173. cam = cv2.VideoCapture(0) # 0 -> index of camera
  174.  
  175. whiteThreshold = 550 #when capturing black/white make this 550, when capturing a track make this 400
  176. # when taking a picture with my webcam of a picture of white lines on meta's gray floor the white was extremely white, the
  177. # gray had a total rgb of 500 or so. so this has to be way higher for the program to distinct between gray and white
  178. # the track had a total of 200/300 on red, and a total of 400/500 on white, so that is a good treshold for that situation
  179.  
  180. #get one image to set the sized correctly
  181. #myImage = Image.open(imagePaths[0])
  182. myImage = TakePicture()
  183. width = int(cam.get(3)) # 3 is the width, 4 is the height
  184. middle = width/2
  185. #middle = myImage.size[0]/2
  186. deviation = width/20 #devide the image in n regions. used for the buzzing. when the regions get smaller
  187. #divide by a higher number, the later the buzzing starts
  188. regions = [middle - 4 * deviation, middle - 3 * deviation, middle - 2 * deviation, middle - 1 * deviation]
  189.  
  190. #lineToCheck = np.round(cam.get(4)/2) # 3 is the width, 4 is the height
  191. lineToCheck = int(cam.get(4)/2) # 3 is the width, 4 is the height
  192.  
  193. leftPositions = [0 for _ in range(10)] # np.zeros(10) #array that contains all the positions of the left line
  194. leftVelocity = [0 for _ in range(10)] # np.zeros(10) #array that contains all the velocities of the left line
  195. rightPositions = [0 for _ in range(10)] # np.zeros(10) #array that contains all the positions of the right line
  196. rightVelocity = [0 for _ in range(10)] # np.zeros(10) #array that contains all the velocities of the left line
  197. leftBuzzingLevel = 0 #the vibrating level of the left vibration motor, {0, 1, 2, 3}, 0 being off
  198. rightBuzzingLevel = 0 #the vibrating level of the right vibration motor, {0, 1, 2, 3}, 0 being off
  199.  
  200. leftVibrationMotor = LED(18)
  201. rightVibrationMotor = LED(19)
  202.  
  203.  
  204. #print("-------------------------------------------------------------------")
  205.  
  206. outputString = ""
  207.  
  208. print("Starting program")
  209.  
  210. stream = io.BytesIO()
  211. camera = picamera.PiCamera()
  212.  
  213. camera.start_preview()
  214. time.sleep(2)
  215.  
  216.  
  217. #for j in range(len(imageOrder)):
  218. j = 0
  219. while True:
  220. j += 1
  221. print("Locations: ", leftLine, " | ", rightLine)
  222. print("predict: ", predictedLeft, " | ", predictedRight)
  223. #print("leftMotor: ", leftVibrationMotor, "rightMotor: ", rightVibrationMotor)
  224. time.sleep(1)
  225. #load image (take image)
  226. #myImage = Image.open(imagePaths[imageOrder[j]])
  227.  
  228. myImage = TakePicture()
  229.  
  230. #gets all the x values for white pixels
  231. whiteXCoordsInImage = GetWhitesInImage(myImage, lineToCheck)
  232.  
  233.  
  234. #get the location of the left line and right line
  235. leftLine, rightLine = DetermineLines((whiteXCoordsInImage))
  236.  
  237. leftPositions.append(leftLine)
  238. leftPositions.pop(0)
  239. if rightLine == 0:
  240. rightLine = width
  241. rightPositions.append((width) - rightLine) #with this the right position gets translated to the left and flipped
  242. #so for both left and right lines the thing is: the further to the right, the worse (both comming from the left)
  243. rightPositions.pop(0)
  244.  
  245. #here the leftPositions and rightPositions are filled with the last 10 positions
  246. #determine the velocity (to the right or left)
  247. if leftPositions[-1] != 0 and leftPositions[-2] != 0:
  248. leftVelocity.append(leftPositions[-1] - leftPositions[-2])
  249. else:
  250. leftVelocity.append(0)
  251. leftVelocity.pop(0)
  252.  
  253. if rightPositions[-1] != 0 and rightPositions[-2] != 0:
  254. rightVelocity.append(rightPositions[-1] - rightPositions[-2])
  255. else:
  256. rightVelocity.append(0)
  257. rightVelocity.pop(0)
  258.  
  259. leftVelocityAsArray = np.asarray(leftVelocity)
  260. predictedLeft = leftPositions[-1] + np.average((leftVelocityAsArray[leftVelocityAsArray != 0]))
  261. rightVelocityAsArray = np.asarray(rightVelocity)
  262. predictedRight = rightPositions[-1] + np.average((rightVelocityAsArray[rightVelocityAsArray != 0]))
  263.  
  264. #predicted is nan if every position is 0, so check for nan
  265.  
  266. if np.isnan((predictedLeft)) or np.isnan((predictedRight)):
  267. rightBuzzingLevel = 5
  268. rightVibrationMotor.on()
  269. leftBuzzingLevel = 5
  270. leftVibrationMotor.on()
  271. #print(j)#, " - ", imagePaths[imageOrder[j]])
  272. #print("Left:")
  273. #print("Locations: ", leftPositions)
  274. #print("Velocity: ", leftVelocity[-1])
  275.  
  276. #print()
  277. #print("Right:")
  278. #print("Locations: ", rightPositions)
  279. #print("Velocity: ", rightVelocity[-1])
  280.  
  281. #print()
  282. #print("Buzzing Levels", leftBuzzingLevel, " | ", rightBuzzingLevel)
  283.  
  284. #print("Location: (", leftPositions[-1], ", ", leftPositions[-2], ")")
  285. #print("Buzzing Levels", leftBuzzingLevel, " | ", rightBuzzingLevel)
  286. #print("-------------------------------------------------------------------")
  287.  
  288. #now = time.time()
  289. #outputString += "image: " + imagePaths[imageOrder[j]] + " | " + \
  290. # " Buzzing: " + str(leftBuzzingLevel) + " | " + str(rightBuzzingLevel) + " | " + \
  291. # "Time: " + str(now) + " Detection Error" + "\n"
  292.  
  293. continue
  294.  
  295.  
  296. #check for each regions if the predicted lines is inside. if not set the according buzzing level
  297. #leftBuzzingLevel = 0
  298. #for i in range(0,len(regions)):
  299. # if predictedLeft < regions[i]:
  300. # break
  301. # else:
  302. # leftBuzzingLevel = i
  303.  
  304. #rightBuzzingLevel = 0
  305. #for i in range(0,len(regions)):
  306. # if predictedRight < regions[i]:
  307. # break
  308. # else:
  309. # rightBuzzingLevel = i
  310.  
  311. #leftBuzzingLevel = 0
  312. #for i in range(0, len(regions)):
  313. # if (predictedLeft < regions[i]):
  314. # leftBuzzingLevel = i
  315. # else:
  316. # break
  317.  
  318. #rightBuzzingLevel = 0
  319. #for i in range(0, len(regions)):
  320. # if (predictedRight < regions[i]):
  321. # rightBuzzingLevel = i
  322. # else:
  323. # break
  324.  
  325. if predictedLeft > regions[1]:
  326. leftBuzzingLevel = 1
  327. leftVibrationMotor.on()
  328. else:
  329. leftBuzzingLevel = 0
  330. leftVibrationMotor.off()
  331. if predictedRight > regions[1]:
  332. rightBuzzingLevel = 1
  333. rightVibrationMotor.on()
  334. else:
  335. rightBuzzingLevel = 0
  336. rightVibrationMotor.off()
  337.  
  338. #leftBuzzingLevel = 0
  339. #if predictedLeft > regions[3]:
  340. # leftBuzzingLevel = 1
  341. #rightBuzzingLevel = 0
  342. #if predictedRight > regions[3]:
  343. # rightBuzzingLevel = 1
  344.  
  345.  
  346.  
  347. #print(j)#, " - ", imagePaths[imageOrder[j]])
  348. #print("Left:")
  349. #print("Locations: ", leftPositions)
  350. leftPositionsArray = np.asarray((leftPositions))
  351. leftVelocityArray = np.asarray((leftVelocity))
  352. #print("Current location: ", leftLine, " | Average: ", np.average(leftPositionsArray[leftPositionsArray > 0]),
  353. # " | Avg velocity: ",np.average(leftVelocityArray[leftVelocityArray != 0]))
  354. #print("Prediction: ", predictedLeft)
  355.  
  356. #print()
  357. #print("Right:")
  358. #print("Locations: ", rightPositions)
  359. rightPositionsArray = np.asarray((rightPositions))
  360. rightVelocityArray = np.asarray((rightVelocity))
  361. #print("Current location: ", rightLine, " | Average: ", np.average(rightPositionsArray[rightPositionsArray > 0]),
  362. # " | Avg velocity: ", np.average(rightVelocityArray[rightVelocityArray != 0]))
  363. #print("Prediction: ", predictedRight)
  364. #print()
  365. #print("Buzzing Levels", leftBuzzingLevel, " | ", rightBuzzingLevel)
  366.  
  367. #print("Location: (", leftPositions[-1], ", ", leftPositions[-2], ")")
  368. #print("Buzzing Levels", leftBuzzingLevel, " | ", rightBuzzingLevel)
  369.  
  370. now = time.time()
  371. #outputString += "image: " + imagePaths[imageOrder[j]] + " | " + \
  372. # " Buzzing: " + str(leftBuzzingLevel) + " | " + str(rightBuzzingLevel) + " | " + \
  373. # "Time: " + str(now) + "\n"
  374.  
  375. #print("-------------------------------------------------------------------")
  376.  
  377. with open('Data.txt', 'w') as f:
  378. f.write(outputString)
  379. f.close()
  380.  
  381.  
  382. camera.stop_preview()
  383. print("Klaaar")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement