基于电磁噪声信号检测的电子设备识别(EMSENSE)

1. 基本思路

众所周知,电子设备在工作的时候,由于热电流电阻三极管都会向外发射噪声信号。通过手接触,信号通过人体,再到设备的天线,设备检测这些信号,就可以通过一些机器学习的方法加以识别出是什么电子设备,相当于每一个电子设备都有一个指纹。
这种技术的最大特特点是不需要被识别物体发出信号,只需要识别传统设备而拥有了只能电器的一些特性。可能会是物联网发展过程中的一个可行方案。希望大家继续发展这项技术。
本项目检测的信号频率范围为0-100M Hz,之后的研究可以考虑在其他频率上检测,也希望大家给出理论上的支持,为什么低中频的噪声电磁信号有利于识别。

2. 硬件改造

参考论文:
https://www.gierad.com/assets/emsense/emsense.pdf
硬件主要的设备是一个 RTL2832U SDR receiver, SDR是指 self defined radio,可以理解成一块集成在芯片上,可以通过usb口把信号传到电脑或者嵌入式设备的收音机。
我们主要用到的是SDR中的模数转化模块和读取信号的芯片。短接了放大混频震荡等模块。详情请见参考文献。

噪声信号
人体
天线
低通滤波
数模转换
pc读取

下面是具体细节

2.1 天线改造

天线和手腕接触,本项目中改装了收音机原来的天线,由于绕磁天线本身就是一个高通滤波器,所以把它剪短了很多,去头去尾,留取中间一小段。
天线和手接触的部分,采取四层结构:
金属层1—— 绝缘层——金属层2——绝缘层
金属层1 连接原来天线的信号线,金属层2连接原来的天线的地线。

2.2 芯片改造


將进入数模转化前的两个电容去除,使得芯片的其他部分短路。使用跳线的方式,焊接上一个巴伦转换器WB1010。
巴伦转换器的实质是一个低通滤波器, datasheet: https://www.mouser.cn/datasheet/2/597/wbt-463414.pdf
可见同一边的两个管脚是等价的,C1和C2可以互换,信号口和地可以互换。
巴伦转化器标记+V的管脚连接天线的信号线,标记GND的管脚连接天线的地线。
在这里插入图片描述

3. 软件支持

根据以下网站获得软件支持: https://github.com/roger-/pyrtlsdr

有了硬件和软件之后,剩下的做什么就可以自由发挥了!

4. class txtSDR

我写了一个类,用于一些SDR的基本行为。

    def getOneSample(self):
        lockSDR.acquire()
        samples = self.sdr.read_samples(NUM_SAMPLES_PER_SCAN)
        psd_scan, f = psd(samples, NFFT=NFFT)
        aa=np.zeros((3))
        psd_scan[2047:2050]=aa
        self.psd_scan = psd_scan
        lockSDR.release()

读取一次数据,由于实际情况中存在较大的直流分量,且变化比较大,对预测造成巨大干扰。所以,通过附零的方式,手动去除直流分量。

  1. 下采样,使用scipy 包的 signal对象。
    def DownSample(self, S, i):
        return signal.resample(S, 512)
  1. 读取十个数据,取平均作为背景噪声。
    def getBackGroundNois(self):
        printMy("Getting background noise profile!")
        self.back_ground = 0
        self.getOneSample()
        psd_scan = self.getPsd_scan()
        for x in range(10):
            self.getOneSample()
            psd_scan = self.getPsd_scan()
            self.back_ground += psd_scan
        self.back_ground /= 10
        printMy("Got background noise profile!")
  1. 有了每次的读取数据后,手动提取一些特征,组合成一个向量
    def getFeatures(self):
        psd_scan = self.psd_scan - self.back_ground
        std = np.std(psd_scan, ddof = 1)
        S1=psd_scan - (self.back_ground + 2.5 * std)
        maxS = np.maximum(0, S1)
        S = self.DownSample(S1, 512)
        diff_1 = S[1:] - S[0:-1]
        diff_2 = diff_1[1:] - diff_1[0:-1]
        rms = np.sqrt(np.mean(S**2))
        S_list = S.tolist()
        max_index = S_list.index(max(S_list))
        #printMy("max_index", max_index)
        min_index = S_list.index(min(S_list))
        COM = np.dot(S, np.linspace(0,1,512)) / np.sum(S)# center of mass
        std = np.std(S)
        kurtosis = stats.kurtosis(S)
        Crest = maxS / np.sum(S)
        self.features = np.hstack((Crest,kurtosis,min_index,max_index,COM,std,diff_1,diff_2,rms)).reshape(1,-1).flatten()
        #self.features = np.hstack((Crest,kurtosis,min_index,max_index,COM,std,rms)).reshape(1,-1).flatten()
        #printMy(Crest,kurtosis,min_index,max_index,COM,std,diff_1,diff_2,rms)
  1. 采集新的一个数据,读取连续20个数据,把特征和tag 保存在本地’data/'文件夹中。tag 是指目前的第几个物体。
    def addNewItem(self):
        self.tag=self.tag+1
        np.save("tag",self.tag)
        
        time.sleep(0.5)

        for x in range(1,20):
            # printMy(str(x)+"...")
            self.getOneSample()
            self.getFeatures()
            path='data/'+str(time.time())
            dataToSave=np.hstack(([self.tag],self.features))
            np.save(path,dataToSave)
  1. 读取所有的数据,把第一位作为y,第一位以后作为x,训练模型,并保存到本地。
    def train(self):

        if self.tag < 2:
            return
        printMy('save model...')
        path='data/'
        fileList = os.listdir(path)
        y = []
        x = []

        for f in fileList:
            f = path + f
            dataN = np.load(f)
            #printMy("dataN[0]:"+str(dataN[0]))
            y.append(dataN[0].tolist())
            x.append(dataN[1:].tolist())         
        from sklearn import svm
        from sklearn.externals import joblib as jl
        clf = svm.SVC()
        clf.fit(np.array(x),np.array(y))
        Y = clf.predict(np.array(x))
        printMy("done!\naccurency on training sets:"+str(np.sum(Y==y)/len(y)))
        jl.dump(clf,'clf.model')        
        pass
  1. 进行预测,使用已有模型。
    def Predict(self, features):
        
        if os.path.exists('clf.model'):
            from sklearn.externals import joblib as jl
            model=jl.load('clf.model')
            answer=model.predict(features)
        else:
            answer=-1
        return answer
  1. 删除一则数据和清空数据。
    def clear(self):
        path='data/'
        fileList = os.listdir(path)
        for f in fileList:
            f = path + f
            os.remove(f) 

        if os.path.exists('clf.model'):     
            os.remove('clf.model')
        np.save('tag',0)
        self.tag = 0

    def deleteOneItem(self, a):
        path='data/'
        fileList = os.listdir(path)
        flag = 0
        for f in fileList:
            f = path + f
            dataN = np.load(f)
            if dataN[0] == a:
                os.remove(f) 
                flag = 1
            
            elif dataN[0] > a:
                #print(dataN[0])
                dataN[0] -= 1
                np.save(f,dataN)

        if flag == 1:
            print("tag:"+str(self.tag))
            self.tag -= 1
            np.save("tag",self.tag)

5. class Ui_MainWindow

GUI 窗口,主要是pyqt 界面按钮的设计以及按钮事件对SDR的方法的调用。
最关键的是

6、检测效果

各个电子产品的噪声波形
在这里插入图片描述演示视频:https://pan.baidu.com/s/133g-HFulpZLWsblDXQmKqw 密码:vc3x
由于身高差,帮我那点脑的刀某同学无法入镜,对此,我表示十分遗憾以及深切慰问。

7. 代码总汇

myGui.py:


from PyQt5 import QtCore,QtGui,QtWidgets
import sys
import qtawesome
from PyQt5.QtWidgets import (QApplication, QWidget,QPushButton,
    QLineEdit,QHBoxLayout, QVBoxLayout,QColorDialog,QInputDialog,QFileDialog)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QCursor,QColor
import matplotlib
import matplotlib.animation as animation
from matplotlib.mlab import psd
import pylab as pyl
import numpy as np
import sys
from rtlsdr import RtlSdr
from scipy import signal
from scipy import stats
import os
import time
import argparse
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from PyQt5 import QtWidgets,QtCore
from PyQt5.QtWidgets import QMainWindow,QApplication
import sys
from collections import Counter
import threading
showflag = True
lockSDR = threading.Lock()
lockPrint = threading.Lock()


NFFT = 1024*4
NUM_SAMPLES_PER_SCAN = NFFT*16
NUM_BUFFERED_SWEEPS = 100
NUM_SCANS_PER_SWEEP = 1
FREQ_INC_COARSE = 1e6
FREQ_INC_FINE = 0.1e6
GAIN_INC = 5

printBuffer = ''

def printMy(OneString):
    #print(OneString)
    global printBuffer
    temp = getPrintBuffer()
    temp = printBuffer + '\n' + str(OneString)
    lockPrint.acquire()
    printBuffer = temp
    lockPrint.release()
    #print(printBuffer)

def getPrintBuffer():
    lockPrint.acquire()
    temp = printBuffer
    lockPrint.release()
    return temp

class txtSdr(object):
    def __init__(self, sdr=None, fig=None):
        self.sdr = sdr if sdr else RtlSdr()
        self.numOfSample = 0 
        self.back_ground = np.zeros([4096,])
        self.mod = 0        
        if os.path.exists("tag.npy"):
            self.tag = np.load("tag.npy")
        else:
            self.tag = 0


    def DownSample(self, S, i):
        return signal.resample(S, 512)

    def getFeatures(self):
        psd_scan = self.psd_scan - self.back_ground
        std = np.std(psd_scan, ddof = 1)
        S1=psd_scan - (self.back_ground + 2.5 * std)
        maxS = np.maximum(0, S1)

        S = self.DownSample(S1, 512)
        diff_1 = S[1:] - S[0:-1]
        diff_2 = diff_1[1:] - diff_1[0:-1]
        rms = np.sqrt(np.mean(S**2))
        S_list = S.tolist()
        max_index = S_list.index(max(S_list))
        #printMy("max_index", max_index)
        min_index = S_list.index(min(S_list))
        COM = np.dot(S, np.linspace(0,1,512)) / np.sum(S)# center of mass
        std = np.std(S)
        kurtosis = stats.kurtosis(S)
        Crest = maxS / np.sum(S)
        self.features = np.hstack((Crest,kurtosis,min_index,max_index,COM,std,diff_1,diff_2,rms)).reshape(1,-1).flatten()
        #self.features = np.hstack((Crest,kurtosis,min_index,max_index,COM,std,rms)).reshape(1,-1).flatten()
        #printMy(Crest,kurtosis,min_index,max_index,COM,std,diff_1,diff_2,rms)

    def Predict(self, features):
        
        if os.path.exists('clf.model'):
            from sklearn.externals import joblib as jl
            model=jl.load('clf.model')
            answer=model.predict(features)
        else:
            answer=-1
        return answer

    def train(self):

        if self.tag < 2:
            return
        printMy('save model...')
        path='data/'
        fileList = os.listdir(path)
        y = []
        x = []

        for f in fileList:
            f = path + f
            dataN = np.load(f)
            #printMy("dataN[0]:"+str(dataN[0]))
            y.append(dataN[0].tolist())
            x.append(dataN[1:].tolist())         
        from sklearn import svm
        from sklearn.externals import joblib as jl
        clf = svm.SVC()
        clf.fit(np.array(x),np.array(y))
        Y = clf.predict(np.array(x))
        printMy("done!\naccurency on training sets:"+str(np.sum(Y==y)/len(y)))
        jl.dump(clf,'clf.model')        
        pass

    def getOneSample(self):
        lockSDR.acquire()
        samples = self.sdr.read_samples(NUM_SAMPLES_PER_SCAN)
        psd_scan, f = psd(samples, NFFT=NFFT)
        aa=np.zeros((3))
        psd_scan[2047:2050]=aa
        self.psd_scan = psd_scan
        lockSDR.release()

    def getPsd_scan(self):
        lockSDR.acquire()
        psd_scan = self.psd_scan
        lockSDR.release()
        return psd_scan

    def getBackGroundNois(self):
        printMy("Getting background noise profile!")
        self.back_ground = 0
        self.getOneSample()
        psd_scan = self.getPsd_scan()
        for x in range(10):
            self.getOneSample()
            psd_scan = self.getPsd_scan()
            self.back_ground += psd_scan
        self.back_ground /= 10
        printMy("Got background noise profile!")
        

    def addNewItem(self):
        self.tag=self.tag+1
        np.save("tag",self.tag)
        
        time.sleep(0.5)

        for x in range(1,20):
            # printMy(str(x)+"...")
            self.getOneSample()
            self.getFeatures()
            path='data/'+str(time.time())
            dataToSave=np.hstack(([self.tag],self.features))
            np.save(path,dataToSave)
        
        

    def setMod(self, mod):
        self.mod = int(mod)

    def getMod(self):
        #printMy("mod:"+str(self.mod))
        return self.mod


    def getInstruction(self):
        return self.instruction;

    def clear(self):
        path='data/'
        fileList = os.listdir(path)
        for f in fileList:
            f = path + f
            os.remove(f) 

        if os.path.exists('clf.model'):     
            os.remove('clf.model')
        np.save('tag',0)
        self.tag = 0

    def deleteOneItem(self, a):
        path='data/'
        fileList = os.listdir(path)
        flag = 0
        for f in fileList:
            f = path + f
            dataN = np.load(f)
            if dataN[0] == a:
                os.remove(f) 
                flag = 1
            
            elif dataN[0] > a:
                #print(dataN[0])
                dataN[0] -= 1
                np.save(f,dataN)

        if flag == 1:
            print("tag:"+str(self.tag))
            self.tag -= 1
            np.save("tag",self.tag)




        
class Figure_Canvas(FigureCanvas):   # 通过继承FigureCanvas类,使得该类既是一个PyQt5的Qwidget,又是一个matplotlib的FigureCanvas,这是连接pyqt5与matplot                                          lib的关键

    def __init__(self,psdr,parent=None):
        self.sdr_txt=psdr
        fig = Figure(figsize=(6,4.5))  # 创建一个Figure,注意:该Figure为matplotlib下的figure,不是matplotlib.pyplot下面的figure
        fig.set_facecolor('white')
        #fig.patch.set_alpha(0.673) 
        FigureCanvas.__init__(self, fig) # 初始化父类
        self.setParent(parent)
        self.axes = fig.add_subplot(111) # 调用figure下面的add_subplot方法,类似于matplotlib.pyplot下面的subplot方法
        self.flag = True
        self.lockFC = threading.Lock()
        y = self.getY()
        self.x=np.arange(np.shape(y)[0])
        



    def test(self):
        self.axes.set_xlabel('Current frequency (MHz)')
        self.axes.get_yaxis().set_visible(False)
        self.axes.get_xaxis().set_visible(False)
 
        ax = self.axes
        ax.spines['top'].set_visible(False) #去掉上边框
        ax.spines['bottom'].set_visible(False) #去掉下边框
        ax.spines['left'].set_visible(False) #去掉左边框
        ax.spines['right'].set_visible(False) #去掉右边框
        flag =  self.getFlag()
        num=1
        while  flag:
            self.axes.cla()
            #printMy(num)
            num+=1
            flag =  self.getFlag()
            y = self.getY()
            #printMy("drawing...",y)
            self.axes.plot(self.x, y,alpha=1)  
            #self.axes.patch.set_facecolor("black")            #设置ax1区域背景颜色               
            #self.axes.patch.set_alpha(0.01)                   #设置ax1区域背景颜色透明度  
            self.axes.axis([0,4096,0,1e-1])
            self.draw()
            time.sleep(0.1)
            if np.mod(num,200)==0:
                pass
                #self.sdr_txt.getBackGroundNois()

    def setXY(self,y):
        self.lockFC.acquire()
        self.y=y;
        self.lockFC.release()

    def getY(self):
        self.lockFC.acquire()
        mod = self.sdr_txt.getMod();
        if(mod==0):
            self.sdr_txt.getOneSample()
            y=self.sdr_txt.getPsd_scan();
        else:
            y=self.y
        self.lockFC.release()
        return y

    def getFlag(self):
        self.lockFC.acquire()
        flag=self.flag
        self.lockFC.release()
        return flag

    def setFlag(self,flag):
        self.lockFC.acquire()
        self.flag=flag
        self.lockFC.release()        
        
    def changeFlag(self):
        self.flag = not self.flag

    
                



def main():
    pass

    

if __name__ == '__main__':
    sdr_txt = txtSdr()
    sdr_txt.getBackGroundNois()  
    main()

newUI.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'newUI.ui'
#
# Created by: PyQt5 UI code generator 5.12.1
#
# WARNING! All changes made in this file will be lost!

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog
from myGui import txtSdr
from myGui import Figure_Canvas
from myGui import *
import time, datetime
from collections import Counter
import threading
import dialog
from dialog import *
import os
import logging 

class updatePrintThread(QtCore.QThread):
    trigger = QtCore.pyqtSignal(str) # trigger传输的内容是字符串
    def __init__(self, parent=None):
        super(updatePrintThread, self).__init__(parent) 
        self.printFlag = 1
 
    def setup(self, args):
        self.args = args
  
    def run(self): # 很多时候都必重写run方法, 线程start后自动运行
        self.my_function()
    
    def my_function(self):
        while self.printFlag:
            textNow = getPrintBuffer()
            self.trigger.emit(textNow)  
            time.sleep(0.5)

class toTrainTH(QtCore.QThread):
    #signal = pyqtSignal()    # 括号里填写信号传递的参数
    def __init__(self, parent=None):
        super(toTrainTH, self).__init__(parent)

    def run(self):
        sdr_txt.train()

class toAddTH(QtCore.QThread):
    #signal = pyqtSignal()    # 括号里填写信号传递的参数
    def __init__(self, parent=None):
        super(toAddTH, self).__init__(parent)

    def run(self):
        sdr_txt.addNewItem()
        printMy("done!")
        self.dlog.show()
    def setup(self,dlog):
        self.dlog = dlog

        

class toPredTH(QtCore.QThread):
    #signal = pyqtSignal()    # 括号里填写信号传递的参数
    def __init__(self, parent=None):
        super(toPredTH, self).__init__(parent)
    def setup(self, list_devices):
        self.list_devices = list_devices
        pass
    def run(self):
        time.sleep(1)
        x = []
        for i in range(0,10):
            sdr_txt.getOneSample()
            sdr_txt.getFeatures()
            x.append(sdr_txt.features)
            answer=sdr_txt.Predict(x)
        print(answer)
        if answer[0] == -1:
            printMy('No module available for prediction! \nPlease train one first!')
            return
        word_counts = Counter(answer)
        if word_counts.most_common(1)[0][1] > 5: 
            indexNum = word_counts.most_common(1)[0][0]
            
            printMy("I guess you are touching " + self.list_devices.item(indexNum-1).data(0) +". Am I right?") 

        else:
            printMy("Sorry, I don't know what you are touching. ")


         


class Ui_MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Ui_MainWindow, self).__init__(parent)  
          
    def setFigCanvas(self):
        self.dr = Figure_Canvas(sdr_txt) 
        t = threading.Thread(target=self.dr.test)
        t.start()

    def setTextBrowser(self):
        self.PrintThread = updatePrintThread(self) # 创建线程
        self.PrintThread.trigger.connect(self.updateTextBrowser) # 连接信号!
        self.PrintThread.start()

    def updateTextBrowser(self, message):
        self.textBrowser.clear()
        self.textBrowser.append(message)


    def setProp(self):
        self.dlog = QDialog()
        self.dlog_ui = Ui_Dialog()
        self.dlog_ui.setupUi(self.dlog)
        self.itemName = []
        self.chooseItemNum = -1
        self.chooseItemName = ''

    def setupUi(self, MainWindow):
        self.setProp()
        self.setFigCanvas()
        MainWindow.setObjectName("MainWindow")
        MainWindow.setEnabled(True)
        MainWindow.resize(1200, 700)
        MainWindow.setAnimated(True)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setStyleSheet("QWidget{\n"
            "background-color:rgb(249,249,249);\n"
            "}")
        self.centralwidget.setObjectName("centralwidget")
        self.label_device = QtWidgets.QLabel(self.centralwidget)
        self.label_device.setGeometry(QtCore.QRect(30, 60, 141, 31))
        font = QtGui.QFont()
        font.setFamily("微软雅黑")
        font.setPointSize(15)
        font.setBold(True)
        font.setWeight(75)
        self.label_device.setFont(font)
        self.label_device.setObjectName("label_device")
        self.list_devices = QtWidgets.QListWidget(self.centralwidget)
        self.list_devices.setGeometry(QtCore.QRect(30, 129, 241, 471))
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.list_devices.sizePolicy().hasHeightForWidth())
        self.list_devices.setSizePolicy(sizePolicy)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(False)
        font.setUnderline(False)
        font.setWeight(50)
        font.setStrikeOut(False)
        font.setKerning(True)
        self.list_devices.setFont(font)
        self.list_devices.viewport().setProperty("cursor", QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.list_devices.setAutoFillBackground(False)
        self.list_devices.setStyleSheet("QListWidget{\n"
            "background-color:rgb(249,249,249);\n"
            "border-radius:10px;\n"
            "}")
        self.list_devices.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.list_devices.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.list_devices.setMidLineWidth(0)
        self.list_devices.setAutoScrollMargin(16)
        self.list_devices.setGridSize(QtCore.QSize(0, 30))
        self.list_devices.setObjectName("list_devices")

        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(300, 0, 901, 701))
        self.widget.setStyleSheet("QWidget{\n"
            "background-color:white;\n"
            "}")
        self.widget.setObjectName("widget")
        self.tabWidget = QtWidgets.QTabWidget(self.widget)
        self.tabWidget.setGeometry(QtCore.QRect(30, 60, 841, 591))
        font = QtGui.QFont()
        font.setFamily("微软雅黑")
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.tabWidget.setFont(font)
        self.tabWidget.setObjectName("tabWidget")
        self.tab_idf = QtWidgets.QWidget()
        self.tab_idf.setObjectName("tab_idf")
        self.label_dname = QtWidgets.QLabel(self.tab_idf)
        self.label_dname.setGeometry(QtCore.QRect(330, 150, 221, 41))
        font = QtGui.QFont()
        font.setFamily("微软雅黑")
        font.setPointSize(17)
        font.setBold(True)
        font.setWeight(75)
        self.label_dname.setFont(font)
        self.label_dname.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.label_dname.setAlignment(QtCore.Qt.AlignCenter)
        self.label_dname.setObjectName("label_dname")
        self.btn_start = QtWidgets.QPushButton(self.tab_idf)
        self.btn_start.setGeometry(QtCore.QRect(330, 240, 221, 50))
        font = QtGui.QFont()
        font.setFamily("微软雅黑")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.btn_start.setFont(font)
        self.btn_start.setStyleSheet("QPushButton{\n"
            "color:white;\n"
            "background-color:rgb(19,167,197);\n"
            "border-radius:10px;\n"
            "}")
        self.btn_start.setObjectName("btn_start")
        self.tabWidget.addTab(self.tab_idf, "")
        self.tab_manage = QtWidgets.QWidget()
        self.tab_manage.setObjectName("tab_manage")
        self.btn_add = QtWidgets.QPushButton(self.tab_manage)
        self.btn_add.setGeometry(QtCore.QRect(30, 40, 221, 50))
        font = QtGui.QFont()
        font.setFamily("微软雅黑")
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.btn_add.setFont(font)
        self.btn_add.setStyleSheet("QPushButton{\n"
            "color:white;\n"
            "background-color:rgb(19,167,197);\n"
            "border-radius:10px;\n"
            "}")
        self.btn_add.setObjectName("btn_add")
        self.btn_startTrain = QtWidgets.QPushButton(self.tab_manage)
        self.btn_startTrain.setGeometry(QtCore.QRect(310, 40, 221, 50))
        font = QtGui.QFont()
        font.setFamily("微软雅黑")
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.btn_startTrain.setFont(font)
        self.btn_startTrain.setStyleSheet("QPushButton{\n"
            "color:white;\n"
            "background-color:rgb(19,167,197);\n"
            "border-radius:10px;\n"
            "}")
        self.btn_startTrain.setObjectName("btn_startTrain")
        self.btn_startPred = QtWidgets.QPushButton(self.tab_manage)
        self.btn_startPred.setGeometry(QtCore.QRect(590, 40, 221, 50))
        font = QtGui.QFont()
        font.setFamily("微软雅黑")
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.btn_startPred.setFont(font)
        self.btn_startPred.setStyleSheet("QPushButton{\n"
            "color:white;\n"
            "background-color:rgb(19,167,197);\n"
            "border-radius:10px;\n"
            "}")
        self.btn_startPred.setObjectName("btn_startPred")
        self.textBrowser = QtWidgets.QTextBrowser(self.tab_manage)
        self.textBrowser.setGeometry(QtCore.QRect(590, 120, 221, 411))
        self.textBrowser.setStyleSheet("QTextBrowser{\n"
            "background-color:rgb(249,249,249);\n"
            "border-radius:10px;\n"
            "}")
        self.textBrowser.setObjectName("textBrowser")
        #self.graphicsView = QtWidgets.QGraphicsView(self.tab_manage)
        self.graphicsView = QtWidgets.QGraphicsView(self.tab_manage)

        self.graphicsView.setGeometry(QtCore.QRect(30, 120, 501, 411))
        self.graphicsView.setObjectName("graphicsView")
        self.graphicscene = QtWidgets.QGraphicsScene()  # 第三步,创建一个QGraphicsScene,因为加载的图形(FigureCanvas)不能直接放到graphicview控件中,必须先放到graphicScene,然后再把graphicscene放到graphicview中
        self.graphicscene.addWidget(self.dr) 
        self.graphicsView.setScene(self.graphicscene)  # 第五步,把QGraphicsScene放入QGraphicsView


        self.tabWidget.addTab(self.tab_manage, "")
        self.btn_delete = QtWidgets.QPushButton(self.centralwidget)
        self.btn_delete.setGeometry(QtCore.QRect(30, 620, 31, 31))
        self.btn_delete.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.btn_delete.setStyleSheet("QPushButton{\n"
            "border-image:url(delete_button.png);\n"
            "}\n"
            "\n"
            "QPushButton:pressed{\n"
            "border-image:url(delete_button_press.png);\n"
            "}")
        self.btn_delete.setText("")
        self.btn_delete.setObjectName("btn_delete")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(1)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label_device.setText(_translate("MainWindow", "Devices"))

        item = QtWidgets.QListWidgetItem()
        self.list_devices.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.list_devices.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.list_devices.addItem(item)

        __sortingEnabled = self.list_devices.isSortingEnabled()
        self.list_devices.setSortingEnabled(False)

        item = self.list_devices.item(0)
        item.setText(_translate("MainWindow", "txt的PC"))

        item = self.list_devices.item(1)
        item.setText(_translate("MainWindow", "xsh的PC"))

        item = self.list_devices.item(2)
        item.setText(_translate("MainWindow", "txt的iPhone"))
        self.itemNum = 3

        self.list_devices.setSortingEnabled(__sortingEnabled)
        self.label_dname.setText(_translate("MainWindow", "txt的PC"))
        self.btn_start.setText(_translate("MainWindow", "START"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_idf), _translate("MainWindow", "Identification"))
        self.btn_add.setText(_translate("MainWindow", "Add a Device"))
        self.btn_startTrain.setText(_translate("MainWindow", "Start Training"))
        self.btn_startPred.setText(_translate("MainWindow", "Start Predicting"))
        self.textBrowser.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
            "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
            "p, li { white-space: pre-wrap; }\n"
            "</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
            "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'微软雅黑\'; font-weight:600; color:#5b5b5b;\">Instructions</span></p>\n"
            "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'微软雅黑\'; font-weight:600; color:#5b5b5b;\">Instructions</span></p>\n"
            "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'微软雅黑\'; font-weight:600; color:#5b5b5b;\">Instructions</span></p>\n"
            "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'微软雅黑\'; font-weight:600; color:#5b5b5b;\">Instructions</span></p>\n"
            "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'微软雅黑\'; font-weight:600; color:#5b5b5b;\">Instructions</span></p>\n"
            "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'微软雅黑\'; font-weight:600; color:#5b5b5b;\">Instructions</span></p>\n"
            "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'微软雅黑\'; font-weight:600; color:#5b5b5b;\"><br /></p>\n"
            "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'微软雅黑\'; font-weight:600; color:#5b5b5b;\">Training Complicated!</span></p>\n"
            "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'微软雅黑\'; font-size:10pt; font-weight:600;\"><br /></p></body></html>"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_manage), _translate("MainWindow", "Management"))
        self.textBrowser.clear()
        #sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)
        #sys.stderr = EmittingStream(textWritten=self.normalOutputWritten)        
        self.connectBotton()
        self.itemInit()
        self.setTextBrowser()
   

    def acceptBtn(self, dilog):
        newItem = dilog.lineEdit.text()
        printMy(newItem)

        self.list_devices.addItem(newItem)
        self.itemName.append(newItem)
        np.save("items/" + newItem, sdr_txt.tag)
        self.dlog.close()

    def connectBotton(self):
        def check(index):
            #print(index)
            self.chooseItemNum = index.row()
            self.chooseItemName = self.list_devices.item(index.row()).data(0)
            self.chooseItemVal = np.load("items/"+str(self.chooseItemName)+".npy")
            #print(self.chooseItemNum,self.chooseItemName,self.chooseItemVal)


        self.btn_startTrain.clicked.connect(self.toTrain)
        self.btn_startPred.clicked.connect(self.toPredict)
        #self.show1.clicked.connect(self.toShow)
        self.btn_add.clicked.connect(self.addItem)       
        self.btn_delete.clicked.connect(self.deleteItem) 
        btnCancel = self.dlog_ui.btn_cancel
        btnCancel.clicked.connect(self.dlog.close)
        self.dlog_ui.btn_accept.clicked.connect(lambda: self.acceptBtn(self.dlog_ui))                
        self.list_devices.clicked.connect(check)

    def deleteItem(self):
        printMy("deleting item " + str(self.chooseItemNum))
        if self.chooseItemNum == -1:
            self.list_devices.clear()
            sdr_txt.clear()
            path='items/'
            fileList = os.listdir(path)
            for f in fileList:
                f = path + f
                os.remove(f)
            self.itemNum = 0
        else:
            #item = self.list_devices.findItems(self.chooseItemName,Qt.MatchExactly)[0]

            #print(item)
            for x in range(1):
                aa = self.list_devices.takeItem(int(self.chooseItemNum))
                #print(aa,self.chooseItemNum)
            self.chooseItemNum = -1
            os.remove("items/"+str(self.chooseItemName)+".npy")
            path='items/'
            fileList = os.listdir(path)  
            for f in fileList:
                ff = path + f
                
                a = np.load(ff)
                if  a == self.chooseItemVal:
                    os.remove(ff + ".npy")
                elif a > self.chooseItemVal:
                    np.save(ff, a-1)

            sdr_txt.deleteOneItem(self.chooseItemVal)
            self.itemNum -= 1


    def itemInit(self):
        self.list_devices.clear()
        path='items/'
        fileList = os.listdir(path)
        flag = 0
        for f in fileList:
            if f in self.itemName:
                pass
            else:
                self.list_devices.addItem(f[0:-4])
                self.itemName.append(f)
        self.itemNum = len(self.itemName)
        #print("1111")

    def addItem(self):
        self.itemNum += 1
        printMy("Start training. Put your hand on item NO." + str(self.itemNum))
        self.addItemth = toAddTH(self)
        self.addItemth.setup(self.dlog)
        self.addItemth.start()
        

    def toTrain(self):
        self.trainThread = toTrainTH(self)
        #self.trainThread.signal.connect(self.callback)
        self.trainThread.start()

    '''
    def buttonClick(self)
        self.thread = Example()
        self.thread.signal.connect(self.callback)
        self.thread.start()    # 启动线程'''

    def toPredict(self):
        printMy("put your hand on thing to detlect")
        self.toPredth=toPredTH(self)
        self.toPredth.setup(self.list_devices)
        self.toPredth.start()




if __name__ == '__main__':
    sdr_txt = txtSdr()
    sdr_txt.getBackGroundNois()  
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    try:
        sys.exit(app.exec_())
    finally:
        ui.dr.changeFlag()
        ui.PrintThread.printFlag = 0

    

dialog.py

# -*- coding: utf-8 -*-


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(459, 166)
        self.lineEdit = QtWidgets.QLineEdit(Dialog)
        self.lineEdit.setGeometry(QtCore.QRect(50, 70, 361, 21))
        self.lineEdit.setObjectName("lineEdit")
        self.label = QtWidgets.QLabel(Dialog)
        self.label.setGeometry(QtCore.QRect(50, 30, 111, 21))
        font = QtGui.QFont()
        font.setFamily("微软雅黑")
        font.setPointSize(10)
        font.setBold(False)
        font.setWeight(50)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.btn_accept = QtWidgets.QPushButton(Dialog)
        self.btn_accept.setGeometry(QtCore.QRect(210, 110, 93, 28))
        self.btn_accept.setObjectName("btn_accept")
        self.btn_cancel = QtWidgets.QPushButton(Dialog)
        self.btn_cancel.setGeometry(QtCore.QRect(320, 110, 93, 28))
        self.btn_cancel.setObjectName("btn_cancel")

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.label.setText(_translate("Dialog", "输入设备名称"))
        self.btn_accept.setText(_translate("Dialog", "OK"))
        self.btn_cancel.setText(_translate("Dialog", "Cancel"))

猜你喜欢

转载自blog.csdn.net/qq_39575818/article/details/90514825