当前位置:   article > 正文

Kinect系列1:(Windows环境配置)Python3+Pykinect2+KinectV2相机读取彩色图与深度图_kinect python

kinect python

前言:

Kinect是微软在2009年公布的XBOX360体感周边外设。它是一种3D体感摄影机,同时它导入了即时动态捕捉、影像辨识、麦克风输入、语音辨识、社群互动等功能。而相比Kinect V1,Kinect V2具有较大的红外传感器尺寸,并且(相对于其他深度相机)具有较宽阔的视场角,生成的深度图质量比较高。此外,Kinect V2的SDK非常给力,SDK中提供了同时最多进行六个人的骨架追踪、基本的手势操作和脸部跟踪,支持 Cinder 和 Open Frameworks,并且具有内置的Unity 3D插件。下面是Kinect V1和Kinect V2的一些对比。

KinectV1和V2性能参数对比
种类V1V2
彩色图分辨率640*4801920*1280
深度图分辨率320*240512*424
红外图分辨率--512*424
深度检测距离0.4m~4m0.4m~4.5m
垂直方向视角57度70度
水平方向视角43度60度

同时,相对V1版相机基本是通过C++进行读取与开发,V2版也提供了一些开源Python接口对相机进行读取,如(Kinect/Pykinect2)。接着就可以方便地使用OpenCV、Open3D或深度学习等算法了。目前应用Python开发KinectV2主要有三种思路:

A. Libfreenect2以及OpenNI2:此方法在ROS端配置比较方便(参考博客),但在Windows端配置比较复杂(参考博客)。且对UsbDk或libusbK和libfreenect2等文件通过Visual Studio编译的过程依赖工具多,不同电脑总会出现各种问题,解决起来比较繁琐。

B. Matlab(读取)和Python的联合编程:通过kin2工具箱(参考开源项目)调用C++封装好的Kinect SDK,并通过Matlab和Python的实时通讯接口传输图片。缺点是占用内存大、传输延时大、调试复杂。

C. 应用Pykinect2库:通过开源的Pykinect2工具库读取,但数据方面只提供RGB和深度图接口,且该库是使用Python2开发。在应用Python3的安装和开发过程中会遇到一系列的问题,在本文中列出相应的解决方案。

工作环境:

系统:windows10家庭版

Anaconda版本:4.14.0

Python版本:3.8.12

IDE:Pycharm

安装流程:

1、下载Kinect for Windows SDK2.0,并正确安装至本机,打开Kinect Studio检查安装是否成功。参考博客

2、在Anaconda的Terminal下载Pykinect2库:

pip install pykinect2 -i https://pypi.tuna.tsinghua.edu.cn/simple

3、进入Pykinect2(Github)下载最新库,并把其中的这两个文件替换(Anaconda所在路径)\envs\(环境名称)\Lib\site-packages\pykinect2下的同名文件。

此步骤可以解决这个报错:

4、接下来会遇到这个报错,此报错是由于Pykinect2依赖库comtypes连接的版本与最新版本不兼容。

此时需要重新安装comtypes库:

pip install comtypes==1.1.4 -i https://pypi.tuna.tsinghua.edu.cn/simple

5、接下来会遇到这个报错,此报错是由于该版本的comtypes库是基于Python2编写的,与现在环境的Python3版本不兼容。

此时需要将comtypes库中用到的Python2文件转换为Python3文件才能够正常执行,先找到Anaconda安装路径中的2to3.py文件,位于(Anaconda安装路径)\envs\(环境名称)\Tools\scripts:

打开电脑cmd(Win+R),进入到对应路径下:

找到comtypes中报错的文件路径,使用2to3.py将其转为Python3文件,例如输入:

python 2to3.py -w D:\Anaconda\envs\paddle\lib\site-packages\comtypes\__init__.py

顺序解决所有类似的报错,此步骤涉及近10个文件,需要耐心重复执行。执行完后便可正常引用Pykinect2库了。

6、编写Python调用Pykinect2的读取程序,此处参考(开源博客)中提供的示例代码进行修改:

  1. #coding=utf-8
  2. from pykinect2 import PyKinectV2
  3. from pykinect2.PyKinectV2 import *
  4. from pykinect2 import PyKinectRuntime
  5. import numpy as np
  6. import ctypes
  7. import math
  8. import cv2 as cv
  9. import time
  10. import copy
  11. class Kinect(object):
  12. def __init__(self):
  13. self._kinect = PyKinectRuntime.PyKinectRuntime(PyKinectV2.FrameSourceTypes_Color | PyKinectV2.FrameSourceTypes_Depth | PyKinectV2.FrameSourceTypes_Infrared)
  14. self.depth_ori = None
  15. self.infrared_frame = None
  16. self.color_frame = None
  17. self.w_color = 1920
  18. self.h_color = 1080
  19. self.w_depth = 512
  20. self.h_depth = 424
  21. self.csp_type = _ColorSpacePoint * int(1920 * 1080)
  22. self.csp = ctypes.cast(self.csp_type(), ctypes.POINTER(_DepthSpacePoint))
  23. self.color = None
  24. self.depth = None
  25. self.depth_draw = None
  26. self.color_draw = None
  27. self.infrared = None
  28. self.first_time = True
  29. def get_the_last_color(self):
  30. if self._kinect.has_new_color_frame():
  31. frame = self._kinect.get_last_color_frame()
  32. gbra = frame.reshape([self._kinect.color_frame_desc.Height, self._kinect.color_frame_desc.Width, 4])
  33. self.color_frame = gbra[:, :, 0:3]
  34. return self.color_frame
  35. def get_the_last_depth(self):
  36. if self._kinect.has_new_depth_frame():
  37. frame = self._kinect.get_last_depth_frame()
  38. image_depth_all = frame.reshape([self._kinect.depth_frame_desc.Height,
  39. self._kinect.depth_frame_desc.Width])
  40. self.depth_ori = image_depth_all
  41. return self.depth_ori
  42. def get_the_last_infrared(self):
  43. if self._kinect.has_new_infrared_frame():
  44. frame = self._kinect.get_last_infrared_frame()
  45. image_infrared_all = frame.reshape([self._kinect.infrared_frame_desc.Height,
  46. self._kinect.infrared_frame_desc.Width])
  47. self.infrared_frame = image_infrared_all
  48. return self.infrared_frame
  49. def map_depth_point_to_color_point(self, depth_point):
  50. depth_point_to_color = copy.deepcopy(depth_point)
  51. n = 0
  52. while 1:
  53. self.get_the_last_depth()
  54. self.get_the_last_color()
  55. if self.depth_ori is None:
  56. continue
  57. color_point = self._kinect._mapper.MapDepthPointToColorSpace(
  58. _DepthSpacePoint(511-depth_point_to_color[1], depth_point_to_color[0]), self.depth_ori[depth_point_to_color[0], 511-depth_point_to_color[1]])
  59. # color_point = self._kinect._mapper.MapDepthPointToColorSpace(
  60. # _DepthSpacePoint(depth_point[0], depth_point[1]), self.depth[depth_point[1], depth_point[0]])
  61. if math.isinf(float(color_point.y)):
  62. n += 1
  63. if n >= 50000:
  64. print('')
  65. color_point = [0, 0]
  66. break
  67. else:
  68. color_point = [np.int0(color_point.y), 1920-np.int0(color_point.x)]
  69. break
  70. return color_point
  71. def map_color_points_to_depth_points(self, color_points):
  72. self.get_the_last_depth()
  73. self.get_the_last_color()
  74. self._kinect._mapper.MapColorFrameToDepthSpace(
  75. ctypes.c_uint(512 * 424), self._kinect._depth_frame_data, ctypes.c_uint(1920 * 1080), self.csp)
  76. depth_points = [self.map_color_point_to_depth_point(x, True) for x in color_points]
  77. return depth_points
  78. #将彩色像素点映射到深度图像中
  79. def map_color_point_to_depth_point(self, color_point, if_call_flg=False):
  80. n = 0
  81. color_point_to_depth = copy.deepcopy(color_point)
  82. color_point_to_depth[1] = 1920 - color_point_to_depth[1]
  83. while 1:
  84. self.get_the_last_depth()
  85. self.get_the_last_color()
  86. # self.depth = cv.medianBlur(image_depth_all, 5)
  87. if not if_call_flg:
  88. self._kinect._mapper.MapColorFrameToDepthSpace(
  89. ctypes.c_uint(512 * 424), self._kinect._depth_frame_data, ctypes.c_uint(1920 * 1080), self.csp)
  90. if math.isinf(float(self.csp[color_point_to_depth[0]*1920+color_point_to_depth[1]-1].y)) or np.isnan(self.csp[color_point_to_depth[0]*1920+color_point_to_depth[1]-1].y):
  91. n += 1
  92. if n >= 50000:
  93. print('彩色映射深度,无效的点')
  94. depth_point = [0, 0]
  95. break
  96. else:
  97. self.cor = self.csp[color_point_to_depth[0]*1920+color_point_to_depth[1]-1].y
  98. try:
  99. depth_point = [np.int0(self.csp[color_point_to_depth[0]*1920+color_point_to_depth[1]-1].y),
  100. np.int0(self.csp[color_point_to_depth[0]*1920+color_point_to_depth[1]-1].x)]
  101. except OverflowError as e:
  102. print('彩色映射深度,无效的点')
  103. depth_point = [0, 0]
  104. break
  105. depth_point[1] = 512-depth_point[1]
  106. return depth_point
  107. # depth_points = [self._kinect._mapper.MapColorPointToDepthSpace(_ColorSpacePoint(color_point[0],color_point[1]),self.color_frame[depth_point]))
  108. # for depth_point in depth_points]
  109. # return color_points
  110. #获得最新的彩色和深度图像以及红外图像
  111. def get_the_data_of_color_depth_infrared_image(self, Infrared_threshold = 16000):
  112. # 访问新的RGB帧
  113. time_s = time.time()
  114. if self.first_time:
  115. while 1:
  116. n = 0
  117. if self._kinect.has_new_color_frame():
  118. # # 获得的图像数据是二维的,需要转换为需要的格式
  119. frame = self._kinect.get_last_color_frame()
  120. # 返回的是4通道,还有一通道是没有注册的
  121. gbra = frame.reshape([self._kinect.color_frame_desc.Height, self._kinect.color_frame_desc.Width, 4])
  122. # 取出彩色图像数据
  123. # self.color = gbra[:, :, 0:3]
  124. self.color = gbra[:, :, 0:3][:,::-1,:]
  125. # 这是因为在python中直接复制该图像的效率不如直接再从C++中获取一帧来的快
  126. frame = self._kinect.get_last_color_frame()
  127. # 返回的是4通道,还有一通道是没有注册的
  128. gbra = frame.reshape([self._kinect.color_frame_desc.Height, self._kinect.color_frame_desc.Width, 4])
  129. # 取出彩色图像数据
  130. # self.color_draw = gbra[:, :, 0:3][:,::-1,:]
  131. self.color_draw = gbra[:, :, 0:3][:,::-1,:]
  132. n += 1
  133. # 访问新的Depth帧
  134. if self._kinect.has_new_depth_frame():
  135. # 获得深度图数据
  136. frame = self._kinect.get_last_depth_frame()
  137. # 转换为图像排列
  138. image_depth_all = frame.reshape([self._kinect.depth_frame_desc.Height,
  139. self._kinect.depth_frame_desc.Width])
  140. # 转换为(n,m,1) 形式
  141. image_depth_all = image_depth_all.reshape(
  142. [self._kinect.depth_frame_desc.Height, self._kinect.depth_frame_desc.Width, 1])
  143. self.depth_ori = np.squeeze(image_depth_all)
  144. self.depth = np.squeeze(image_depth_all)[:,::-1]
  145. """————————————————(2019/5/11)——————————————————"""
  146. # 获得深度图数据
  147. frame = self._kinect.get_last_depth_frame()
  148. # 转换为图像排列
  149. depth_all_draw = frame.reshape([self._kinect.depth_frame_desc.Height,
  150. self._kinect.depth_frame_desc.Width])
  151. # 转换为(n,m,1) 形式
  152. depth_all_draw = depth_all_draw.reshape(
  153. [self._kinect.depth_frame_desc.Height, self._kinect.depth_frame_desc.Width, 1])
  154. depth_all_draw[depth_all_draw >= 1500] = 0
  155. depth_all_draw[depth_all_draw <= 500] = 0
  156. depth_all_draw = np.uint8(depth_all_draw / 1501 * 255)
  157. self.depth_draw = depth_all_draw[:,::-1,:]
  158. n += 1
  159. # 获取红外数据
  160. if self._kinect.has_new_infrared_frame():
  161. # 获得深度图数据
  162. frame = self._kinect.get_last_infrared_frame()
  163. # 转换为图像排列
  164. image_infrared_all = frame.reshape([self._kinect.depth_frame_desc.Height,
  165. self._kinect.depth_frame_desc.Width])
  166. # 转换为(n,m,1) 形式
  167. image_infrared_all[image_infrared_all > Infrared_threshold] = 0
  168. image_infrared_all = image_infrared_all / Infrared_threshold * 255
  169. self.infrared = image_infrared_all[:,::-1]
  170. n += 1
  171. t = time.time() - time_s
  172. if n == 3:
  173. self.first_time = False
  174. break
  175. elif t > 5:
  176. print('未获取图像数据,请检查Kinect2连接是否正常')
  177. break
  178. else:
  179. if self._kinect.has_new_color_frame():
  180. # # 获得的图像数据是二维的,需要转换为需要的格式
  181. frame = self._kinect.get_last_color_frame()
  182. # 返回的是4通道,还有一通道是没有注册的
  183. gbra = frame.reshape([self._kinect.color_frame_desc.Height, self._kinect.color_frame_desc.Width, 4])
  184. # 取出彩色图像数据
  185. # self.color = gbra[:, :, 0:3]
  186. self.color = gbra[:, :, 0:3][:, ::-1, :]
  187. # 这是因为在python中直接复制该图像的效率不如直接再从C++中获取一帧来的快
  188. frame = self._kinect.get_last_color_frame()
  189. # 返回的是4通道,还有一通道是没有注册的
  190. gbra = frame.reshape([self._kinect.color_frame_desc.Height, self._kinect.color_frame_desc.Width, 4])
  191. # 取出彩色图像数据
  192. # self.color_draw = gbra[:, :, 0:3][:,::-1,:]
  193. self.color_draw = gbra[:, :, 0:3][:, ::-1, :]
  194. # 访问新的Depth帧
  195. if self._kinect.has_new_depth_frame():
  196. # 获得深度图数据
  197. frame = self._kinect.get_last_depth_frame()
  198. # 转换为图像排列
  199. image_depth_all = frame.reshape([self._kinect.depth_frame_desc.Height,
  200. self._kinect.depth_frame_desc.Width])
  201. # 转换为(n,m,1) 形式
  202. image_depth_all = image_depth_all.reshape(
  203. [self._kinect.depth_frame_desc.Height, self._kinect.depth_frame_desc.Width, 1])
  204. self.depth_ori = np.squeeze(image_depth_all)
  205. self.depth = np.squeeze(image_depth_all)[:, ::-1]
  206. # 获得深度图数据
  207. frame = self._kinect.get_last_depth_frame()
  208. # 转换为图像排列
  209. depth_all_draw = frame.reshape([self._kinect.depth_frame_desc.Height,
  210. self._kinect.depth_frame_desc.Width])
  211. # 转换为(n,m,1) 形式
  212. depth_all_draw = depth_all_draw.reshape(
  213. [self._kinect.depth_frame_desc.Height, self._kinect.depth_frame_desc.Width, 1])
  214. depth_all_draw[depth_all_draw >= 1500] = 0
  215. depth_all_draw[depth_all_draw <= 500] = 0
  216. depth_all_draw = np.uint8(depth_all_draw / 1501 * 255)
  217. self.depth_draw = depth_all_draw[:, ::-1, :]
  218. # 获取红外数据
  219. if self._kinect.has_new_infrared_frame():
  220. # 获得深度图数据
  221. frame = self._kinect.get_last_infrared_frame()
  222. # 转换为图像排列
  223. image_infrared_all = frame.reshape([self._kinect.depth_frame_desc.Height,
  224. self._kinect.depth_frame_desc.Width])
  225. # 转换为(n,m,1) 形式
  226. image_infrared_all[image_infrared_all > Infrared_threshold] = 0
  227. image_infrared_all = image_infrared_all / Infrared_threshold * 255
  228. self.infrared = image_infrared_all[:, ::-1]
  229. return self.color, self.color_draw, self.depth, self.depth_draw, self.infrared
  230. #显示各种图像的视频流
  231. def Kinect_imshow(self,type_im='rgb'):
  232. """
  233. Time :2019/9/3
  234. FunC:
  235. Input: color_data
  236. Return: color_data
  237. """
  238. if type_im =='all':
  239. pass
  240. elif type_im =='rgb':
  241. pass
  242. elif type_im =='depth':
  243. pass
  244. elif type_im =='grared':
  245. pass
  246. if __name__ == '__main__':
  247. a = Kinect()
  248. while 1:
  249. t = time.time()
  250. #color_data = a.get_the_data_of_color_depth_infrared_image()
  251. color, color_draw, depth, depth_draw, infrared = a.get_the_data_of_color_depth_infrared_image()
  252. cv.imshow('a',color)
  253. cv.waitKey(1)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/826604
推荐阅读
相关标签
  

闽ICP备14008679号