2017-04-13 34 views
0

我在Python中遇到了問題。這是一個很重要的地方,我用了一個intel realsense(USB攝像頭)流。使用opencv,我創建了幾個findContours,並將輪廓的結果發送給另一個軟件。Opencv(Python)內存使用問題

問題是存在內存消耗。實際上,內存使用量每2-3秒增加0.1%。

II不知道該怎麼辦...

這是代碼(抱歉,如果這不是美麗的,但我測試了很多東西)

import numpy as np 
import random 
import socket 
import cv2 
import time 
import math 
import pickle 
import httplib, urllib 
from xml.etree import ElementTree as ET 
import logging 


logging.basicConfig(level=logging.INFO) 

try: 
    import pyrealsense as pyrs 
except: 
    print("No pyralsense Module installed!") 
#funzione per registrare gli eventi del mouse 
def drawArea(event,x,y, flag, param): 
    global fx,fy,ix,iy 

    if event == cv2.EVENT_LBUTTONDOWN: 
     ix,iy = x,y 

    elif event == cv2.EVENT_LBUTTONUP: 
     fx,fy = x,y 

def RepresentsInt(s): 
    try: 
     int(s) 
     return True 
    except ValueError: 
     return False 

quit = False 
read = False 
while read == False: 
     file = open('default.xml', 'r') 
     tree = ET.parse(file) 
     root = tree.getroot() 
     for child in root: 
      if child.tag == "intel": 
       intel = int(child[0].text) 
      elif child.tag == "output": 
       portOut = int(child[2].text) 
      elif child.tag =="source": 
       video_source = child.text 
     file.close() 
     root.clear() 
     ix,iy = -1,-1 
     fx,fy = -1,-1 
     timeNP = 10 
     last = time.time() 
     smoothing = 0.9 
     fps_smooth = 30 


     #video_source = video_source.split(",") 
     read = True 

if RepresentsInt(video_source): 
    video_source = int(video_source) 

if intel == 1: 
    pyrs.start() 
    dev = pyrs.Device(video_source) 
master = 1 
address = ('', 3333) 
broadSockListe = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
broadSockListe.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
broadSockListe.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) 
broadSockListe.bind(('',3333)) 
while True: 
    if master == 0: 
     datas, address = broadSockListe.recvfrom(1024) 

     if str(datas) == "8000": 
      separator = ":" 
      seq = (address[0],"8081") 
      masterAddr = separator.join(seq) 
      IP = str([l for l in (
      [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1], [ 
       [(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in 
       [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0]) 
      params = separator.join(("addUnit",IP,str(portOut),"camera","generalList.xml")) 
      params = urllib.urlencode({"Python":params}) 
      headers = {} 
      conn = httplib.HTTPConnection(masterAddr) 
      conn.request("POST",masterAddr ,params, headers) 
      params = separator.join(("masterIP",address[0],str(portOut)+"/","default.xml")) 
      params = urllib.urlencode({"Python":params}) 
      headers = {} 
      myip = IP + ":8081" 
      conn = httplib.HTTPConnection(myip) 
      #eseguo una post al mio server 
      conn.request("POST", myip, params, headers) 
      broadSockListe.close() 
      #imposto master a 1 per dire che l'ho registrato e posso partire col programma 
      master = 1 
    read = False 
    while read == False: 

      '''# leggo le varie impostazioni dal file default 
      file = open('default.xml','r+') 
      tree = ET.parse(file) 
      root = tree.getroot() 
      for child in root: 
       if child.tag == "modifica" and child.text == "1": 
        child.text = "0" 
        tree.write('default.xml') 
      root.clear() 
      file.close()''' 
      read = True 


    prev,prevprev,dirX,dirY = 0,0,0,0 
    spostamento = 15 
    UDP_IP = ["", ""] 
    UDP_PORT = ["", ""] 
    UDP_IP[0] = "127.0.0.1" 
    UDP_PORT[0] = 3030 
    IP_left = "127.0.0.1" 
    IP_right = "127.0.0.1" 
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
    sock.bind(("",portOut)) 
    message = "" 
    sep = "-" 
    font = cv2.FONT_HERSHEY_SIMPLEX 
    kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3)) 
    #rettangoli = [x,y,width,height,angle,box, area, contours] 
    rettangoli = [] 
    cnt = 0 
    letto = 0 
    while True: 
     now = time.time() 
     if letto < now - 2 or letto == 0 or now < letto: 
      letto = now 
      print(now) 
      read = False 
      while read == False: 
        file = open('default.xml', 'r') 
        tree = ET.parse(file) 
        root = tree.getroot() 
        for child in root: 
         if child.tag == "output": 
          UDP_IP[1] = child[0].text 
          UDP_PORT[1] = int(child[1].text) 
         if child.tag == "effects": 
          erode = int(child[0].text) 
          erodePos = int(child[1].text) 
          erode2 = int(child[2].text) 
          erodePos2 = int(child[3].text) 
          dilate1 = int(child[4].text) 
          dilatePos1= int(child[5].text) 
          dilate2 = int(child[6].text) 
          dilatePos2 = int(child[7].text) 
          blur = int(child[8].text) 
          blurPos = int(child[9].text) 
         if child.tag == "intel": 
          val1Min = int(child[1].text) 
          val1Max = int(child[2].text) 
          val2Min = int(child[3].text) 
          val2Max = int(child[4].text) 
          val3Min = int(child[5].text) 
          val3Max = int(child[6].text) 
         if child.tag == "modifica": 
          if child.text == "1": 
           break 
         #definisco dimensioni per collisioni 
         if child.tag == "size": 
          blobSize= int(child[0].text) 
          dimBordoBlob= int(child[1].text) 
         if child.tag == "visualizza": 
          visualizza= child.text 
         if child.tag == "feedback": 
          SFB = int(child.text) 
        root.clear() 
        file.close() 
        read = True 
     dev.wait_for_frame() 
     c = dev.colour 
     c = cv2.cvtColor(c, cv2.COLOR_RGB2BGR) 
     d = dev.depth * dev.depth_scale * -60 
     d = d[5:485, 25:635] 
     d = cv2.applyColorMap(d.astype(np.uint8), cv2.COLORMAP_HSV) 
     c = cv2.resize(c, (320 ,240), interpolation=cv2.INTER_AREA) 
     d = cv2.resize(d, (320,240), interpolation=cv2.INTER_AREA) 
     #trasformo i colori in HSV per filtrarli 
     frame = cv2.cvtColor(d, cv2.COLOR_BGR2HSV) 
     lower_red = np.array([val1Min, val2Min, val3Min]) 
     upper_red = np.array([val1Max, val2Max, val3Max]) 
     frame = cv2.inRange(frame, lower_red, upper_red) 
     dimensions = frame.shape 
     widthStream = dimensions[1] 
     heightStream = dimensions[0] 
     roomFrame = np.zeros((heightStream,widthStream, 3), np.uint8) 
     roomFrame[:] = (0, 0, 0) 
     fgmask = frame 
     halfheight = int(heightStream/2) 
     halfwidth = int(widthStream/2) 
     for i in range(0, 15): 
      if erode >= 1 and erodePos == i: 
       fgmask = cv2.erode(fgmask, kernel, iterations=erode) 
      if dilate1 >= 1 and dilatePos1 == i: 
       fgmask = cv2.dilate(fgmask, kernel, iterations=dilate1) 
      if erode2 >= 1 and erodePos2 == i: 
       fgmask = cv2.erode(fgmask, kernel, iterations=erode2) 
      if dilate2 >= 1 and dilatePos2 == i: 
       fgmask = cv2.dilate(fgmask, kernel, iterations=dilate2) 
      if blur == 1 and blurPos == 1: 
       fgmask = cv2.GaussianBlur(fgmask, (5, 5), 0) 
     if ix > fx: 
      temp = fx 
      fx = ix 
      ix = temp 
     if iy > fy: 
      temp = fy 
      fy = iy 
      iy = temp 
     if cnt == 0: 
      ix,iy = 1,1 
      fx,fy = widthStream-1,heightStream-1 
     fgmask, contours, hierarchy = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 
     rettangoli = [] 
     for cont in contours: 
      rect = cv2.minAreaRect(cont) 
      box = cv2.boxPoints(rect) 
      box = np.int0(box) 
      width = rect[1][0] 
      height = rect[1][1] 
      angle = rect[2] 
      if width > height: 
       angle = 180 + angle 
      else: 
       angle = 270 + angle 
      x, y, w, h = cv2.boundingRect(cont) 
      centerX = int(w/2 + x) 
      centerY = int(h/2 + y) 
      M = cv2.moments(cont) 
      area = int(M['m00']) 
      if area > blobSize: 
       if ix < centerX < fx and iy < centerY < fy: 
        cv2.drawContours(fgmask, [cont], 0, (100, 100, 100), dimBordoBlob) 
        cv2.drawContours(fgmask, [cont], 0, (255, 255, 255), -1) 
        rettangoli.append([centerX, centerY, w, h, angle, box, area, cont]) 
     indice = 0 
     fgmask, contours, hierarchy = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS) 
     if intel == 1: 
      fgmask = cv2.cvtColor(fgmask, cv2.COLOR_GRAY2RGB) 
     rettangoli = [] 
     for cont in contours: 
      rect = cv2.minAreaRect(cont) 
      box = cv2.boxPoints(rect) 
      box = np.int0(box) 
      width = rect[1][0] 
      height = rect[1][1] 
      angle = rect[2] 
      if width > height: 
       angle = 180 + angle 
      else: 
       angle = 270 + angle 
      x, y, w, h = cv2.boundingRect(cont) 
      centerX = int(w/2 + x) 
      centerY = int(h/2 + y) 
      M = cv2.moments(cont) 
      indice += 1 
      if M['m00'] > blobSize: 
       if ix < centerX < fx and iy < centerY < fy: 
        rettangoli.append([centerX, centerY, w, h, angle, box, int(M['m00']), cont]) 
        cv2.drawContours(roomFrame, [cont], 0, (255, 255, 255), -1) 
     for rett in rettangoli: 
      seq = (message,np.array_str(rett[7])) 
      message = sep.join(seq) 
     temp = 0 
     while temp < len(UDP_IP): 
      sock.sendto(bytes(message), (UDP_IP[temp], UDP_PORT[temp])) 
      temp += 1 
     message = "" 
     if SFB == 1: 
      cv2.imshow("Camera Intel", roomFrame) 
     if cv2.waitKey(1) & 0xFF == ord('r'): 
      break 
     if cv2.waitKey(1) & 0xFF == ord('q'): 
      quit = True 
      break 
     name = "color.jpeg" 
     cv2.imwrite(name, c) 
     name = "bn.jpeg" 
     cv2.imwrite(name, roomFrame) 
    if intel == 0: 
     cap.release() 
    cv2.destroyAllWindows() 

回答

0

你正在創造新的你的while循環中的對象。現在舉個例子,你創建一個變量,然後給它分配一個新的對象,它只存在於那個循環中。如果在循環之前聲明變量,則相同的對象將被覆蓋而不是重新創建。

通過只需提前聲明變量name = None,您將能夠確保您重用這些變量。

我希望這對你有用。

+0

嗨,thansk的答案。所以你說我應該在這段時間之外聲明所有變量?我明白了嗎? 我會嘗試... –

+0

任何變量,你不想創建一個新的實例,但只是覆蓋舊的,是的。 Python爲你做所有的內存管理,但你必須給它一些工作。通常變量只能存在於循環內部,但通過永不離開循環,我可以想象它們沒有被正確丟棄。 如果你像intellij那樣調試你的代碼,你也可以看到內存中有什麼對象,這也會幫助你找到罪魁禍首。 –