Raspbot拍照实现(带预览)

这辆小车最有特色的地方就是它的摄像头以及由此派生出来的视觉处理程序,因此玩视觉的前提就是先将小车的摄像头调用出来,查看它的图像信息。在程序中,可以利用小车自带的$picamera2$库中的函数对摄像头进行读取,具体实现代码如下。 初始化摄像头 from picamera2 import Picamera2, Preview picam2 = Picamera2() # 获取摄像头组件信息,准备好之后调用 调整颜色及方向 摄像头默认的读取参数并不能直接用在显示照片的函数中,两者的不同之处主要有以下几点: 由于安装时的物理问题,摄像头默认是倒过来装的,因此如果直接读取并显示,就会出现照片被旋转了180°的情况; 摄像头对颜色的处理默认是按照$RGB$格式进行转换的,但用$cv2$展示图片时却是按照$BGR$格式进行展示的,因此如果直接读取并显示,就会出现颜色混乱的情况,配色极不正常。 解决上述问题有两种调整方式,一种是直接配置摄像头读取图像时的参数,一种是先按照默认的配置读取图像,之后对读取到的图像用$cv2$库进行调整。 方案1:配置摄像头参数 这里可以直接利用$picam2$和$libcamera$自带的配置函数对摄像头读取参数进行配置。 比较奇怪的一点是,摄像头本身确实是用$RGB$格式读取信息的,这与$cv2$展示时的格式不符合,但在代码中仍然要规定format:RGB888,这是因为根据官方文档的下面一段表述可知,为了让$cv2$用户用得更加方便,在自定义颜色读取时所写的$RGB$实际上代表着底层读取时要用$BGR$。这确实容易让人搞混。 cameraConfig = picam2.create_preview_configuration( main={"format":"RGB888", # 这就是比较奇怪的地方 "size":(picWidth, picHeight)} # 设定摄像头读取图片时的大小 ) cameraConfig["transform"] = libcamera.Transform(vflip=1, hflip=1) # 规定读取图片时将图像旋转180度,即左右和上下均进行翻转。vflip表示垂直翻转,hflip表示上下翻转 picam2.configure(cameraConfig) # 设定完配置后一定要用这句话启用配置! 方案2:读取照片后操作 若已经按照默认参数读取了照片,则需用$cv2$库中自带的函数进行转换。 frame = picam2.capture_array() # 先获取一帧 frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) # 将RGB格式转为BGR格式 frame = cv2.flip(frame, -1) 增加预览功能 上面只是说了拍照如何实现,但如果只是拍一张照片,在此之前其实并不能知道摄像头的取景框现在在哪里,有多大,能不能拍全,因此最好加一个拍照前预览几秒的功能。这个功能同样有两种方式可以实现,一种是直接在程序中调用命令行中的预览指令,一种是自己写一个可以持续几秒钟的无限循环。 方案1:模拟命令行执行预览指令 这里需要用到$python$自带的模拟命令行的库以及树莓派提供的预览指令,具体实现如下: import subprocess # 可以模拟在命令行中执行指令 subprocess.run(['rpicam-vid', '-t', '5000', '--vflip', '1', '--hflip', '1']) # 调用树莓派自带的预览指令,其中-t后的数字表示预览持续多少毫秒,--vflip后的数字表示是否进行垂直翻转,--hflip后的数字表示是否进行水平翻转 方案2:编写循环实现 本质上和视频是一个道理,间隔一定时间后更新一帧图片,只要时间间隔足够短,就可以营造出视频的效果,而自定义持续时间即可用$time$库的时间戳之差控制循环的结束。 需要注意的是,如果采用这种方案,必须先采用上面「调整颜色及方向」中的方案1,提前对摄像头进行配置,否则会按照默认的参数进行显示。 import time startTime = time.time() # 获取开始时的时间戳 while time.time()-startTime < 5: # 当预览到达5秒时结束预览 cur = picam2.capture_array() # 获取当前帧 # 将当前帧更新到创建的Preview窗口中,不必担心创建很多窗口,因为imshow函数是根据窗口名称进行更新的 cv2.imshow('Preview', cur) cv2.waitKey(1) # 等待1毫秒,让新的一帧加载到窗口中 cv2.destroyAllWindows() # 删除预览窗口,等待拍照 写入照片文件 写入照片文件非常简单,只需要调用$cv2$中自带的$imwrite$函数即可将照片写入对应名称的文件中。 ...