基于网络监听的摄像头遮挡检测

本文由本人原创,仅作为自己的学习记录

最近研究物联网安全,需求之一就是要实现摄像头遮挡的检测,调研了很久,很多都是基于视频帧分析的,这样不仅处理繁琐,而且对不同编码格式的视频处理也不尽相同,结合最近在学习图像处理的东东,脑洞一开,能不能通过监听网络上的视频流,从而还原出视频,再进一步提取关键帧图像,通过对比遮挡前后图像的相似度,进而判断摄像头是否被遮挡呢?下面是我的实现步骤。

有人说摄像头都有遮挡报警设置,为什么还要做这个?这个....我也不知道,客户就是上帝,上帝让你做,就得做。言归正传。

由于网络设备时串行部署在网络中,作为网络转发设备,对硬件资源的占用一定要慎重,所以,通过直接向摄像头获取视频数据这种方式被放弃,能不能通过tcpdump监听网络流量,进而把RTP的视频流保存为视频文件呢?网上还真有真有的工具,videosnarf就是其中之一,具体实现大家可以自行百度,这里不做详细介绍,上代码:

    def __init__(self, pcap_time, percent):
        self.pcap_time = pcap_time
        self.percent = int(percent)
        self.pcap_filename = '/tmp/udp_rtp.pcap'
        self.vodiodir = '/tmp/vodio/'

      初始化目录
        if not os.path.exists(self.vodiodir):
            os.mkdir(self.vodiodir)                     
        self.picturedir = '/tmp/picture/'
        if not os.path.exists(self.picturedir):
            os.mkdir(self.picturedir)                     
        self.picture_predir = '/tmp/picture_pre/'
        if not os.path.exists(self.picture_predir):
            os.mkdir(self.picture_predir)  

     抓取数据包

    def get_pcap(self):
        print 'begin packet capture'

       在这里,抓包只为了获取视频数据,进而获取图像,所以,抓包时间尽可能的短一些,避免占用系统资源
        command = 'timeout -t ' + self.pcap_time + ' /usr/sbin/tcpdump -i any udp -w ' + self.pcap_filename
        print command
        os.system(command)

     将数据包转换成视频文件
    def trans_pcap_to_h264file(self):
        print 'begin trans pcap to h264'
        command = ' ./videosnarf -i ' + self.pcap_filename + ' -o ' + self.vodiodir
        print command
        os.system(command)

下一步是如何从视频文件中提取图片,继续找工具,强大的ffmpeg实现了这个功能,能够根据需要对视频进行截图,代码如下:

    def get_picture_from_vodio(self):
        print 'begin get picture from vodio'
        vodio_list = os.listdir(self.vodiodir)
        for i in vodio_list:
            command = './ffmpeg -i ' + self.vodiodir + i + ' -r 1 -f image2 ' + self.picturedir + i.split('_')[0] + '_%4d.jpeg'
            print command
            os.system(command)

到这里基本上完成了图像的提取工作,下一步就是要针对前后两次的图像就行对比,然后就可以根据设定的相似度进行摄像头遮挡的检测,同样的,也可以实现对对移动物体的检测哦,如何实现大家自行补脑吧。

python对图像的处理有很多开源的库,这里使用了pil库,首先提取图片的框架图,大家对比下面两幅图片:

第一幅是正常图片,第二幅是提取的框架图,很简单,通过计算第二幅图的黑白点个数,即可得到图的灰度值,比较前后两次抓取图片的灰度值,即可得到图片的相似度,是不是so easy!!

def getGray(image_file):
   tmpls=[]
   for h in range(0,  image_file.size[1]):#h
      for w in range(0, image_file.size[0]):#w
         tmpls.append( image_file.getpixel((w,h))  )                          
   return tmpls                 
def getAvg(ls):#获取平均灰度值
   return sum(ls)/len(ls)
 
def getMH(a,b):#比较字符有几个字符相同
   dist = 0;
   for i in range(0,len(a)):
      if a[i]==b[i]:
         dist=dist+1
   return dist
 
def getImgHash(fne):
   image_file = Image.open(fne) # 打开
   image_file=image_file.resize((12, 12))#重置图片大小我12px X 12px
   image_file=image_file.convert("L")#转256灰度图
   Grayls=getGray(image_file)#灰度集合
   avg=getAvg(Grayls)#灰度平均值
   bitls=''#接收获取0或1
   #除去变宽1px遍历像素
   for h in range(1,  image_file.size[1]-1):#h
      for w in range(1, image_file.size[0]-1):#w
         if image_file.getpixel((w,h))>=avg:#像素的值比较平均值 大于记为1 小于记为0
            bitls=bitls+'1'
         else:
            bitls=bitls+'0'
   return bitls

程序运行结果如下:

设置抓包时间3秒 相似度低于80%为遮挡

themis:~# python camera_cover_dect.py  3 80
begin packet capture
timeout -t 3 /usr/sbin/tcpdump -i any udp -w /tmp/udp_rtp.pcap
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
2604 packets captured
2621 packets received by filter
12 packets dropped by kernel
begin trans pcap to h264
 ./videosnarf -i /tmp/udp_rtp.pcap -o /tmp/vodio/

begin get picture from vodio
./ffmpeg -i /tmp/vodio/10.50.10.36_3.264 -r 1 -f image2 /tmp/picture/10.50.10.36_%4d.jpeg

./ffmpeg -i /tmp/vodio/10.30.10.211_2.264 -r 1 -f image2 /tmp/picture/10.30.10.211_%4d.jpeg

begin clean vodio
rm -f /tmp/vodio/*
begin compare picture
192.168.28.189_0001.jpeg
ls /tmp/picture/ | grep 192.168.28.189
    192.168.28.189_0001.jpeg Similarity degree:80%

设置抓包时间3秒 相似度低于98%为遮挡
themis:~# python camera_cover_dect.py  3 98
begin packet capture
timeout -t 3 /usr/sbin/tcpdump -i any udp -w /tmp/udp_rtp.pcap
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
2730 packets captured
2758 packets received by filter
28 packets dropped by kernel
begin trans pcap to h264
 ./videosnarf -i /tmp/udp_rtp.pcap -o /tmp/vodio/

begin get picture from vodio
./ffmpeg -i /tmp/vodio/192.168.88.226_2.264 -r 1 -f image2 /tmp/picture/192.168.88.226_%4d.jpeg

./ffmpeg -i /tmp/vodio/192.168.28.189_1.264 -r 1 -f image2 /tmp/picture/192.168.28.189_%4d.jpeg

begin clean vodio
rm -f /tmp/vodio/*
begin compare picture
192.168.28.189_0001.jpeg
ls /tmp/picture/ | grep 192.168.28.189
    192.168.28.189_0001.jpeg Similarity degree:73%
    camare 192.168.28.189 is covered!!!
达到预定目标,实现了基于流量监听的摄像头遮挡检测,是不是很简单。

感谢开源工具videosnarf ffmpeg tcpdump,感谢用户提出这么奇葩的要求。相关代码资源可以在一下链接下载,有问题欢迎大家交流。

如需源码,请联系本人 zhang_peng18@163.com


版权声明:本文为a414065310原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。