2014-09-21 67 views
-2

我對我的項目工作,其中II想從我的攝像頭拍攝的視頻幀,發送到遠程客戶端的蟒蛇,我使用OpenCV中捕捉幀,但我已經把它發送到遠程客戶端框架框架沒有保存在服務器... 我被困在這裏,因爲一週請幫我 我應該將它轉換爲字符串通過套接字發送?如果是,那麼如何? PLS幫我我的代碼是轉換爲字符串在python

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

究竟是_proble m_與此代碼?它做錯了什麼? – abarnert 2014-09-21 01:10:55

+0

問題發生在c.send(b)行,它表示必須輸入錯誤,我無法將幀發送給客戶端.. – Learner 2014-09-21 01:15:54

+0

那麼,_什麼是'b'?_粘貼異常和回溯,並告訴我們「b」的類型是什麼。 (如果你不知道,只需要問Python:'print(type(b))'。另外,告訴我們這是Python 2.x還是3.x.給我們一些實際運行的代碼,如果你想要任何人幫助你調試它;這段代碼只給出了'ig'變量上的'NameError'。 – abarnert 2014-09-21 01:20:00

回答

0

我認爲你正在試圖解決的問題是在這裏:

c.send(b) 

如果你閱讀文檔的socket.send

Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. For further information on this concept, consult the Socket Programming HOWTO .

而且實際上,在打開TCP套接字時立即發送大量數據正是這種情況,您希望它只發送一部分數據。

您可以閱讀鏈接的HOWTO,它將解釋如何處理部分發送的緩衝區,但是針對您的問題,因爲除了一次處理一個客戶端而沒有併發,完成請求以外,掛在它上面,文檔中的下一個功能sendall可以完成你想要的任何功能。


但是,這不是您的代碼中唯一的問題。例如,在下一行做到這一點:

s.close 

只是引用功能,而不()調用它,沒有任何作用。事實證明這是一件好事,因爲如果這個有效果,那麼將會關閉聽衆套接字,而不是客戶端套接字。如果客戶等待關機,它將永遠等待;同時,如果第二個客戶端嘗試連接,它將被拒絕。


另外,如果你寫的客戶端自己,我願意打賭,你剛纔用b = s.recv(87029),這都將有同樣的問題:它並不一定會接受87029個字節,它會收到什麼高達那麼多字節。您必須將recv循環添加到緩衝區中,直到您獲得足夠的空間。有關更多詳細信息,請參閱Sockets are byte streams, not message streams

+0

如果圖像已經被保存,我可以發送,但是我不能發送捕獲的幀而不保存它..幫助我代碼,thanx for ur help ..示例代碼讚賞... – Learner 2014-09-21 01:20:16

+0

@Learner:你有什麼試圖發送捕獲的幀?你的代碼顯示你正在調用['QueryFrame'](http://docs.opencv.org/ modules/highgui/doc/reading_and_writing_images_and_video.html#cv.QueryFrame)來獲取一個圖像對象。你用什麼代碼來獲取字節?如果你沒有向我們展示它,而是向我們展示不同的代碼,一個文件,怎麼能有人調試它? – abarnert 2014-09-21 01:24:28

+0

是我寫了客戶端也..爲行b = s.recv(87029)我發送已保存的圖像在我的電腦,它是我爲靜態目前的數據,罰款罰款,但我的問題是我不想保存這些幀,只是捕獲併發送到客戶端,我該怎麼做? – Learner 2014-09-21 01:25:10

1

除了其他答案中的問題 - 您仍需修復 - 您有另一個問題。

frame = cv2.cv.QueryFrame(capture) 
open(frame,"rb") 

QueryFrame返回圖像對象。 open需要一個文件名或一個整數文件描述符。圖像對象顯然不是文件名,所以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字節。

+0

因爲我是新來的蟒蛇我不知道太多,在簡單我想發送的圖像是從我的攝像頭沒有保存到客戶端,一段時間以爲客戶端瀏覽器希望你現在可以幫助我.. - – Learner 2014-09-21 01:31:39

+0

@Learner:我不知道什麼「一段時間以爲客戶端爲瀏覽器」的含義。瀏覽器不會生成原始套接字調用,它會發出HTTP請求。如果你想構建一個Web服務器,你必須這樣做(或者更好的方法是使用一個可以爲你做的框架)。 – abarnert 2014-09-21 03:25:16

1
  • 請,永遠不會嘗試將圖像轉換爲字符串,這是一個完全浪費。
  • 是的,你將不得不編碼圖像的FOM的攝像頭,但爲Base64(相反,你需要的圖像,你的客戶可以閱讀,就像在內存中的PNG)
  • 不使用棄用cv2.cv API,它很快就會消失(OpenCV的3.0)
  • 堅持一個衆所周知的協議,像MJPEG

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()