使用 Lepton 寻人
这是使用开源计算机视觉库 OpenCV,通过 FLIR Lepton 摄像头实现基本寻人算法的教程。
目标
热像仪非常适合在几乎所有光照条件下寻找哺乳动物。作为一项探索它们能做什么的练习,让我们尝试在 Lepton 的视野区域寻人,使用 OpenCV 在他们周围画上轮廓。
工具
您需要的硬件:
- Lepton
- PureThermal 板
- 安装了 OpenCV 绑定的 Python 2.7 环境。可以设置 Windows、OSX 或 Linux。
- 如果您想保存图像的话,也可以用 PIL。
设置
按照适用于您的特定平台的教程来设置 Python 环境,并安装 OpenCV。完成后,通过查看网络摄像头视频流来验证一切是否正常。
import cv2
cv2.namedWindow("preview")
cameraID = 0
vc = cv2.VideoCapture(cameraID)
if vc.isOpened(): # try to get the first frame
rval, frame = vc.read()
else:
rval = False
while rval:
cv2.imshow("preview", frame)
rval, frame = vc.read()
key = cv2.waitKey(20)
if key == 27: # exit on ESC
break
这应该会显示流。如果您的计算机连接或集成了网络摄像头,则可能需要将 cameraID 更改为 0 以外的值。在我的开发机器上,PureThermal 板的 ID 是 1。
方法
OpenCV 的网络摄像头捕获代码无法捕获辐射热数据,这是用于人数统计的理想格式,但它也可以从 PureThermal 板捕获彩色馈送,这将足够用一点预处理来绘制轮廓。
具体来说,人体倾向于在默认颜色调色板中呈现非常明亮的画面,因此将 RGB 图像转换为 HSV 并观察 V 通道可以非常清楚地看到体温物体在场景中的位置。
尝试将 cv2.imshow("preview", frame) 与以下内容互换:
frame_hsv = cv2.cvtColor(frame, cv2.COLOR_RGB2HSV)
frame_v = frame_hsv[:,:,2]
cv2.imshow("preview", frame_v)
现在可以很明显地看到人员在哪里,我们有一些可以用计算机视觉实现的东西。
输入 OpenCV
OpenCV 是非常流行的 C++ 计算机视觉库,与 Python 绑定。它提供多种常见的计算机视觉操作,可以很好地用于绘制我们的轮廓。
我们将从 Canny 边缘检测开始。它是在图像中查找边缘的强大技术。
可以使用以下代码查看 OpenCV 检测到的边缘:
thresh = 50
edges = cv2.Canny(frame_v,thresh,thresh*2, L2gradient=True)
cv2.imshow("preview", edges)
但这看起来不够好。边缘检测拾取了过多的高频噪声并将其误认为是边缘。利用图像平滑应该能够解决这个问题。使用称为“双边滤波器”的边缘保留图像平滑方法。这就像是高斯模糊,但它对我们首先要寻找的边缘的影响较小。
blurredBrightness = cv2.bilateralFilter(frame_v,9,150,150)
thresh = 70
edges = cv2.Canny(blurredBrightness,thresh,thresh*2, L2gradient=True)
cv2.imshow("preview", edges)
这看起来好多了,但仍有改进的空间。让我们试着减少像灯光被勾勒成人体这样的情况。这很棘手,但 OpenCV 提供了一种方法。首先,我们将通过对原始图像进行阈值设置,并在像素温暖的地方放置 1,在像素不温暖的地方放置 0,以创建二进制图像。然后,我们将使用 OpenCV 来消除该操作创建的 1 的斑点。之后,再次将这些斑点扩展到与之前大致相同的大小。
_,mask = cv2.threshold(blurredBrightness,200,1,cv2.THRESH_BINARY)
erodeSize = 5
dilateSize = 7
import numpy as np
eroded = cv2.erode(mask, np.ones((erodeSize, erodeSize)))
mask = cv2.dilate(eroded, np.ones((dilateSize, dilateSize)))
在腐蚀和膨胀之后,二进制图像基本保持不变,但所有的小图形都被消除了。这正是我们想要的。现在,我们可以用它遮住所有属于小图形的边缘。
让我们看看应用于检测到的边缘时的效果。
不错!它看起来也很好地覆盖在源图像上。
最终代码看起来像这样。您可能需要根据自己的喜好调整常量,OpenCV 提供了各种工具,您可以使用这些工具来改进满足特定需求的结果。
import cv2
import numpy as np
cv2.namedWindow("preview")
cameraID = 0
vc = cv2.VideoCapture(cameraID)
if vc.isOpened(): # try to get the first frame
rval, frame = vc.read()
else:
rval = False
while rval:
frame_v = cv2.cvtColor(frame, cv2.COLOR_RGB2HSV)[:,:,2]
blurredBrightness = cv2.bilateralFilter(frame_v,9,150,150)
thresh = 50
edges = cv2.Canny(blurredBrightness,thresh,thresh*2, L2gradient=True)
_,mask = cv2.threshold(blurredBrightness,200,1,cv2.THRESH_BINARY)
erodeSize = 5
dilateSize = 7
eroded = cv2.erode(mask, np.ones((erodeSize, erodeSize)))
mask = cv2.dilate(eroded, np.ones((dilateSize, dilateSize)))
cv2.imshow("preview", cv2.resize(cv2.cvtColor(mask*edges, cv2.COLOR_GRAY2RGB) | frame, (640, 480), interpolation = cv2.INTER_CUBIC))
rval, frame = vc.read()
key = cv2.waitKey(20)
if key == 27: # exit on ESC
break