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.

240 lines
8.7 KiB

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