每日总结
一 实验目的
l 使学生综合运用图形用户界面设计的概念;
l 使学生熟悉使用中间面板,组成层次复杂的GUI界面;
l 使学生掌握Python图形绘制和图像处理步骤与方法;
l 使学生掌握Python可视化处理的步骤、方法与编程;
二 实验环境及实验准备
l 所需硬件环境为微机;
l 所需软件环境为Python 3.X等;
l 掌握Python下界面容器与基本组件的基本知识与应用;
l 掌握Python下事件处理模型;
l 掌握Python下图形绘制的方法;
三 实验内容
(一)、设计实现电子算盘,并完成测试
【题目描述】
给小朋友设计一个电子算盘。要求绘制电子算盘界面,设计并实现打珠算过程(界面参考如下图示)。
界面右侧要求以图形绘制的方式绘制自画像,注意不能是图像文件显示的形式。
from tkinter import *
tk = Tk()
tk.title("电子算盘") # 窗口名称
tank = Canvas(tk, width=1000, height=600, bg='ivory') # 创建画板
tank.pack() # 显示画板
tank.create_rectangle(30, 30, 520, 190, width=3) # 左上侧方框
tank.create_rectangle(30, 190, 520, 570, width=3) # 左下侧方框
tank.create_oval(900, 400, 620, 120, fill='yellow')
tank.create_oval(800, 200, 850, 250, fill='black', tags='left')
tank.create_oval(670, 200, 720, 250, fill='black', tags='right')
tank.create_line(695, 320, 825, 320, width=5, tags='mouth')
backround_image = PhotoImage(file="orange2.png") # 上珠图片
backround_image2 = PhotoImage(file="yellow2.png") # 下珠图片
button = Button()
button1 = [button for i in range(5)] # 5个上珠
button2 = [[button for i in range(5)] for i in range(4)] # 四行,每行五个下珠
num = [[0 for i in range(5)] for i in range(4)] # 五个下珠分别对应的数值
num2 = [0 for i in range(5)] # 五个上珠分别对应的数值
def getNum(num, num2): # 计算算盘总和
sum_ = 0
for i in num:
for j in i:
sum_ += j
for i in num2:
sum_ += i
return sum_
def button_click_back(events): # 鼠标右击点击事件触发
widget = events.widget
for i in range(5):
if widget == button1[i]:
button1[i].place(x=40 + 100 * i, y=50 + 70 * 1)
num2[i] = 0
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
for i in range(4):
for j in range(5):
if widget == button2[i][j]:
if i == 3:
button2[3][j].place(x=40 + 100 * j, y=210 + 70 * (i + 1))
num[3][j] = 0
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
if i == 2:
button2[2][j].place(x=40 + 100 * j, y=210 + 70 * (i + 1))
button2[3][j].place(x=40 + 100 * j, y=210 + 70 * (i + 2))
num[2][j] = 0
num[3][j] = 0
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
if i == 1:
button2[1][j].place(x=40 + 100 * j, y=210 + 70 * (i + 1))
button2[2][j].place(x=40 + 100 * j, y=210 + 70 * (i + 2))
button2[3][j].place(x=40 + 100 * j, y=210 + 70 * (i + 3))
num[1][j] = 0
num[2][j] = 0
num[3][j] = 0
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
if i == 0:
button2[0][j].place(x=40 + 100 * j, y=210 + 70 * (i + 1))
button2[1][j].place(x=40 + 100 * j, y=210 + 70 * (i + 2))
button2[2][j].place(x=40 + 100 * j, y=210 + 70 * (i + 3))
button2[3][j].place(x=40 + 100 * j, y=210 + 70 * (i + 4))
num[0][j] = 0
num[1][j] = 0
num[2][j] = 0
num[3][j] = 0
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
def button_click(events): # 鼠标左击点击事件触发
widget = events.widget
for i in range(5):
if widget == button1[i]:
button1[i].place(x=40 + 100 * i, y=50 + 70 * 0)
num2[i] = 10 ** (4 - i) * 5
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
for i in range(4):
for j in range(5):
if widget == button2[i][j]:
if i == 3:
button2[0][j].place(x=40 + 100 * j, y=210 + 70 * (i - 3))
button2[1][j].place(x=40 + 100 * j, y=210 + 70 * (i - 2))
button2[2][j].place(x=40 + 100 * j, y=210 + 70 * (i - 1))
button2[3][j].place(x=40 + 100 * j, y=210 + 70 * (i))
num[0][j] = 10 ** (4 - j) * 1
num[1][j] = 10 ** (4 - j) * 1
num[2][j] = 10 ** (4 - j) * 1
num[3][j] = 10 ** (4 - j) * 1
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
if i == 2:
button2[0][j].place(x=40 + 100 * j, y=210)
button2[1][j].place(x=40 + 100 * j, y=210 + 70 * 1)
button2[2][j].place(x=40 + 100 * j, y=210 + 70 * 2)
num[0][j] = 10 ** (4 - j) * 1
num[1][j] = 10 ** (4 - j) * 1
num[2][j] = 10 ** (4 - j) * 1
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
if i == 1:
button2[0][j].place(x=40 + 100 * j, y=210)
button2[1][j].place(x=40 + 100 * j, y=210 + 70 * 1)
num[0][j] = 10 ** (4 - j) * 1
num[1][j] = 10 ** (4 - j) * 1
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
else:
button2[i][j].place(x=40 + 100 * j, y=210 + 70 * i)
num[0][j] = 10 ** (4 - j) * 1
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
for i in range(5): # 生成5个上珠
button1[i] = Button(tk, image=backround_image)
button1[i].bind("<Button-1>", button_click)
button1[i].bind("<Button-3>", button_click_back)
button1[i]["bg"] = "ivory"
button1[i]["border"] = "0"
button1[i].place(x=40 + 100 * i, y=50 + 70)
for i in range(4): # 四行,每行生成5个下珠
for j in range(5):
button2[i][j] = Button(tk, image=backround_image2)
button2[i][j].bind("<Button-1>", button_click)
button2[i][j].bind("<Button-3>", button_click_back)
button2[i][j]["bg"] = "ivory"
button2[i][j]["border"] = "0"
button2[i][j].place(x=40 + 100 * j, y=210 + 70 * (i + 1))
tk.mainloop()
【运行测试】
(二)、以(一)中的电子算盘为基础,设计并实现珠算测试器,并完成测试。
【题目描述】
给小朋友设计一个珠算测试器,要求能够完成珠算加减法的测试。具体的要求功能如下:
(1) 用户启动测试,输入用户名后系统随机生成特定数目的加减法测试题;
(2) 要求测试使用表盘式或数字时秒表进行界面计时显示(参考如上图示);
(3) 对于每道测试题目,要求用户使用电子算盘完成珠算过程,当按下确认键时,将珠算结果与正确答案比对,并在界面上显示总题数、已答题数和已做对题数;
(4) 当测试完成,界面显示本次测试情况(包括用户名、测试题目及答题明细、对错情况、测试用时和测试成绩)
【源代码程序】
【运行测试】
from random import randint
from tkinter import *
import tkinter.messagebox as msgbox
tk = Tk()
tk.title("电子算盘") # 窗口名称
tank = Canvas(tk, width=1000, height=600, bg='ivory') # 创建画板
tank.pack() # 显示画板
tank.create_rectangle(30, 30, 520, 190, width=3) # 左上侧方框
tank.create_rectangle(30, 190, 520, 570, width=3) # 左下侧方框
# tank.create_oval(900, 400, 620, 120, fill='yellow')
# tank.create_oval(800, 200, 850, 250, fill='black', tags='left')
# tank.create_oval(670, 200, 720, 250, fill='black', tags='right')
# tank.create_line(695, 320, 825, 320, width=5, tags='mouth')
backround_image = PhotoImage(file="orange2.png") # 上珠图片
backround_image2 = PhotoImage(file="yellow2.png") # 下珠图片
button = Button()
button1 = [button for i in range(5)] # 5个上珠
button2 = [[button for i in range(5)] for i in range(4)] # 四行,每行五个下珠
num = [[0 for i in range(5)] for i in range(4)] # 五个下珠分别对应的数值
num2 = [0 for i in range(5)] # 五个上珠分别对应的数值
counter = 0
sure = Button() # 确定按钮
st = Button() # 启动检测按钮
equation = Label() # 算式
answer = Label(width=50, height=7) # 答题情况
name = Entry() # 用户名输入
true_result = Label(width=50, height=4) # 上一题的正确答案
digit = Label(tk, bg='yellow', fg='blue', height=5, width=25, font='宋体 10 bold') # 计时器
true = 0 # 已做对题数
false = 0 # 做错题数
score = 0 # 题目得分
result = 0 # 每道题的正确答案
topic = "" # 题目
def run_counter(digit, second): # 计时器
def counting():
global counter
if second == 1:
counter += 1
else:
counter += 0
digit.config(text="计时器:" + str(counter))
digit.after(1000, counting)
counting()
def getNum(num, num2): # 计算算盘总和
sum_ = 0
for i in num:
for j in i:
sum_ += j
for i in num2:
sum_ += i
return sum_
def suanshi(): # 生成随机加减法测试题
answer = 0
operator = ""
num1 = 0
num2 = 0
p = randint(1, 2)
if p == 1:
while True:
num1 = randint(0, 99999)
num2 = randint(0, 99999)
if num1 + num2 <= 99999:
break
answer = num1 + num2
operator = "+"
elif p == 2:
while True:
num1 = randint(0, 99999)
num2 = randint(0, 99999)
if num1 - num2 > 0:
break
answer = num1 - num2
operator = "-"
equation = str(num1) + operator + str(num2)
return equation, answer
def button_click_back(events): # 鼠标右击点击事件触发
widget = events.widget
for i in range(5):
if widget == button1[i]:
button1[i].place(x=40 + 100 * i, y=50 + 70 * 1)
num2[i] = 0
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
for i in range(4):
for j in range(5):
if widget == button2[i][j]:
if i == 3:
button2[3][j].place(x=40 + 100 * j, y=210 + 70 * (i + 1))
num[3][j] = 0
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
if i == 2:
button2[2][j].place(x=40 + 100 * j, y=210 + 70 * (i + 1))
button2[3][j].place(x=40 + 100 * j, y=210 + 70 * (i + 2))
num[2][j] = 0
num[3][j] = 0
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
if i == 1:
button2[1][j].place(x=40 + 100 * j, y=210 + 70 * (i + 1))
button2[2][j].place(x=40 + 100 * j, y=210 + 70 * (i + 2))
button2[3][j].place(x=40 + 100 * j, y=210 + 70 * (i + 3))
num[1][j] = 0
num[2][j] = 0
num[3][j] = 0
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
if i == 0:
button2[0][j].place(x=40 + 100 * j, y=210 + 70 * (i + 1))
button2[1][j].place(x=40 + 100 * j, y=210 + 70 * (i + 2))
button2[2][j].place(x=40 + 100 * j, y=210 + 70 * (i + 3))
button2[3][j].place(x=40 + 100 * j, y=210 + 70 * (i + 4))
num[0][j] = 0
num[1][j] = 0
num[2][j] = 0
num[3][j] = 0
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
def button_click(events): # 鼠标左击点击事件触发
widget = events.widget
for i in range(5):
if widget == button1[i]:
button1[i].place(x=40 + 100 * i, y=50 + 70 * 0)
num2[i] = 10 ** (4 - i) * 5
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
for i in range(4):
for j in range(5):
if widget == button2[i][j]:
if i == 3:
button2[0][j].place(x=40 + 100 * j, y=210 + 70 * (i - 3))
button2[1][j].place(x=40 + 100 * j, y=210 + 70 * (i - 2))
button2[2][j].place(x=40 + 100 * j, y=210 + 70 * (i - 1))
button2[3][j].place(x=40 + 100 * j, y=210 + 70 * (i))
num[0][j] = 10 ** (4 - j) * 1
num[1][j] = 10 ** (4 - j) * 1
num[2][j] = 10 ** (4 - j) * 1
num[3][j] = 10 ** (4 - j) * 1
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
if i == 2:
button2[0][j].place(x=40 + 100 * j, y=210)
button2[1][j].place(x=40 + 100 * j, y=210 + 70 * 1)
button2[2][j].place(x=40 + 100 * j, y=210 + 70 * 2)
num[0][j] = 10 ** (4 - j) * 1
num[1][j] = 10 ** (4 - j) * 1
num[2][j] = 10 ** (4 - j) * 1
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
if i == 1:
button2[0][j].place(x=40 + 100 * j, y=210)
button2[1][j].place(x=40 + 100 * j, y=210 + 70 * 1)
num[0][j] = 10 ** (4 - j) * 1
num[1][j] = 10 ** (4 - j) * 1
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
else:
button2[i][j].place(x=40 + 100 * j, y=210 + 70 * i)
num[0][j] = 10 ** (4 - j) * 1
label = Label(tk, text="当前数字:" + str(getNum(num, num2)), width=30, height=4)
label.place(x=780, y=30)
def start():
global name
global equation
global sure
global result
global digit
global topic
st.place_forget()
digit.place(x=540, y=30)
run_counter(digit, 1)
Label(tk, text="用户名", bg="ivory").place(x=540, y=150)
name = Entry(tk, show='', font=('Arial', 14))
name.place(x=580, y=150)
p = suanshi()
topic = p[0]
result = p[1]
equation = Label(tk, text=topic, width=40, height=4)
equation.place(x=540, y=200)
sure = Button(text="确定", command=judge, width=10, height=3)
sure.place(x=850, y=200)
def judge(): # 判断结果
global true
global false
global score
global topic
global result
global true_result
if true + false == 5:
msgbox.showinfo('温馨提示', '恭喜您已做完所有题目!!!')
answer["text"] = "用户名:" + name.get() + "\n已答题数:" + str(true + false) + "\n做对题数:" + str(true) + "\n做错题数:" \
+ str(false) + "\n测试时长:" + str(counter) + "s" + "\n测试成绩:" + str(score) + "\n答题完毕!!!"
answer.place(x=540, y=400)
else:
print(getNum(num, num2), result)
if getNum(num, num2) == result:
true += 1
score += 20
else:
false += 1
answer["text"] = "总题数:5\n已答题数:" + str(true + false) + "\n已做对题数:" + str(true) + "\n做错题数:" + str(
false) + "\n得分:" + str(
score)
answer.place(x=540, y=400)
p = suanshi()
true_result["text"] = "上一题题目:" + topic + "\n上一题正确答案:" + str(result)
equation["text"] = p[0]
result = p[1]
equation.place(x=540, y=200)
true_result.place(x=540, y=300)
for i in range(5): # 生成5个上珠
button1[i] = Button(tk, image=backround_image)
button1[i].bind("<Button-1>", button_click)
button1[i].bind("<Button-3>", button_click_back)
button1[i]["bg"] = "ivory"
button1[i]["border"] = "0"
button1[i].place(x=40 + 100 * i, y=50 + 70)
for i in range(4): # 四行,每行生成5个下珠
for j in range(5):
button2[i][j] = Button(tk, image=backround_image2)
button2[i][j].bind("<Button-1>", button_click)
button2[i][j].bind("<Button-3>", button_click_back)
button2[i][j]["bg"] = "ivory"
button2[i][j]["border"] = "0"
button2[i][j].place(x=40 + 100 * j, y=210 + 70 * (i + 1))
st = Button(text="启动测试", command=start, width=50, height=10)
st.place(x=600, y=100)
tk.mainloop()
四 实验分析及问题思考
查找资料,结合实例代码,至少比较三种Python图形处理库或图像处理库的异同点。【答案】python的图像处理库有很多种比如:pillow库 、Numpy库、Scipy库、opencv库、pgmagic库等
其中较常用的是NUmapy库、pillow库 、openCV库,今天我们就这三种图像处理库来进行比较
首先是numapy库;
他是一个python库可以帮助我们处理所有类型的科学计算,他是在执行任何数据预处理或数据科学相关任务是导入的第一个库,处理图像可以说是一个”副业“
使用他我们可以非常方便的操纵图像的RGB值其操作代码:
from PIL import Image
import numpy as np
img = np.array(Image.open('0.jpg'))
img_red = img.copy()
img_red[:, :, (1, 2)] = 0
img_green = img.copy()
img_green[:, :, (0, 2)] = 0
img_blue = img.copy()
img_blue[:, :, (0, 1)] = 0
img_ORGB = np.concatenate((img,img_red, img_green, img_blue), axis=1)
img_converted = Image.fromarray(img_ORGB)
img_converted.show() ## Combine Image Contains
其次就pillow库他是python中最常用的图像处理库之一,它提供了许多可以用来操纵图像的函数,例如:调整大小,改变滤镜,等等是python中常用且便捷的操作可之一
下面是一个可以使图片对比度更加明显的代码:
from PIL import Image,ImageEnhance
img_original = Image.open("dark.jpg")
img_original.show("Original Image")
img = ImageEnhance.Contrast(img_original)
img.enhance(3.8).show("Image With More Contrast")
openCV库也是python中最常用的图像处理库之一,他的有点在于他可以方便的与网络摄像头图像和视频进行交互,并且他可以执行多种实时任务,
目前主要应用于人脸识别检测,和目标检测等
下面是应用他进行crop操作的代码样例:
import cv2
img = cv2.imread("images/test.jpg")
imgCropped = img[50:283,25:190]
shape = imgCropped.shape
print(shape[0])
imgCropped = cv2.resize(imgCropped,(shape[0]*12//10,shape[1]*2))
cv2.imshow("Image cropped",imgCropped)
cv2.imshow("Image",img)
cv2.waitKey(0)
除了上述三中提到的图像处理课歪还有一种图像处理库其作用和pillow库很相似只不过他多用于处理图像的旋转、锐化、简便等操作他就是pgmagick库
他其实是graphicsMagick库的补充下面是锐化带样例代码:
from pgmagick.api import Image
img = Image('fox.png')
# scaling image up to 1.5x
img.scale((150, 100), 'fox_scaled')
上述介绍了几种图像处理库的大概功能下面叙述其各自优缺点以及异同点
1.scikit-image
scikit-image是一个开源的Python包,适用于numpy数组。它实现了用于研究,教育和工业应用的算法和实用工具。即使是那些刚接触Python生态系统的人,它也是一个相当简单直接的库。此代码是由活跃的志愿者社区编写的,具有高质量和同行评审的性质。
2.Numpy
Numpy是Python编程的核心库之一,并为数组提供支持。图像本质上是包含数据点像素的标准Numpy数组。因此,我们可以通过使用基本的NumPy操作,例如切片、掩膜和花式索引,来修改图像的像素值。可以使用skimage加载图像并使用matplotlib显示图像。
3.Scipy
scipy是Python的另一个类似Numpy的核心科学模块,可用于基本的图像操作和处理任务。特别是子模块scipy.ndimage,提供了在n维NumPy数组上操作的函数。该包目前包括线性和非线性滤波,二值形态学,B样条插值和对象测量等功能函数。
4. PIL/Pillow
PIL是Python编程语言的一个免费库,它支持打开、操作和保存许多不同的文件格式的图像。然而,随着2009年的最后一次发布,它的开发停滞不前。但幸运的是还有Pillow,一个PIL积极开发的且更容易安装的分支,它能运行在所有主要的操作系统,并支持Python3。这个库包含了基本的图像处理功能,包括点运算、使用一组内置卷积核的滤波和色彩空间的转换。
5.OpenCV-Python
OpenCV是计算机视觉应用中应用最广泛的库之一
。OpenCV-Python是OpenCV的python版API。OpenCV-Python的优点不只有高效,这源于它的内部组成是用C/C++编写的,而且它还容易编写和部署。这使得它成为执行计算密集型计算机视觉程序的一个很好的选择。
Python可视化训练
班级:信2105-2 学号:20213848 姓名:付楚楚
实验自评
实验内容 |
自评结果(在对应格内打ü) |
|||
不熟练 |
一般 |
比较熟练 |
熟练 |
|
Python容器与组件的布局应用 |
|
|
|
ü |
Python界面事件设计 |
|
|
|
ü |
Python图形绘制应用 |
|
|
|
ü |
Python图像处理应用 |
|
|
|
ü |
实验体会
这次实验我体会到了Python可视化的强大功能,我不断熟悉训练Python的技术,会将Python掌握的更加熟练
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下