视频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模块,不需要去替换,不需要去获取值,只需要去判断下是否有匹配,同时忽略大小写就可以
后记:
当时项目经理要求去比对这些摄像头内容的时候内心是崩溃的,毕竟数量放在那,上千个呢,如果一个打开手动比较,其实是可以的,而且速度也不慢,因为打开,用眼睛看,是非常容易找到显示不同的地方的
就像手工测试的一样,虽然单调,无聊,其实本质上是效率最高的,只是往往被看不起而已
那用代码去自动打开摄像头内容,截图,这些都很简单,代码都找的到,但同样就像最简单的一个自动化代码一样,当你真的去做的时候,你就要考虑更多的东西,日志记录,截图保存等等
再加上调试的时间,效率比手工慢的多,有这个时间其实手工都比较完了,但确实可以帮助我们产出完整的报告,截图等,这点是手工无法比较的
但如果要彻底实现自动化,完全的,就又涉及到图像文字识别,这个对我来说,我可以去找现成的接口或者工具,但对于这个领域,尤其是图像识别领域,其实并不深入了解,这就是一种困境
毕竟你不是专门研究这个领域,而现在领域又接近无限细分
最后其实觉得,其实完全不需要,手工打开比较,半天就搞定的事