Python实现直播推流效果
首先给出展示结果,大体就是检测工业板子是否出现。采取检测的方法比较简单,用的OpenCV的模板检测。
大体思路
- opencv读取视频
- 将视频分割为帧
- 对每一帧进行处理(opencv模板匹配)
- 在将此帧写入pipe管道
- 利用ffmpeg进行推流直播
中间遇到的问题
在处理本地视频时,并没有延时卡顿的情况。但对实时视频流的时候,出现了卡顿延时的效果。在一顿度娘操作之后,采取了多线程的方法。
opencv读取视频
defrun_opencv_camera(): video_stream_path=0 #当video_stream_path=0会开启计算机默认摄像头也可以为本地视频文件的路径 cap=cv2.VideoCapture(video_stream_path) whilecap.isOpened(): is_opened,frame=cap.read() cv2.imshow('frame',frame) cv2.waitKey(1) cap.release()
OpenCV模板匹配
模板匹配就是在一幅图像中寻找一个特定目标的方法之一,这种方法的原理非常简单,遍历图像中每一个可能的位置,比较各处与模板是否相似,当相似度足够高时,就认为找到了目标。
deftemplate_match(img_rgb): #灰度转换 img_gray=cv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY) #模板匹配 res=cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED) #设置阈值 threshold=0.8 loc=np.where(res>=threshold) iflen(loc[0]): #这里直接固定区域 cv2.rectangle(img_rgb,(155,515),(1810,820),(0,0,255),3) cv2.putText(img_rgb,category,(240,600),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2) cv2.putText(img_rgb,Confidence,(240,640),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2) cv2.putText(img_rgb,Precision,(240,680),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2) cv2.putText(img_rgb,product_yield,(240,720),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2) cv2.putText(img_rgb,result,(240,780),cv2.FONT_HERSHEY_SIMPLEX,2,(0,255,0),5) returnimg_rgb
FFmpeg推流
在Ubuntu14上安装Nginx-RTMP流媒体服务器
https://www.nhooo.com/article/175121.htm
importsubprocessassp rtmpUrl="" camera_path="" cap=cv.VideoCapture(camera_path) #Getvideoinformation fps=int(cap.get(cv.CAP_PROP_FPS)) width=int(cap.get(cv.CAP_PROP_FRAME_WIDTH)) height=int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)) #ffmpegcommand command=['ffmpeg', '-y', '-f','rawvideo', '-vcodec','rawvideo', '-pix_fmt','bgr24', '-s',"{}x{}".format(width,height), '-r',str(fps), '-i','-', '-c:v','libx264', '-pix_fmt','yuv420p', '-preset','ultrafast', '-f','flv', rtmpUrl] #管道配置 p=sp.Popen(command,stdin=sp.PIPE) #readwebcamera while(cap.isOpened()): ret,frame=cap.read() ifnotret: print("Openingcameraisfailed") break #processframe #yourcode #processframe #writetopipe p.stdin.write(frame.tostring())
说明:rtmp是要接受视频的服务器,服务器按照上面所给连接地址即可。
多线程处理
pythonmutilprocessing多进程编程https://www.nhooo.com/article/134726.htm
defimage_put(q): #采取本地视频验证 cap=cv2.VideoCapture("./new.mp4") #采取视频流的方式 #cap=cv2.VideoCapture(0) #cap.set(cv2.CAP_PROP_FRAME_WIDTH,1920) #cap.set(cv2.CAP_PROP_FRAME_HEIGHT,1080) ifcap.isOpened(): print('success') else: print('faild') whileTrue: q.put(cap.read()[1]) q.get()ifq.qsize()>1elsetime.sleep(0.01) defimage_get(q): whileTrue: #start=time.time() #flag+=1 frame=q.get() frame=template_match(frame) #end=time.time() #print("thetimeis",end-start) cv2.imshow("frame",frame) cv2.waitKey(0) #pipe.stdin.write(frame.tostring()) #cv2.imwrite(save_path+"%d.jpg"%flag,frame) #多线程执行一个摄像头 defrun_single_camera(): #初始化 mp.set_start_method(method='spawn')#init #队列 queue=mp.Queue(maxsize=2) processes=[mp.Process(target=image_put,args=(queue,)), mp.Process(target=image_get,args=(queue,))] [process.start()forprocessinprocesses] [process.join()forprocessinprocesses] defrun(): run_single_camera()#quick,with2threads pass
说明:使用Python3自带的多线程模块mutilprocessing模块,创建一个队列,线程A从通过rstp协议从视频流中读取出每一帧,并放入队列中,线程B从队列中将图片取出,处理后进行显示。线程A如果发现队列里有两张图片,即线程B的读取速度跟不上线程A,那么线程A主动将队列里面的旧图片删掉,换新图片。
全部代码展示
importtime importmultiprocessingasmp importnumpyasnp importrandom importsubprocessassp importcv2 importos #定义opencv所需的模板 template_path="./high_img_template.jpg" #定义矩形框所要展示的变量 category="Category:board" var_confidence=(np.random.randint(86,98))/100 Confidence="Confidence:"+str(var_confidence) var_precision=round(random.uniform(98,99),2) Precision="Precision:"+str(var_precision)+"%" product_yield="ProductYield:100%" result="Result:perfect" #读取模板并获取模板的高度和宽度 template=cv2.imread(template_path,0) h,w=template.shape[:2] #定义模板匹配函数 deftemplate_match(img_rgb): #灰度转换 img_gray=cv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY) #模板匹配 res=cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED) #设置阈值 threshold=0.8 loc=np.where(res>=threshold) iflen(loc[0]): #这里直接固定区域 cv2.rectangle(img_rgb,(155,515),(1810,820),(0,0,255),3) cv2.putText(img_rgb,category,(240,600),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2) cv2.putText(img_rgb,Confidence,(240,640),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2) cv2.putText(img_rgb,Precision,(240,680),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2) cv2.putText(img_rgb,product_yield,(240,720),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2) cv2.putText(img_rgb,result,(240,780),cv2.FONT_HERSHEY_SIMPLEX,2,(0,255,0),5) returnimg_rgb #视频属性 size=(1920,1080) sizeStr=str(size[0])+'x'+str(size[1]) #fps=cap.get(cv2.CAP_PROP_FPS)#30p/self #fps=int(fps) fps=11 hz=int(1000.0/fps) print('size:'+sizeStr+'fps:'+str(fps)+'hz:'+str(hz)) rtmpUrl='rtmp://localhost/hls/test' #直播管道输出 #ffmpeg推送rtmp重点:通过管道共享数据的方式 command=['ffmpeg', '-y', '-f','rawvideo', '-vcodec','rawvideo', '-pix_fmt','bgr24', '-s',sizeStr, '-r',str(fps), '-i','-', '-c:v','libx264', '-pix_fmt','yuv420p', '-preset','ultrafast', '-f','flv', rtmpUrl] #管道特性配置 #pipe=sp.Popen(command,stdout=sp.PIPE,bufsize=10**8) pipe=sp.Popen(command,stdin=sp.PIPE)#,shell=False #pipe.stdin.write(frame.tostring()) defimage_put(q): #采取本地视频验证 cap=cv2.VideoCapture("./new.mp4") #采取视频流的方式 #cap=cv2.VideoCapture(0) #cap.set(cv2.CAP_PROP_FRAME_WIDTH,1920) #cap.set(cv2.CAP_PROP_FRAME_HEIGHT,1080) ifcap.isOpened(): print('success') else: print('faild') whileTrue: q.put(cap.read()[1]) q.get()ifq.qsize()>1elsetime.sleep(0.01) #采取本地视频的方式保存图片 save_path="./res_imgs" ifos.path.exists(save_path): os.makedir(save_path) defimage_get(q): whileTrue: #start=time.time() #flag+=1 frame=q.get() frame=template_match(frame) #end=time.time() #print("thetimeis",end-start) cv2.imshow("frame",frame) cv2.waitKey(0) #pipe.stdin.write(frame.tostring()) #cv2.imwrite(save_path+"%d.jpg"%flag,frame) #多线程执行一个摄像头 defrun_single_camera(): #初始化 mp.set_start_method(method='spawn')#init #队列 queue=mp.Queue(maxsize=2) processes=[mp.Process(target=image_put,args=(queue,)), mp.Process(target=image_get,args=(queue,))] [process.start()forprocessinprocesses] [process.join()forprocessinprocesses] defrun(): run_single_camera()#quick,with2threads pass if__name__=='__main__': run()
总结
以上所述是小编给大家介绍的Python实现直播推流效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。