我正在开发我的项目,我希望从我的网络摄像头捕获视频帧并发送到python中的远程客户端,我使用opencv捕获帧但我必须逐帧将其发送到远程客户端而不保存在服务器中... 我被困在这里,因为一周请帮助我 我应该将它转换为字符串以通过套接字发送吗?如果是的话怎么样? PLS帮助我,我的代码是
import cv2
import socket
import base64
host = "localhost"
port = 6052
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((host,port))
s.listen(5)
print "server started...."
#if __name__ == "__main__":
while True:
c, addr = s.accept()
print "client connected..."
capture = cv2.cv.CaptureFromCAM(0)
#cv2.cv.NamedWindow('image')
frame = cv2.cv.QueryFrame(capture)
#cv2.cv.ShowImage('image', frame)
#succ, ig = cv2.cv.LoadImage(capture)
with open(frame,"rb") as f:
es = base64.b64encode(f.read())
stri = str.decode('base64','strict')
print "string is " + stri
#with open(ig, "rb") as f:
# b = f.read(87029)
# print "data = " + b
# c.send(b)
#k = cv2.cv.WaitKey(10)
#if k % 256 ==27 :
#break
#cv2.DestroyWindow('image')
s.close()
答案 0 :(得分:1)
除了其他答案中的问题 - 你还需要修复 - 你还有另一个问题。
frame = cv2.cv.QueryFrame(capture)
open(frame,"rb")
QueryFrame
返回一个图像对象。 open
采用文件名或整数文件描述符。
如果您有一个文件,例如通过将帧保存到文件中,您将获得可以传递给open
的文件名的唯一方法。您声称自己拥有执行此操作的代码。据推测,在该代码中,您的代码与此类似:
cv2.cv.imwrite(filename, image, params)
f = open(filename, 'rb')
我不知道你使用了什么样的咒语; image
可能是您通过捕捉帧而读取的图像。
imencode
函数类似于imwrite
,除了它在缓冲区中创建内存中的图像文件,而不是将其写入磁盘。它采用与imwrite
相同的参数,除了文件扩展名而不是完整文件名(因为它不会将任何内容保存到磁盘,但它仍然需要知道什么类型的文件-PNG,JPE,等)。
所以:
buf = cv2.cv.imencode(extension, image, params)
现在,buf
是您可以传递给send
的字节。
答案 1 :(得分:0)
我认为你试图解决的问题是:
c.send(b)
如果您阅读了socket.send
的文档:
将数据发送到套接字。套接字必须连接到远程套接字。可选的标志参数与上面的
recv()
具有相同的含义。返回发送的字节数。 应用程序负责检查是否已发送所有数据;如果只传输了部分数据,则应用程序需要尝试传递剩余数据。有关此概念的更多信息,请参阅Socket Programming HOWTO。
事实上,在打开TCP套接字后立即发送大量数据正是您希望它只发送部分数据的情况。
你可以阅读链接的HOWTO,它将解释如何处理部分发送的缓冲区,但是对于你的问题,因为除了一次处理一个没有并发的客户端之外什么都不做,完成请求,并挂在它上面,文档中的下一个功能sendall
可以完成你想要的一切。
但是,这不是代码中唯一的问题。例如,下一行就是这样做的:
s.close
只需引用一个函数,而不用()
调用它,就没有效果。结果证明这是一件好事,因为如果有效果,它将关闭侦听器套接字,而不是客户端套接字。如果客户端等待关闭,它将永远等待;同时,如果第二个客户试图连接,它将被拒绝。
另外,如果你自己写了客户端,我愿意打赌你刚用b = s.recv(87029)
,这会产生同样的问题:它不一定会收到87029字节,它会接收最多的任何字节。你必须循环recv
添加到缓冲区,直到你得到足够的。有关详细信息,请参阅Sockets are byte streams, not message streams。
答案 2 :(得分:0)
import cv2
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
import time
capture=None
class CamHandler(BaseHTTPRequestHandler):
def do_GET(self):
print self.path
if self.path.endswith('.mjpg'):
self.send_response(200)
self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary')
self.end_headers()
while True:
try:
rc,img = capture.read()
if not rc:
continue
imgRGB = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
r, buf = cv2.imencode(".jpg",imgRGB)
self.wfile.write("--jpgboundary\r\n")
self.send_header('Content-type','image/jpeg')
self.send_header('Content-length',str(len(buf)))
self.end_headers()
self.wfile.write(bytearray(buf))
self.wfile.write('\r\n')
time.sleep(0.5)
except KeyboardInterrupt:
break
return
if self.path.endswith('.html') or self.path=="/":
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write('<html><head></head><body>')
self.wfile.write('<img src="http://127.0.0.1:9090/cam.mjpg"/>')
self.wfile.write('</body></html>')
return
def main():
global capture
capture = cv2.VideoCapture(0)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 320);
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 240);
try:
server = HTTPServer(('',9090),CamHandler)
print "server started"
server.serve_forever()
except KeyboardInterrupt:
capture.release()
server.socket.close()
if __name__ == '__main__':
main()