最近为了让机器人更加聪慧而善解人意,准备在英伟达的TX2上开发一下视觉目标检测与速度预判,需要一种比较好的方案,因此选择了Retinanet(Resnet)残差网络进行图像的识别。它需要配置TensorFlow1.4.0以上级别的框架,以及Python3.5,于是乎步入了血海深坑至今酸爽不已。接下来是需要注意的坑(对于菜狗来说,很多都是坑,让大神见笑了):
一、ARM内核与X86内核是不同的,在我们平时使用的电脑上很方便的vscode或者atom,是不支持ARM内核的,同学们不要再傻傻安装了。例如TensorFlow以及它的依赖,Numpy、SciPy、pillow、h5py、Keras等等,在X86上是可以用pip3直接安装的,但是在ARM上会显示:
Could not find a version that satisfies the requirement ...(from versions: )
No matching distribution found for ...
回头来看自己竟然会在这种问题上卡。。。安装TensorFlow的过程我倾向于源码编译,这样需要下载bazel,也需要小心谨慎。在pip install中可能会出现pip import main error的问题,这个需要在/usr/bin/pip下修改:
from pip import __main__
if __name__ == '__main__':
sys.exit(__main__._main())
二、TensorFlow、CUDA、CUDNN的版本需要对齐,例如TX2刷机后自带CUDA9.0,而CUDNN的版本是7.0,那下载的TensorFlow版本需要在1.6~1.8之间,而我一开始用pip upgrade下载了1.9,也是不行的。如果目前CUDA版本是8.0,那TensorFlow版本只能在1.4以下了。
三、Python3中opencv与ros冲突的问题,例如在import cv2时出现ImportError: No module named 'cv2'的报错,那是由于ros默认支持Python2.7,在ros的文件夹中找到cv.so,将它改名就可以了。然后在Python3中运行ros代码,需要安装catkin-tool与rospkg,要不然在运行时会去Python2.7目录下寻找。
四、cv_bridge,它本身就是一个小坑,它能使rosmsg和cvMat互相转换,但是它在Python3中的使用也不是一帆风顺,上来就报了ImportError: dynamic module does not define module export function 的错:
[ERROR] [1543892418.353969]: bad callback: <bound method image_converter.callback of <__main__.image_converter object at 0x7f7a22594748>>
Traceback (most recent call last):
File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/topics.py", line 750, in _invoke_callback cb(msg)
File "/home/qinhaidong/imagetest/src/subscribe/src/subscribe.py", line 27, in callback cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
File "/opt/ros/kinetic/lib/python2.7/dist-packages/cv_bridge/core.py", line 163, in imgmsg_to_cv2 dtype, n_channels = self.encoding_to_dtype_with_channels(img_msg.encoding)
File "/opt/ros/kinetic/lib/python2.7/dist-packages/cv_bridge/core.py", line 99, in encoding_to_dtype_with_channels return self.cvtype2_to_dtype_with_channels(self.encoding_to_cvtype2(encoding))
File "/opt/ros/kinetic/lib/python2.7/dist-packages/cv_bridge/core.py", line 91, in encoding_to_cvtype2 from cv_bridge.boost.cv_bridge_boost import getCvType
ImportError: dynamic module does not define module export function (PyInit_cv_bridge_boost)
解决办法:https://stackoverflow.com/questions/49221565/unable-to-use-cv-bridge-with-ros-kinetic-and-python3
需要用Python3对cv_bridge进行重新build。
五、在ros subscribe的callback函数中,不能调用TensorFlow框架,由于ros只支持Python2.7的问题(又是这个问题),rospy的callback函数也是出自于Python2.7目录,在callback函数中做识别目测怎样都会报错!当然渴望被打脸。。。所以,只能用多线程做,这又跳进了下一个坑。
六、Python的多线程和C++不太一样,它对self(类似于this指针)的要求十分严苛,我在写分线程中是while死循环,而主线程是rospy.spin( )的时候(此时又得吐槽没有spinOnce这个函数了),又会出现阻塞的情况,那具体的写法应该是:
def act(self):
...
t = threading.Thread(target = self.act) #生成一个线程实例
t.start() #启动线程
thread括号里不要加括号。多线程吃的亏似乎还有一些,只能慢慢体会了。
七、如果用rosmsg作为图像的输入,它用cvbridge转化为cvMat,可能还要转化为numpy中的ndarray才能输入到网络中,不但复杂而且耗时,一帧高精度图像光转换就要0.2秒,这跟实时性就基本上拜拜了。还是用它直连用VideoCapture方便一些。
这就是一些或深或浅的坑,花了将近两周时间才逐一踩完,与各位共勉,也纪念一下痛心疾首的生活。。