python线程监控_Python 使用摄像头监测心率!这么强吗?
发布日期:2022-02-04 01:43:52 浏览次数:29 分类:技术文章

本文共 4183 字,大约阅读时间需要 13 分钟。

实验效果

实验思路用 opencv 打开摄像头,读取指定窗口区域的RGB分量均值,本实验读取前额皮肤

用 matplotlib 绘制动态序列曲线

用 HP 滤波过滤RGB序列的趋势部分,保留波动信息,如第2列图所示

对 HP 滤波后的残差,即波动信息,做FFT变换,获得信号频谱

绿色分量频谱的尖峰反映了心跳的频率,正常人的心跳频率在 1~2 Hz 之间

代码实现

采用多线程的模式:线程一作为生产者,用于 opencv 读取图片中的RGB信号,并发送到一个公共队列 data_queue

线程二作为消费者,但实际不消费,只是读取公共队列上的信息并用 matplotlib 画图

当公共队列满了之后,线程一无法插入新数据,这时由线程一弹出队首的数据,即最早的信号值

线程一

class Producer(threading.Thread):

def __init__(self,data_queue,*args,**kwargs):

super(Producer, self).__init__(*args,**kwargs)

self.data_queue = data_queue

def run(self):

capture = cv2.VideoCapture(0) # 0是代表摄像头编号,只有一个的话默认为0

capture.set(cv2.CAP_PROP_FPS, 10)

try:

t0 = time.time()

while (True):

ref, frame = capture.read()

frame = frame[:,::-1,:].copy()

H, W, _ = frame.shape

w, h = 40, 40

x, y = W//2 -w//2, H//4-h//2

area = frame[y:y + h, x:x + w, :]

cv2.rectangle(frame, (x,y), (x+w,y+h), (0,255,0), 2)

frame[:h,:w] = area

t = time.time()-t0

cv2.putText(frame, 't={:.3f}'.format(t), (10, H-10), cv2.FONT_HERSHEY_PLAIN, 1.2, (255, 255, 255), 2)

cv2.imshow("face", frame)

B = np.average(area[:,:,0])

G = np.average(area[:,:,1])

R = np.average(area[:,:,2])

if self.data_queue.full():

self.data_queue.queue.popleft()

self.data_queue.put((t,B,G,R))

c = cv2.waitKey(10) & 0xff # 等待10ms显示图像,若过程中按“Esc”退出

if c == 27:

capture.release()

break

except:

traceback.print_exc()

finally:

capture.release()

cv2.destroyAllWindows()

if self.data_queue.full():

self.data_queue.get()

self.data_queue.put('Bye')

print('Producer quit')

线程二

从公共队列中读取原始的 RGB 信号,做 HP 滤波,做傅里叶变换,作图

class Consumer(threading.Thread):

def __init__(self,data_queue,*args,**kwargs):

super(Consumer, self).__init__(*args,**kwargs)

self.data_queue = data_queue

def run(self):

time.sleep(1)

fig, axes = plt.subplots(3, 3)

axes[0, 0].set_title('原始信号')

axes[0, 1].set_title('HP滤波残差')

axes[0, 2].set_title('FFT频谱')

axes[0, 0].set_ylabel('Blue')

axes[1, 0].set_ylabel('Green')

axes[2, 0].set_ylabel('Red')

axes[2, 0].set_xlabel('Time(s)')

axes[2, 1].set_xlabel('Time(s)')

axes[2, 2].set_xlabel('Frequency(Hz)')

start = None

lines = [None, None, None]

glines = [None, None, None]

rlines = [None, None, None]

flines = [None, None, None]

BGR = [None, None, None]

g = [None, None, None]

r = [None, None, None]

f = [None, None, None]

num_fft = 256

while True:

# time.sleep(0.2)

if self.data_queue.qsize() > 2:

if self.data_queue.queue[-1] == 'Bye':

break

ts, BGR[0], BGR[1], BGR[2] = zip(*self.data_queue.queue)

t = ts[-1] if len(ts) > 0 else 0

for i in range(3):

g[i] = hp(BGR[i], 1000)

r[i] = BGR[i] - g[i]

# FFT

for i in range(3):

rr = r[i][-num_fft:]

f[i] = np.fft.fft(rr, num_fft)

f[i] = np.abs(f[i])[:num_fft//2]

fs =len(rr)/ (ts[-1] - ts[-len(rr)])

if start is None:

start = 1

lines[0] = axes[0,0].plot(ts, BGR[0], '-b')[0]

lines[1] = axes[1,0].plot(ts, BGR[1], '-g')[0]

lines[2] = axes[2,0].plot(ts, BGR[2], '-r')[0]

glines[0] = axes[0,0].plot(ts, g[0], '-k')[0]

glines[1] = axes[1,0].plot(ts, g[1], '-k')[0]

glines[2] = axes[2,0].plot(ts, g[2], '-k')[0]

rlines[0] = axes[0, 1].plot(ts, r[0], '-b')[0]

rlines[1] = axes[1, 1].plot(ts, r[1], '-g')[0]

rlines[2] = axes[2, 1].plot(ts, r[2], '-r')[0]

flines[0] = axes[0, 2].plot(np.arange(num_fft//2)*fs/num_fft, f[0], '-b', marker='*')[0]

flines[1] = axes[1, 2].plot(np.arange(num_fft//2)*fs/num_fft, f[1], '-g', marker='*')[0]

flines[2] = axes[2, 2].plot(np.arange(num_fft//2)*fs/num_fft, f[2], '-r', marker='*')[0]

for i in range(3):

lines[i].set_xdata(ts)

lines[i].set_ydata(BGR[i])

glines[i].set_xdata(ts)

glines[i].set_ydata(g[i])

rlines[i].set_xdata(ts)

rlines[i].set_ydata(r[i])

flines[i].set_xdata(np.arange(num_fft//2)*fs/num_fft)

flines[i].set_ydata(f[i])

for i in range(3):

axes[i,0].set_xlim([t - 10, t + 1])

axes[i,0].set_ylim([np.min(BGR[i][-num_fft:]), np.max(BGR[i][-num_fft:])])

axes[i, 1].set_xlim([t - 10, t + 1])

axes[i, 1].set_ylim([np.min(r[i][-num_fft:]), np.max(r[i][-num_fft:])])

axes[i, 2].set_xlim([0, fs//2])

axes[i, 2].set_ylim([np.min(f[i]), np.max(f[i])])

plt.pause(0.1)

print('Consumer quit')

主函数

N = 300

data_queue = Queue(N)

p = Producer(data_queue)

p.start()

c = Consumer(data_queue)

c.start()

p.join()

c.join()

print('EXIT')

1234567891011

实验总结从图中可以看出,RGB 三个分量中,绿色分量最能反映心跳信息,和文献中的结果一致

求得信号的频谱之后,如何转化成心率?直接用频率乘以 60 即可

转载地址:https://blog.csdn.net/weixin_39603908/article/details/110170446 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:采样频率和带宽的关系_发送端测试的主力设备 - 实时示波器朝向高带宽高位数发展...
下一篇:win7安装python3.6失败_win7下python3.6安装配置方法图文教程

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年04月15日 16时54分55秒