python如何写二进制乘法_如何用python写一个简单的数字信号处理计算器(文章末公开代码)?...

86bb0cceff4e626489e0ed238d563e3b.png

众所知周,法国的大神傅里叶可能通信和电子信息相关行业最头疼的人物,这个闹过革命,随拿破仑远征埃及的埃及总督,在回到法国的后,向法国皇家科学院递交过一篇关于三角级数论文,但是非常可惜,这篇论文并未引起大数学家高等数学中绕不开的大神——拉格朗日的注意。然而数十年过去了,随着无线电报机的出现,傅里叶变换焕发了新的生机。现在,本科大学生的两门课《信号与系统》和《数字信号处理》就是以傅里叶变换为基本研究对象。作为通信和电子信息专业的专业基础课,其上手难度可想而知,尤其是在刚学《数字信号处理》时,甚至连DFT都算不清楚。今天,笔者就送给大家一个用来专门计算《数字信号处理》中卷积和DFT的工具。

这里需要声明一下,这个计算器使用python写成,目前只能在python的环境下运行,所以没有装python的同学们要把python装上,另外,还需要tkinter和numpy、matplotlib三个库,利用pip可以轻松安装。(不会安装的同学们也不用担心,我会在下一篇文章中讲述windows如何安装pip和下载相应库)

当然,有兴趣的同学可以自己写一个卷积和dft的函数,这算是信号专业的入门了。

首先,我们展示一下计算器的外观,并简要介绍一下布局:

00bfcc8f4df770713dbb702b2a518a1c.png

这个计算器最左边有两个CheckButton,用来选择计算器的主要功能:卷积还是dft,再到右边,从上往下看,先是两个Entry,分别作为待处理数据的输入口,初始化时,两个输入口都存在,当我们选中dft时,则只有输入口1,而选择卷积时,则输入口1和输入口2都存在。

往下看是两个RadioButton,用来选择是否做出计算结果的图像,以方便使用者观看。下面是四个Button,作用等到使用方法时一一解释。

最下面是一个text,用来展示输入数据和计算结果,当选择卷积功能时,则会出现 两个text,用来分别显示两组输入数据。

下面,我们来介绍一下如何使用这个计算器。

dft功能:

首先,我们要在功能区选择dft功能,这时上方会显示“已选择dft”,如果不小心将dft和卷积同时选上,则会出现“不能同时选择”。

第二步,就可以输入数据了,在输入口1输入数据,每输入完一个数据就敲击一下“Enter”键,该输入就会在下方的text中显示,并且自动空格。因为dft是数据运算,所以如果你输入的不是数字,上方就会出现红色提示“输入只能是数字”。

bc81eaad7248707ba976f96d8886d053.png

3dca34cbf81746d5b98d8bf1f366aff5.png

当数据输入完后,可以选择是否做图,这一步并不是很关键,因为不论是否做图,都会呈现数值结果。待数据输入完后,请点击输入结束,这时会出现一个“-->”符号,然后点击计算,这时如果你选择了做图,就会出现图像,如果选择不做图,则什么都没有出现,那么计算数值呢?别忘了有一个显示结果,轻点“显示结果”,就会出现一个text,而计算结果就在上面。

下面,我们来操作一遍:

c28c27e68b98f92cab895d3ff73bfe33.png
dft计算https://www.zhihu.com/video/1221903431230812160

计算的图像如下:

a2348b2d62c16f011072e76705b518a5.png

大家可能会奇怪,为什么计算出的图像有三个,其实只要仔细看一下纵坐标就可以知道,第一幅图是原序列的图像,第二幅是卷积后序列的实部,第三幅是卷积后序列的虚部,由于二维图像无法同时绘制出复数(a+bi),所以将实部和虚部分开展示。

现在,我们来介绍卷积功能。

卷积功能:

卷积和dft在操作方法上的的不同之处在于,卷积有两个原始序列,所以有两个Entry,分别作为原始序列x1和x2的输入口。

ce9f50f9f1552d44507bfdd89761c919.png

输入数据的方法同dft,这里就不再重复了,不同的是,卷积的两个原始序列分别显示在了两个不同text中,这样方便观看。数据输入完后,就点击输入结束——计算——展示结果,然后就会出现计算结果。

如图,上述数据计算结果:

3072d390a2a499dfc551fdf88085e503.png

现在,我们再来动手操作一遍:

591cfb2bf25aafa08e5da3484c36c0f0.png
卷积计算方法https://www.zhihu.com/video/1221903583496581120

我们已经介绍完了计算器的使用方法,现在我将代码开源,欢迎大家来完善功能。笔者编程能力有限,这个程序算是笔者学习gui的小试牛刀了。

import numpy as np
from tkinter import *
import matplotlib.pyplot as plt
import seaborn
		

 

root=Tk()

draw=IntVar()
draw.set(1)
f4=Frame()
lf1=LabelFrame(relief=GROOVE,text='是否做图:')

ra1=Radiobutton(lf1,text='是',variable=draw,value=1)
ra2=Radiobutton(lf1,text='否',variable=draw,value=0)
ra1.grid(row=1,column=1)
ra2.grid(row=1,column=2)
la2=Label(f4,text="请选择")
la3=Label(f4,text="功能")
la2.pack()
la3.pack()
ck1=IntVar()
ck2=IntVar()
ck1.set(0)
ck2.set(0)
cb1=Checkbutton(f4,text="dft",variable=ck1,width=4,indicatoron=1,justify='left')
cb2=Checkbutton(f4,text="卷积",variable=ck2,width=4,indicatoron=1,justify='left')
cb1.pack()
w1=Toplevel()
w1.title('计算结果')
w1.withdraw()

cb2.pack()
f4.pack(side='left')
t1=Text(width=30,height=10)
t2=Text(width=15,height=10)
t3=Text(w1,width=30,height=20)
t3.pack()


a=StringVar()
a.set('输入口1')
b=StringVar()
b.set('输入口2')
f1=Frame()
f1.pack()
la1=Label(f1,text='计算器',width=24)
la1.pack()
f2=Frame(relief=SUNKEN,bd=2)
f2.pack()
en1=Entry(f2,width=24,textvariable=a)
en1.pack()
en2=Entry(f2,width=24,textvariable=b)
en2.pack()
f3=Frame()
lf1.pack()







def c1(a):
    
    v=a
    t1.insert('insert',v)
    t1.insert('insert',' ')
    en1.delete(0,END)
   
def c1b(a):
    v=a
    t2.insert('insert',v)
    t2.insert('insert',' ')
    en2.delete(0,END)
   
    


        
def c2(event):
    if ck1.get()==1 and ck2.get()==0:
        c=t1.delete("0.0","end")
    else:
        c=t1.delete("0.0","end")
        c=t2.delete("0.0","end")
        
def c3(event):
    if ck1.get()==1 and ck2.get()==0:
        t1.insert('insert','-->')
    elif ck1.get()==0 and ck2.get()==1:
        t1.insert('insert','-->')
        t2.insert('insert','-->')
        
def c4(a):
    if ck1.get()==1 and ck2.get()==0:
        y=t1.get("0.0","end")
        u=0
        k=0
        m=0
        n=0
        p=[]
        j=[]
        h=[]
        x=y.split(' ')
        x.remove('-->n')   
        m=len(x)
        while n<m:
            x[n]=int(x[n])
            n=n+1
        w=np.fft.fft(x)   
        print(w)
        t3.insert('insert',w)
        while k<m:
            j.append(w[k].imag)
            k=k+1
        while u<m:
            h.append(w[u].real)
            u=u+1
        draw2=a
        
        if draw2==1:
            fig,ax=plt.subplots(3,1)
            ax[0].stem(range(m),x)
            ax[0].set_xlabel('k')
            ax[0].set_ylabel('h(k)')
            ax[1].stem(range(m),h)
            ax[1].set_xlabel('k')
            ax[1].set_ylabel('H(k)real')
            ax[2].stem(range(m),j)
            ax[2].set_xlabel('k')
            ax[2].set_ylabel('H(k)imag')
         
            plt.show()
    elif ck1.get()==0 and ck2.get()==1:
        y1=t1.get("0.0","end")
        u=0
        k=0
        m=0
        n=0
        p=[]
        j=[]
        h=[]
        x1=y1.split(' ')
        x1.remove('-->n')   
        m=len(x1)
        while n<m:
            x1[n]=int(x1[n])
            n=n+1
            
        y2=t2.get("0.0","end")
        u=0
        k=0
        m=0
        n=0
        p=[]
        j=[]
        h=[]
        x2=y2.split(' ')
        x2.remove('-->n')   
        m=len(x2)
        while n<m:
            x2[n]=int(x2[n])
            n=n+1
        y3=np.convolve(x1,x2)
        print(y3)
        t3.insert('insert',y3)
        draw1=a
        
        if draw1==1:
            x3=len(x1)+len(x2)-1
            plt.stem(range(x3),y3)
            plt.show()



       
        
    elif  ck1.get()==1 and ck2.get()==1:
        t1.delete("0.0","end")
        t1.insert('insert',"不能同时选择多种功能")

    elif  ck1.get()==0 and ck2.get()==0:
        t1.delete("0.0","end")
        t1.insert('insert',"请选择一种功能")
def c5(o,i):
    if o=='1':
        
        if i not in '0123456789 -->输入口':
            la1.config(text='输入只能是数字',fg='red')
            return False
        else:
            la1.config(text='计算器',fg='black')
    return True
  
def c7():
    if ck1.get()==1 and ck2.get()==0:
        la2.config(text="已选择")
        la3.config(text="dft")
        t2.pack_forget()
        
        t1.config(width=30,height=10)
        en2.pack_forget()
    elif  ck1.get()==0 and ck2.get()==1:
        la2.config(text="已选择")
        la3.config(text="卷积")
        t1.config(width=15,height=10)
        t2.pack(side='right')
        en2.pack()
        
    elif  ck1.get()==1 and ck2.get()==1:
        la2.config(text="不能同")
        la3.config(text="时选择")
        t2.pack_forget()
        
        t1.config(width=30,height=10)

    elif  ck1.get()==0 and ck2.get()==0:
        la2.config(text="请选择")
        la3.config(text="功能")
        t2.pack_forget()
        
        t1.config(width=30,height=10)
    
c6=en1.register(c5)    
en1.config(validate='all',validatecommand=(c6,'%d','%S'))
c8=en2.register(c5)
en2.config(validate='all',validatecommand=(c8,'%d','%S'))
b1=Button(f3,width=5,text='清空')
b2=Button(f3,width=5,text='计算')
b3=Button(f3,width=6,text='输入结束')
b4=Button(f3,width=6,text='显示结果',command=w1.deiconify)
b1.grid(row=1,column=3)
b2.grid(row=1,column=2)
b3.grid(row=1,column=1)
b4.grid(row=1,column=4)
en1.bind('<Return>',lambda event: c1(en1.get()))
en2.bind('<Return>',lambda event: c1b(en2.get()))
b1.bind('<Button-1>',c2)
b3.bind('<Button-1>',c3)
b2.bind('<Button-1>',lambda event: c4(draw.get()))
cb1.config(command=c7)
cb2.config(command=c7)






f3.pack()

t1.pack(side='left')


root.mainloop()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值