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.

257 lines
9.3 KiB

  1. import serial
  2. import threading
  3. import time
  4. class Frame():
  5. def __init__(self, time, data):
  6. self.time = time
  7. self.data = data
  8. class GridEye():
  9. def __init__(self, serialPort, baudrate):
  10. self.port = serial.Serial(serialPort, baudrate)
  11. self.frame = None
  12. self.reading = True
  13. self.thread = threading.Thread(target = self.reader)
  14. self.thread.setDaemon(True)
  15. self.lock = threading.Lock()
  16. def start(self):
  17. self.port.reset_input_buffer()
  18. self.thread.start()
  19. def stop(self):
  20. self.reading = False
  21. self.thread.join()
  22. def reader(self):
  23. data = []
  24. data_time = 0;
  25. while (self.reading):
  26. line = b''
  27. while (self.reading):
  28. c = self.port.read()
  29. if c == b'\r':
  30. c = self.port.read()
  31. break
  32. if c == b'\n':
  33. break
  34. line += c
  35. #line = self.port.readline()#.decode('utf-8')
  36. # if line:
  37. # print (line)
  38. # time.sleep(0.01)
  39. # if self.port.in_waiting > 0:
  40. # print (self.port.in_waiting)
  41. if b'#' in line:
  42. if len(data) == 8:
  43. #print (data)
  44. self.lock.acquire()
  45. self.frame = Frame(data_time, data)
  46. self.lock.release()
  47. else:
  48. print ('something wrong', len(data))
  49. data_time = time.time()
  50. data = []
  51. else:
  52. try:
  53. row = [float(x) for x in line.split()]
  54. if len(row) == 8:
  55. data.append(row)
  56. except ValueError as e:
  57. print ('error', e)
  58. data_time = time.time()
  59. data = []
  60. if len(data) > 8:
  61. data.pop(0)
  62. class Distance():
  63. def __init__(self, serialPort, baudrate):
  64. self.port = serial.Serial(serialPort, baudrate)
  65. self.distance = 200
  66. self.reading = True
  67. self.thread = threading.Thread(target = self.reader)
  68. self.thread.setDaemon(True)
  69. self.lock = threading.Lock()
  70. def start(self):
  71. self.port.reset_input_buffer()
  72. self.thread.start()
  73. def stop(self):
  74. self.reading = False
  75. self.thread.join()
  76. def reader(self):
  77. while (self.reading):
  78. line = b''
  79. while (self.reading):
  80. c = self.port.read()
  81. if c == b'\r':
  82. c = self.port.read()
  83. break
  84. if c == b'\n':
  85. break
  86. line += c
  87. if b'Distance' in line:
  88. try:
  89. dist = float(line.decode('utf-8').split(':')[1])
  90. print (dist)
  91. if dist > 200.0:
  92. dist = 200.0
  93. self.lock.acquire()
  94. self.distance = dist
  95. self.lock.release()
  96. except ValueError as e:
  97. print ('error', e)
  98. if __name__ == '__main__':
  99. import cv2
  100. import numpy as np
  101. import math
  102. def exponential(img, value):
  103. tmp = cv2.pow(img.astype(np.double), value)*(255.0/(255.0**value))
  104. return tmp.astype(np.uint8)
  105. SIZE = 128
  106. overlap = 120
  107. AVERAGE_FRAME = 10
  108. distanceBetweenSensors = 7.7 #cm
  109. distance2Object = 60.0 #cm
  110. ADJUST_BACK = 5
  111. EXPONENTAL_VALUE = 0.4
  112. offset = (distanceBetweenSensors / (2*distance2Object*math.tan(30.0/180.0*math.pi))) * SIZE
  113. overlap = int(SIZE - offset)
  114. print (overlap)
  115. grideye = GridEye('COM15', 115200)
  116. grideye.start()
  117. grideye2 = GridEye('COM17', 115200)
  118. grideye2.start()
  119. distanceSensor = Distance('COM18', 9600)
  120. distanceSensor.start()
  121. fourcc = cv2.VideoWriter_fourcc(*'XVID')
  122. videoWriter = cv2.VideoWriter('output.avi', fourcc, 10.0, (SIZE*2,SIZE*3))
  123. cv2.imshow('sample', np.zeros((SIZE*3,SIZE*2), np.uint8))
  124. aver1 = np.zeros((SIZE,SIZE), np.uint16)
  125. aver2 = np.zeros((SIZE,SIZE), np.uint16)
  126. cnt = 0
  127. while True:
  128. if grideye.frame and grideye2.frame:
  129. grideye.lock.acquire()
  130. grideye2.lock.acquire()
  131. distanceSensor.lock.acquire()
  132. frame = grideye.frame
  133. grideye.frame = None
  134. frame2 = grideye2.frame
  135. grideye2.frame = None
  136. # frame2 = frame
  137. distance2Object = distanceSensor.distance
  138. distanceSensor.lock.release()
  139. grideye2.lock.release()
  140. grideye.lock.release()
  141. p = np.zeros((16,16), np.uint16)
  142. img = (np.array(frame.data)-15)*10
  143. img = cv2.resize(img.astype(np.uint8), (SIZE,SIZE), interpolation = cv2.INTER_CUBIC) # INTER_LINEAR, INTER_CUBIC
  144. img2 = (np.array(frame2.data)-15)*10
  145. img2 = cv2.resize(img2.astype(np.uint8), (SIZE,SIZE), interpolation = cv2.INTER_CUBIC)
  146. if cnt < AVERAGE_FRAME:
  147. cnt += 1
  148. aver1 += img
  149. aver2 += img2
  150. if cnt == AVERAGE_FRAME:
  151. aver1 = aver1/AVERAGE_FRAME
  152. aver1 = aver1.astype(np.uint8)
  153. aver1 += ADJUST_BACK
  154. aver2 = aver2/AVERAGE_FRAME
  155. aver2 = aver2.astype(np.uint8)
  156. aver2 += ADJUST_BACK
  157. continue
  158. img = cv2.subtract(img, aver1)
  159. img2 = cv2.subtract(img2, aver2)
  160. out = np.full((SIZE*3, SIZE*2), 255, dtype=np.uint16)
  161. out[:SIZE, :SIZE] = img
  162. out[:SIZE, SIZE:] = img2
  163. try:
  164. overlap = int(SIZE - (distanceBetweenSensors / (2*distance2Object*math.tan(30.0/180.0*math.pi))) * SIZE)
  165. except:
  166. overlap = 0
  167. if overlap < 0:
  168. overlap = 0
  169. offset = int(overlap/2)
  170. # tmp = cv2.resize(img.astype(np.uint8), (SIZE*2-overlap, SIZE))
  171. # tmp.astype(np.uint16)
  172. tmp = np.zeros((SIZE, SIZE*2-overlap), dtype=np.uint16)
  173. tmp[:, :SIZE] = img
  174. tmp[:, -SIZE:] += img2
  175. tmp[:, (SIZE-overlap): SIZE] = tmp[:, (SIZE-overlap): SIZE]/2
  176. tmp = exponential(tmp, EXPONENTAL_VALUE)
  177. out[SIZE:SIZE*2, offset: SIZE*2-overlap+offset] = tmp
  178. # out[SIZE:SIZE*2, offset:SIZE+offset] = img
  179. # out[SIZE:SIZE*2, (SIZE-overlap)+offset:SIZE+offset] += img2[:,:overlap]
  180. # out[SIZE:SIZE*2, (SIZE-overlap)+offset:SIZE+offset] = out[SIZE:SIZE*2, (SIZE-overlap)+offset:SIZE+offset]/2
  181. # out[SIZE:SIZE*2, SIZE+offset:SIZE+(SIZE-overlap)+offset] = img2[:,overlap:SIZE]
  182. maxProduct = 0
  183. overlap2 = 0
  184. for i in range(80, 128):
  185. product = sum(img[:,SIZE-i:].astype(np.uint32)*img2[:,:i].astype(np.uint32))
  186. product = sum(product) / len(product)
  187. if product > maxProduct:
  188. maxProduct = product
  189. overlap2 = i
  190. offset = int(overlap2/2)
  191. tmp = np.zeros((SIZE, SIZE*2-overlap2), dtype=np.uint16)
  192. tmp[:, :SIZE] = img
  193. tmp[:, -SIZE:] += img2
  194. tmp[:, (SIZE-overlap2): SIZE] = tmp[:, (SIZE-overlap2): SIZE]/2
  195. tmp = exponential(tmp, EXPONENTAL_VALUE)
  196. out[SIZE*2:, offset: SIZE*2-overlap2+offset] = tmp
  197. # out[SIZE*2:, offset:SIZE+offset] = img
  198. # out[SIZE*2:, (SIZE-overlap2)+offset:SIZE+offset] += img2[:,:overlap2]
  199. # out[SIZE*2:, (SIZE-overlap2)+offset:SIZE+offset] = out[SIZE*2:, (SIZE-overlap2)+offset:SIZE+offset]/2
  200. # out[SIZE*2:, SIZE+offset:SIZE+(SIZE-overlap2)+offset] = img2[:,overlap2:SIZE]
  201. out = out.astype(np.uint8)
  202. img = (np.array(frame.data)-15)*10
  203. img = img.astype(np.uint8)
  204. img2 = (np.array(frame2.data)-15)*10
  205. img2 = img2.astype(np.uint8)
  206. p = np.zeros((8,16), np.uint8)
  207. for i in range(16):
  208. if i%2 == 0:
  209. p[:,i] = img[:,int(i/2)]
  210. else:
  211. p[:,i] = img2[:,int(i/2)]
  212. p = cv2.resize(p, (SIZE,SIZE), interpolation = cv2.INTER_CUBIC)
  213. cv2.imshow('sample', out)
  214. cv2.imshow('p', p)
  215. videoWriter.write(cv2.cvtColor(out,cv2.COLOR_GRAY2BGR))
  216. key = cv2.waitKey(1)
  217. if key == ord('q'):
  218. break
  219. elif key == ord('a'):
  220. overlap += 1
  221. elif key == ord('d'):
  222. overlap -= 1
  223. elif key == ord('c'):
  224. cv2.imwrite('out.jpg', out)
  225. time.sleep(0.001)
  226. grideye.stop()
  227. grideye2.stop()
  228. videoWriter.release()
  229. cv2.destroyAllWindows()