西安企业网站搭建,如何注册网站主办者,wordpress 页面代码,淘宝网官方网站电脑版目录 0. 需求1. 基于http方式传递图片数据1.1 发送图片数据1.2 接收图片数据并可视化1.3 测试 2. 基于redis方式传递图片数据2.1 发送图片数据2.2 接收图片数据并可视化2.3 测试 3. 对比 0. 需求
在不同进程或者不同语言间传递摄像头图片数据#xff0c;比如从java实现的代码… 目录 0. 需求1. 基于http方式传递图片数据1.1 发送图片数据1.2 接收图片数据并可视化1.3 测试 2. 基于redis方式传递图片数据2.1 发送图片数据2.2 接收图片数据并可视化2.3 测试 3. 对比 0. 需求
在不同进程或者不同语言间传递摄像头图片数据比如从java实现的代码中获取摄像头画面数据将其传递给python实现的算法代码中进行处理。这里提供基于http方式和基于redis方式这两种方式进行实现并比较两者传输速度。
作为样例代码均采用python实现运行环境为ubuntu 18.04。
1. 基于http方式传递图片数据
1.1 发送图片数据 思路创建两个线程一个线程利用Opencv通过rtsp地址获得摄像头画面一个线程将摄像头图片数据转为字节流并通过http方式发送。 实现
#codinggb2312
# 文件名http_send.py
import requests
import base64
import cv2
import time
import threading
from queue import LifoQueueclass rtspRead: # rtsp地址读取def __init__(self, rtsp, port):self.rtsp rtsp # 摄像头的rtsp地址self.addr http://127.0.0.1:{}/image_post.format(port) # 本地http传输地址self.frameQueue LifoQueue() # 视频帧的队列self.frameLock threading.Lock() # 视频帧队列的锁self.threadFlag True # def start(self): # 开始t1 threading.Thread(targetself.sendFrame, args(), daemonTrue)t2 threading.Thread(targetself.readFrame, args(), daemonTrue)t1.start()t2.start()t1.join()t2.join()def sendFrame(self): # 通过http发送图片num 0 # 计算100次图片发送到接受的平均时间以及平均帧数while self.threadFlag:time.sleep(0.01)is_get_frame False # 没有从队列中获得图片self.frameLock.acquire()if self.frameQueue.qsize():frame self.frameQueue.get()is_get_frame True # 从队列中获得图片self.frameLock.release()if is_get_frame:# frame 是ndarray对象,这里是把原始ndarray转成jpg的字节流转成其它格式直接替换jpg即可img_str cv2.imencode(.jpg, frame)[1].tobytes()#使用b64encode对bytes-like类型对象进行编码(加密)并返回bytes对象img_data base64.b64encode(img_str)data {img: img_data}resp requests.post(self.addr, datadata) # 发送图片数据并获得http_receive.py的返回信息print(结果, resp.text)def readFrame(self): # 通过rtsp读取图片self.cap cv2.VideoCapture(self.rtsp)if self.cap.isOpened():time.sleep(0.01)print(成功获得句柄)while self.threadFlag:ret, frame self.cap.read()if ret:self.frameLock.acquire()while self.frameQueue.qsize() 3: # 尽量确保队列中为最新的图片帧self.frameQueue.get()self.frameQueue.put(frame)self.frameLock.release() else:print(句柄获得失败)self.threadFlag Falseself.cap.release()if __name__ __main__:rtsp_read rtspRead(rtsp://xx:xxxx, 9322) rtsp_read.start()1.2 接收图片数据并可视化 思路通过flask框架接收http请求并将接收到的图片数据的字节流转为np格式并进一步转为opencv格式。另起一个线程接收opencv格式的图片数据并做显示。 实现
#codinggb2312
# 文件名http_receive.py
from flask import Flask, request
import base64
import numpy as np
import cv2
import threading
from queue import LifoQueue
import timeclass RtspPlay():def __init__(self):self.frame None # 视频帧self.threadFlag True # def start(self): # 开始t1 threading.Thread(targetself.play, args(), daemonTrue)t1.start()#t1.join()def play(self):starttime time.time()while self.threadFlag:time.sleep(0.01)print(进入展示线程)if time.time() - starttime 260:self.threadFlag Falseif self.frame is not None:print(展示frame)cv2.imshow(http_pic, self.frame)if cv2.waitKey(1) 0xFF ord(q):breakcv2.destroyAllWindows()def setFrame(self, img):print(更新frame)self.frame img.copy()rtspPlay RtspPlay()
rtspPlay.start()app Flask(__name__)
app.route(/image_post, methods[POST])
def img_post():if request.method POST:# 获取图片数据img_base64 request.form.get(img)# 把图片的二进制进行转化img_data base64.b64decode(img_base64) #将拿到的base64的图片转换回来img_array np.fromstring(img_data,np.uint8) # 转换np序列img cv2.imdecode(img_array,cv2.COLOR_BGR2RGB) # 转换Opencv格式mat cv2.resize(img, (600, 600))print(mat.shape)rtspPlay.setFrame(mat)time.sleep(0.01)return receive img sucessif __name__ __main__:app.run(host127.0.0.1, port9322)
1.3 测试
# 先开一个terminal窗口启用接收进程
python http_receive.py# 再开一个terminal窗口启用发送进程
python http_send.py2. 基于redis方式传递图片数据
2.1 发送图片数据 思路创建两个线程一个线程利用Opencv通过rtsp地址获得摄像头画面一个线程将摄像头图片数据转为字节流并通过redis方式发送。这里的redis方式具体指的是redis是一个内存数据库通过键值对存储数据通过订阅/发布机制传递消息所以将图片字节流数据存入redis中并将存入消息发布出去实现发送效果。 实现
#codinggb2312
# 文件名redis_send.py
import redis
import cv2
import time
import base64
import threading
from queue import LifoQueueclass redisSendPic: # redis发布者def __init__(self, cameraip):print(redis init ...)self.r redis.Redis(host127.0.0.1, port6379,db0) # 建立连接self.topic img0 # 订阅的主题self.cameraip cameraipdef send(self, img):#print(发送图片)img_str cv2.imencode(.jpg, img)[1].tobytes()data base64.b64encode(img_str)self.r.set(self.cameraip, data)self.r.publish(self.topic, self.cameraip)def getResult(self,): result self.r.get(result) return resultdef delete(self):self.r.delete(result)self.r.delete(self.cameraip)class rtspRead: # rtsp地址读取def __init__(self, rtsp, cameraip):self.rtsp rtspself.cameraip cameraipself.frameQueue LifoQueue() # 视频帧的队列self.frameLock threading.Lock() # 视频帧队列的锁self.threadFlag True # def start(self): # 开始t1 threading.Thread(targetself.sendFrame, args(), daemonTrue)t2 threading.Thread(targetself.readFrame, args(), daemonTrue)t1.start()t2.start()t1.join()t2.join()def sendFrame(self): # 通过redis发送图片self.sendpic redisSendPic(self.cameraip)self.sendpic.r.set(result, start)num 0 # 计算100次图片发送到接受的平均时间以及平均帧数total_time 0while self.threadFlag:time.sleep(0.01)is_get_frame False # 没有从队列中获得图片self.frameLock.acquire()if self.frameQueue.qsize():frame self.frameQueue.get()is_get_frame True # 从队列中获得图片self.frameLock.release()result self.sendpic.getResult() # 从接受进程获得是否中止的信号if result is not None and str(result, utf-8) stop:self.threadFlag False breakif is_get_frame:self.sendpic.r.delete(receive_time) # 删除接受时间send_time time.time() # 发送时间self.sendpic.send(frame) # 发送图片receive_time self.sendpic.r.get(receive_time) # 获得接受图片时间while receive_time is None: # 等待接受图片#print(等待接受)time.sleep(0.01)receive_time self.sendpic.r.get(receive_time)result self.sendpic.getResult() # 从接受进程获得是否中止的信号if result is not None and str(result, utf-8) stop:self.threadFlag False breakif receive_time is not None:total_time float(str(receive_time, utf-8)) - send_time#print(图像发送到接受时间, float(str(receive_time, utf-8)) - send_time)num 1if num 100:print(发送收发100次平均耗时{}s平均速度为{}帧/秒.format(total_time/100, round(100/total_time,2)))num 0total_time 0self.sendpic.delete()def readFrame(self): # 通过rtsp读取图片self.cap cv2.VideoCapture(self.rtsp)if self.cap.isOpened():time.sleep(0.01)print(成功获得句柄)while self.threadFlag:ret, frame self.cap.read()if ret:self.frameLock.acquire()while self.frameQueue.qsize() 3: # 尽量确保队列中为最新的图片帧self.frameQueue.get()self.frameQueue.put(frame)self.frameLock.release() else:print(句柄获得失败)self.threadFlag Falseself.cap.release()if __name__ __main__:rtsp_read rtspRead(rtsp://xx:xxxx, xx) rtsp_read.start()
2.2 接收图片数据并可视化 思路通过redis数据库的消息监听机制当接收到数据入库消息则提取图片字节流数据并将其处理为opencv格式的图片数据从而做到显示。 实现
#codingutf-8
# 文件名redis_receive.py
import redis
import time
import scipy.misc
import cv2
import base64
from PIL import Image
import io
import time
import scipy.misc
import numpy as npr redis.Redis(host127.0.0.1,port6379,db0)
ps r.pubsub()
charecter img
ps.subscribe(charecter str(0))is_first Truefor item in ps.listen():print(get message, , item)#r.set(result, str(ok))if is_first:r.set(receive_time, str(time.time())) # 获得可处理图片时间is_first False start time.time()if item[type] message and item[data] is not None:img_base64 r.get(str(item[data], utf-8))img_data base64.b64decode(img_base64) #将拿到的base64的图片转换回来img_array np.fromstring(img_data,np.uint8) # 转换np序列img cv2.imdecode(img_array,cv2.COLOR_BGR2RGB) # 转换Opencv格式r.set(receive_time, str(time.time())) # 获得可处理图片时间mat cv2.resize(img, (600, 600))print(mat.shape)cv2.imshow(redis_pic, mat)if cv2.waitKey(1) 0xFF ord(q):break#scipy.misc.imsave(D:/video.png, img)# frame cv2.resize(img_data, (0, 0), fx0.5, fy0.5)#r.delete(charecter str(0))#r.set(result, str(ok))print(cost time:, time.time() - start)cv2.destroyAllWindows()
r.set(result, str(stop))
2.3 测试
# 先开一个terminal窗口启用接收进程
python redis_receive.py# 再开一个terminal窗口启用发送进程
python redis_send.py结束进程直接在显示窗口上按下q键即可。
3. 对比
综合来看在可视化摄像头画面的前提下两者均可做到实时显示。其中采用redis方式速度为14帧/秒左右采用http方式速度为10帧/秒左右。
若要提高速度可取消base64的加密过程若仅考虑传输可取消其中的可视化部分传输速度应该会进一步提高。