视频rtsp读取和比对

上个月遇到的一个问题

背景:
     业务中,用户部署了上千个摄像头,摄像头的视频来源是一个rstp的地址,如果手动检查每个摄像头是否可以正常加载会非常浪费时间
     是否可以通过python来自动判断rstp地址是否有效
     在视频画面中会打码信息,如路段信息,但布置的摄像头可能会不匹配,那再进一步,我们是否可以通过画面进行自动判断是否匹配
实现rtsp自动播放和截图:
   
   要读取rtsp的视频,可以使用第三方的cv2的库
    import  import cv2
    通过read()进行持续读取,然后循环播放每一帧
    如果遇到q或者到了5秒,则自动关闭
    通过每一秒都可以自动截图
    先尝试连接摄像头,参数就是rstp的地址
    cap = cv2.VideoCapture(rtspurl) #尝试连接摄像头
    连接摄像头的时候,可能会失败,此时使用isOpened(),可以进行判断,如果isOpened()无法打开,则抛出异常
    表示摄像头无法链接
    if not cap.isOpened(): #如果摄像头没有打开,则抛出异常
            raise SystemError('打开摄像头失败')
    else:
          #如果正常打开,则继续执行
    except SystemError as error:
        errormessage=str(error)+'/'+devicename+"/"+rtspurl+'/'+getnow()
        writetologfile(run.LOGFILE, errormessage)
        time.sleep(2)
  如果摄像头可以正常打开,则继续执行
 #尝试读取摄像头的帧
        ret, frame = cap.read()
循环读取read(),返回ret,frame
#循环读取播放
 while ret:
          ret, frame = cap.read()
        cv2.imshow("frame", frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
                break
 imshow,就是通过窗口显示视频的帧的信息,参数为就是read返回的frame
 执行imshow之后必须跟上waitkey
 这个函数是在给定的时间内等待用户按钮触发,如果用户没有按下键,则继续等待
 0xFF == ord('q'):表示如果检测到按q,则退出整个while循环
 当显示的每一帧画面,我们可以保存到本地
 cv2.imencode('.jpg', frame)[1].tofile(jpgfile) #保存帧文件
 参数还是frame,tofile()中保存的是文件的绝对路径,一般为了防止重复,可以通过拼接当前的时间来进行生成文件名
 jpgfile = devicepath + "\\" + datetime.datetime.now().strftime("%Y%m%d%H%M%S") + ".jpg"
 如果要实现自定的到五秒自动退出
 应该在一开始读取帧的时候就先记录下当前的时间
 然后每次循环都去减去开始的时间
starttime=datetime.datetime.now()  #开始时间
while ret:
  ...
  endtime = datetime.datetime.now()  #计算循环的时候的时间
 timegap = (endtime - starttime).seconds #计算时间差  
 #相减之后,返回相差的秒数
    if timegap==5: #如果相差已到了5秒则自动结束,同样就是跳出循环
                  break
当然代理里还需要处理其他一些事情,如记录log,通过csv文件导入所有的rtsp的地址,创建目录,保存截图
这些通过csv库,os库都可以实现
图片文字识别
     rtsp播放截图,可以观察到画面中显示的打码的文字信息
     如K27+100,那么这个设备的设备名,可能也是K27+100,那么这样就证明设备和rtsp地址是匹配的
     当然可以等全部运行完成之后,一个个截图打开人工进行比对,这样速度也是很快的 
     

 

     那是否可以实现自动比对呢?

    自动比对,其实就是要识别画面中的文字,然后再和设备的名称比较
    先说第一步,识别画面中的文字, 可以使用第三方库PaddleOCR来实现,虽然不能保证百分百可靠
   安装库之后导入
    from paddleocr import PaddleOCR
    使用比较简单,只要直接传递刚才所保存的截图就可以
    通过方法直接读取,返回的是识别后画面上的所有文字信息
    循环可以读取
    ocr = PaddleOCR(use_angle_cls=True, use_gpu=False)
   text = ocr.ocr(imgfile, cls=True)
      for t in text:
          machstr=t[1][0]
 但麻烦的是,在这个画面中如果读取文字,可能读取到的是
  河北
  2022-09-27  XXXXX
  K27+100 下行 
  固定摄像机
   这样几个信息
  其中有用的信息只有K27+100
  同时导入的设备信息 K27+100-左侧-AI摄像机 
  所以判断这个是否符合就成了问题
   想到使用in进行判断,但这个很容易失败
  几个可以参考的方法
1 字符匹配度
    第三方库   
    from difflib import SequenceMatcher
  例

可以把获取的文字同设备名进行比对,看相似度

  可能到了一定阈值就可以判断为相似
2  正则表达式
    通过尝试去匹配其中桩号信息,就可以判断是否符合要求
    可以使用re模块,不需要去替换,不需要去获取值,只需要去判断下是否有匹配,同时忽略大小写就可以 

后记:

     当时项目经理要求去比对这些摄像头内容的时候内心是崩溃的,毕竟数量放在那,上千个呢,如果一个打开手动比较,其实是可以的,而且速度也不慢,因为打开,用眼睛看,是非常容易找到显示不同的地方的

    就像手工测试的一样,虽然单调,无聊,其实本质上是效率最高的,只是往往被看不起而已

    那用代码去自动打开摄像头内容,截图,这些都很简单,代码都找的到,但同样就像最简单的一个自动化代码一样,当你真的去做的时候,你就要考虑更多的东西,日志记录,截图保存等等

    再加上调试的时间,效率比手工慢的多,有这个时间其实手工都比较完了,但确实可以帮助我们产出完整的报告,截图等,这点是手工无法比较的

    但如果要彻底实现自动化,完全的,就又涉及到图像文字识别,这个对我来说,我可以去找现成的接口或者工具,但对于这个领域,尤其是图像识别领域,其实并不深入了解,这就是一种困境

    毕竟你不是专门研究这个领域,而现在领域又接近无限细分

    最后其实觉得,其实完全不需要,手工打开比较,半天就搞定的事

    

    

 

 

 

 
posted on 2022-12-08 14:24  胖虫子  阅读(265)  评论(0编辑  收藏  举报