在python中将变量从类内的函数转换为单独的类函数

在python中将变量从类内的函数转换为单独的类函数,python,function,class,variables,computer-vision,Python,Function,Class,Variables,Computer Vision,我有两个python文件,其中包含两个类。我想把一个类中一个函数中的变量转换成另一个类中的函数 具体来说,类CaptureFrames创建一个名为frames\u count的变量,该变量跟踪正在处理的视频的当前帧。类ProcessMasks对帧进行处理并返回变量hr\u fft。当这个变量返回时,我想创建一个元组,其中包含hr\u fft和frames\u count变量,这样我就可以跟踪与hr\u fft变量相关联的特定帧 我试着将它标记为CaptureFrames.frames\u cou

我有两个python文件,其中包含两个类。我想把一个类中一个函数中的变量转换成另一个类中的函数

具体来说,类
CaptureFrames
创建一个名为
frames\u count
的变量,该变量跟踪正在处理的视频的当前帧。类
ProcessMasks
对帧进行处理并返回变量
hr\u fft
。当这个变量返回时,我想创建一个元组,其中包含
hr\u fft
frames\u count
变量,这样我就可以跟踪与
hr\u fft
变量相关联的特定帧

我试着将它标记为
CaptureFrames.frames\u count
CaptureFrames.capture\u frames.frames\u count
,但它不起作用。我该怎么做

这些类如下所示:

import cv2
import numpy as np
import torch
from torch import nn
from models import LinkNet34
import torchvision.transforms as transforms
from torch.autograd import Variable
from PIL import Image, ImageFilter
import time
import sys

class CaptureFrames():

    def __init__(self, bs, source, show_mask=False):
        self.frame_counter = 0
        self.batch_size = bs
        self.stop = False
        self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
        self.model = LinkNet34()
        self.model.load_state_dict(torch.load('linknet.pth', map_location='cpu'))
        self.model.eval()
        self.model.to(self.device)
        self.show_mask = show_mask
        
    def __call__(self, pipe, source):
        self.pipe = pipe
        self.capture_frames(source)
  
    def capture_frames(self, source):
        
        img_transform = transforms.Compose([
            transforms.Resize((256,256)),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
        ])
    
        camera = cv2.VideoCapture(source)
        time.sleep(1)
        self.model.eval()
        (grabbed, frame) = camera.read()
        time_1 = time.time()

        #######################################################

        self.frames_count = 0

        #######################################################

        while grabbed:
            
            (grabbed, orig) = camera.read()
            if not grabbed:
                continue
            
            shape = orig.shape[0:2]
            frame = cv2.cvtColor(orig, cv2.COLOR_BGR2RGB)
            frame = cv2.resize(frame,(256,256), cv2.INTER_LINEAR )
            
            
            k = cv2.waitKey(1)
            if k != -1:
                self.terminate(camera)
                break

            a = img_transform(Image.fromarray(frame))
            a = a.unsqueeze(0)
            imgs = Variable(a.to(dtype=torch.float, device=self.device))
            pred = self.model(imgs)
            
            pred= torch.nn.functional.interpolate(pred, size=[shape[0], shape[1]])
            mask = pred.data.cpu().numpy()
            mask = mask.squeeze()
            
            # im = Image.fromarray(mask)
            # im2 = im.filter(ImageFilter.MinFilter(3))
            # im3 = im2.filter(ImageFilter.MaxFilter(5))
            # mask = np.array(im3)
            
            mask = mask > 0.8
            orig[mask==0]=0
            self.pipe.send([orig])

            if self.show_mask:
                cv2.imshow('mask', orig)
            
            if self.frames_count % 30 == 29:
                time_2 = time.time()
                sys.stdout.write(f'\rFPS: {30/(time_2-time_1)}')
                sys.stdout.flush()
                time_1 = time.time()

        #######################################################

            self.frames_count+=1

        #######################################################

        self.terminate(camera)

    
    def terminate(self, camera):
        self.pipe.send(None)
        cv2.destroyAllWindows()
        camera.release()


也许有一点建议-如果你有一个复杂的代码,但你想实现一些简单的效果,建立一个玩具模型(两个非常简单的类,每个类只有一个变量和一个函数),并尝试在那里实现你的解决方案-你会学到很多,并且有更好的机会真正了解发生了什么事情+1。我认为有一种更简单的方法来做你想做的事情,但是这里有太多的代码,我无法简单地重写来演示。如果你能想出一个最简单的例子,那么解释/理解就会容易得多,然后你就可以将这种理解应用到更大的代码中。谢谢,这是一个很好的建议。
import cv2
import numpy as np
from pulse import Pulse
import time
from threading import Lock, Thread
from plot_cont import DynamicPlot
from capture_frames import CaptureFrames
import pandas as pd
from matplotlib import pyplot as plt

from utils import *
import multiprocessing as mp
import sys


class ProcessMasks():

    def __init__(self, sz=270, fs=30, bs=30, size=256):
        print('init')
        self.stop = False
        self.masked_batches = []
        self.batch_mean = []
        self.signal_size = sz
        self.batch_size = bs
        self.signal = np.zeros((sz, 3))
        self.pulse = Pulse(fs, sz, bs, size)
        self.hrs = []
        self.save_results = True

    def __call__(self, pipe, plot_pipe, source):
        self.pipe = pipe
        self.plot_pipe = plot_pipe
        self.source = source
        compute_mean_thread =  Thread(target=self.compute_mean)
        compute_mean_thread.start()
        
        extract_signal_thread =  Thread(target=self.extract_signal)
        extract_signal_thread.start()

        self.rec_frames()
        
        compute_mean_thread.join()
        extract_signal_thread.join()
  
    def rec_frames(self):
        while True and not self.stop:
            data = self.pipe.recv()

            if data is None:
                self.terminate()
                break
            batch = data[0]

            self.masked_batches.append(batch)
    
    def process_signal(self, batch_mean):
        size = self.signal.shape[0]
        b_size = batch_mean.shape[0]

        self.signal[0:size-b_size] = self.signal[b_size:size]
        self.signal[size-b_size:] = batch_mean
        p = self.pulse.get_pulse(self.signal)
        p = moving_avg(p, 6)
        hr = self.pulse.get_rfft_hr(p)
        if len(self.hrs) > 300: self.hrs.pop(0)

        self.hrs.append(hr)
        if self.plot_pipe is not None and self.stop:
            self.plot_pipe.send(None)
        elif self.plot_pipe is not None:
            self.plot_pipe.send([p, self.hrs])
        else:

        #######################################################
        # I want to insert frames_count here, so when I print 
        # hr_fft, I can also print the frame_count for that 
        # observation.

        #######################################################

            hr_fft = moving_avg(self.hrs, 3)[-1] if len(self.hrs) > 5 else self.hrs[-1]
            print(hr_fft, CaptureFrames.frames_count)
            sys.stdout.write(f'\rHr: {round(hr_fft, 0)}')
            sys.stdout.flush()
    
    def extract_signal(self):
        signal_extracted = 0
        
        while True and not self.stop:
            if len(self.batch_mean) == 0:
                time.sleep(0.01)
                continue
            
            mean_dict = self.batch_mean.pop(0)
            mean = mean_dict['mean']

            if mean_dict['face_detected'] == False:
                if self.plot_pipe is not None:
                    self.plot_pipe.send('no face detected')
                continue
            if signal_extracted >= self.signal_size:
                self.process_signal(mean)
            else:
                self.signal[signal_extracted: signal_extracted + mean.shape[0]] = mean
            signal_extracted+=mean.shape[0]
    

    def compute_mean(self):
        curr_batch_size = 0
        batch = None
        while True and not self.stop:                
            if len(self.masked_batches) == 0:
                time.sleep(0.01)
                continue
            
            mask = self.masked_batches.pop(0)     
            if batch is None:
                batch = np.zeros((self.batch_size, mask.shape[0], mask.shape[1], mask.shape[2]))
            
            if curr_batch_size < (self.batch_size - 1):
                batch[curr_batch_size] = mask
                curr_batch_size+=1
                continue
            
            batch[curr_batch_size] = mask
            curr_batch_size = 0

            non_zero_pixels = (batch!=0).sum(axis=(1,2))
            total_pixels = batch.shape[1] * batch.shape[2]
            avg_skin_pixels = non_zero_pixels.mean()
            m = {'face_detected': True, 'mean': np.zeros((self.batch_size, 3))}
            if (avg_skin_pixels + 1) / (total_pixels) < 0.05:
                m['face_detected'] = False
            else:
                m['mean'] = np.true_divide(batch.sum(axis=(1,2)), non_zero_pixels+1e-6)

            self.batch_mean.append(m)

    def terminate(self):
        
        if self.plot_pipe is not None:
            self.plot_pipe.send(None)
        self.savePlot(self.source)
        self.saveresults()
        self.stop = True
    
    def saveresults(self):
        """
        saves numpy array of heart rates as hrs
        saves numpy array of power spectrum as fft_spec
        """
        np.save('hrs', np.array(self.hrs))
        np.save('fft_spec', np.array(self.pulse.fft_spec))


import cv2
import numpy as np
from pulse import Pulse
import time
from threading import Lock, Thread
from plot_cont import DynamicPlot
from capture_frames import CaptureFrames
from process_mask import ProcessMasks

from utils import *
import multiprocessing as mp
import sys
from optparse import OptionParser

class RunPOS():
    def __init__(self,  sz=270, fs=28, bs=30, plot=False):
        self.batch_size = bs
        self.frame_rate = fs
        self.signal_size = sz
        self.plot = plot

    def __call__(self, source):
        time1=time.time()
        
        mask_process_pipe, chil_process_pipe = mp.Pipe()
        self.plot_pipe = None
        if self.plot:
            self.plot_pipe, plotter_pipe = mp.Pipe()
            self.plotter = DynamicPlot(self.signal_size, self.batch_size)
            self.plot_process = mp.Process(target=self.plotter, args=(plotter_pipe,), daemon=True)
            self.plot_process.start()
        
        process_mask = ProcessMasks(self.signal_size, self.frame_rate, self.batch_size)

        mask_processer = mp.Process(target=process_mask, args=(chil_process_pipe, self.plot_pipe, source, ), daemon=True)
        mask_processer.start()
        
        capture = CaptureFrames(self.batch_size, source, show_mask=True)
        capture(mask_process_pipe, source)

        mask_processer.join()
        if self.plot:
            self.plot_process.join()
        time2=time.time()
        time2=time.time()
        print(f'time {time2-time1}')

def get_args():
    parser = OptionParser()
    parser.add_option('-s', '--source', dest='source', default=0,
                        help='Signal Source: 0 for webcam or file path')
    parser.add_option('-b', '--batch-size', dest='batchsize', default=30,
                        type='int', help='batch size')
    parser.add_option('-f', '--frame-rate', dest='framerate', default=25,
                        help='Frame Rate')

    (options, _) = parser.parse_args()
    return options
        
if __name__=="__main__":
    args = get_args()
    source = args.source
    runPOS = RunPOS(270, args.framerate, args.batchsize, True)
    runPOS(source)