在python中将变量从类内的函数转换为单独的类函数
我有两个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
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)