python制作APP,此APP可识别TEM图片结构轮廓,并将坐标提取到excel中,画出TEM结构轮廓图(tkinter,opencv-python)

该博客介绍了使用Python的Tkinter库构建一个包含登录和注册功能的图形界面应用。用户可以输入用户名和密码进行登录,系统会检查用户信息并提供错误提示。如果用户未注册,可以选择注册,注册时需要输入用户名、密码和确认密码。同时,系统还包含了图像处理,用于显示背景图片。注册信息存储在pickle文件中,实现了简单的数据持久化。
摘要由CSDN通过智能技术生成

模块一:main主函数

from tkinter import (Tk, Text, Scrollbar)
from tkinter.constants import (HORIZONTAL, VERTICAL, RIGHT, LEFT, X, Y, BOTH, BOTTOM, YES, NONE, END, CURRENT)
import time
import tkinter as tk
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
import os
from tkinter import filedialog,ttk
from PIL import ImageTk, Image
from tkinter import StringVar
import botton
import get
import pickle

gui = tk.Tk()  
gui.title("用户登录")
canvas_root = tk.Canvas(gui, width=500, height=300)
im_root = get.get_img(r"C:\Users\xujunkang\Desktop\nexchip.jpg", 1000, 600)
canvas_root.create_image(500, 300, image= im_root)
canvas_root.pack(side="top")  


# 两个文字标签,用户名和密码两个部分
tk.Label(gui, text='用户名').place(x=100, y=150)
tk.Label(gui, text='密  码').place(x=100, y=190)

var_usr_name = tk.StringVar()  # 讲文本框的内容,定义为字符串类型
var_usr_name.set('123456789@qq.com')  # 设置默认值
var_usr_pwd = tk.StringVar()

# 第一个输入框-用来输入用户名的。
# textvariable 获取文本框的内容
entry_usr_name = tk.Entry(gui, textvariable=var_usr_name)
entry_usr_name.place(x=160, y=150)
# 第二个输入框-用来输入密码的。
entry_usr_pwd = tk.Entry(gui, textvariable=var_usr_pwd, show='*')
entry_usr_pwd.place(x=160, y=190)

count = 0
def usr_login():
    usr_name = var_usr_name.get()
    usr_pwd = var_usr_pwd.get()
    try:
        with open('usrs_info.pickle', 'rb') as usr_file:
            usrs_info = pickle.load(usr_file)
    except FileNotFoundError:
        with open('usrs_info.pickle', 'wb') as usr_file:
            usrs_info = {'admin': 'admin'}
            pickle.dump(usrs_info, usr_file)

    if usr_name in usrs_info:
        global count
        if usr_pwd == usrs_info[usr_name]:
            gui.destroy()
            botton.main_1()
        elif count < 5:
            tk.messagebox.showinfo(title='登录提示',message='用户名或密码错误!')#登录提示
            count += 1#计数加一
        else:
          tk.messagebox.showinfo(title='登录提示',message='已连续错误5次!请稍后再试!');gui.destroy()
    else:
        is_sign_up = tk.messagebox.askyesno('提示', '你还没有注册,请先注册')
        print(is_sign_up)
        if is_sign_up:
            usr_sign_up()


# 注册按钮
def usr_sign_up():
    def sign_to_Mofan_Python():
        np = new_pwd.get()
        npf = new_pwd_confirm.get()
        nn = new_name.get()
        # 上面是获取数据,下面是查看一下是否重复注册过
        with open('usrs_info.pickle', 'rb') as usr_file:
            exist_usr_info = pickle.load(usr_file)
            if np != npf:
                tk.messagebox.showerror('错误提示', '密码和确认密码必须一样')
            elif nn in exist_usr_info:
                tk.messagebox.showerror('错误提示', '用户名早就注册了!')
            else:
                exist_usr_info[nn] = np
                with open('usrs_info.pickle', 'wb') as usr_file:
                    pickle.dump(exist_usr_info, usr_file)
                tk.messagebox.showinfo('欢迎', '你已经成功注册了')
                window_sign_up.destroy()

    # 点击注册之后,会弹出这个窗口界面。
    window_sign_up = tk.Toplevel(gui)
    window_sign_up.title('欢迎注册')
    window_sign_up.geometry('360x200')  # 中间是x,而不是*号

    # 用户名框--这里输入用户名框。
    new_name = tk.StringVar()
    new_name.set('123456789@qq.com')  # 设置的是默认值
    tk.Label(window_sign_up, text='用户名').place(x=10, y=10)
    entry_new_name = tk.Entry(window_sign_up, textvariable=new_name)
    entry_new_name.place(x=100, y=10)

    # 新密码框--这里输入注册时候的密码
    new_pwd = tk.StringVar()
    tk.Label(window_sign_up, text='密  码').place(x=10, y=50)
    entry_usr_pwd = tk.Entry(window_sign_up, textvariable=new_pwd, show='*')
    entry_usr_pwd.place(x=100, y=50)
    # 密码确认框
    new_pwd_confirm = tk.StringVar()
    tk.Label(window_sign_up, text='确认密码').place(x=10, y=90)
    entry_usr_pwd_confirm = tk.Entry(
        window_sign_up, textvariable=new_pwd_confirm, show='*')
    entry_usr_pwd_confirm.place(x=100, y=90)

    btn_confirm_sign_up = tk.Button(
        window_sign_up, text=' 注  册 ', command=sign_to_Mofan_Python)
    btn_confirm_sign_up.place(x=120, y=130)


# 创建注册和登录按钮
btn_login = tk.Button(gui, text=' 登  录 ', command=usr_login)
btn_login.place(x=150, y=230)  # 用place来处理按钮的位置信息。
btn_sign_up = tk.Button(gui, text=' 注  册 ', command=usr_sign_up)
btn_sign_up.place(x=250, y=230)

gui.mainloop()

#button = tk.Button(gui, text="注册账户", command= build)
#button.place(x=100, y=200, width=50, height=40)

#button2 = tk.Button(gui, text="退出", command= destory)
#button2.place(x=100, y=250, width=50, height=40)
gui.mainloop()  
模块二:botton模块

# -*- coding: utf-8 -*-
"""
Created on Thu Aug 25 11:15:48 2022

@author: xujunkang
"""

from tkinter import (Tk, Text, Scrollbar)
from tkinter.constants import (HORIZONTAL, VERTICAL, RIGHT, LEFT, X, Y, BOTH, BOTTOM, YES, NONE, END, CURRENT)
import time
import tkinter as tk
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
import os
from tkinter import filedialog,ttk
from PIL import ImageTk, Image
from tkinter import StringVar
import openpyxl
from openpyxl import Workbook
import get
    

def main_1():
    root = tk.Tk()  
    root.title("轮廓提取APP")
    
    canvas_root = tk.Canvas(root, width=1000, height=600)
    im_root = get.get_img(r"X:/04 project/08python_study/open_cv/image.JPG", 1000, 600)
    canvas_root.create_image(500, 300, image= im_root)
    canvas_root.pack(side="top") 
    
    label = tk.Label(root,text="提取TEM轮廓",font=("Arial",20))
    # 显示label,pack函数是自适应
    label.place(x=300, y=50, width=500, height=40)
    
    
    btn1 = tk.Button(root)  # 创建按钮,并且将按钮放到窗口里面
    btn1["text"] = "点击查看轮廓情况"  # 给按钮一个名称
    btn1.place(x=100, y=550, width=100, height=40)  # 按钮布局
    
    
    
    def getfile():
         file_path=filedialog.askopenfilename()
         fpath.set(file_path)
      
    def destory():
        root.destroy()
    
    
    
    fpath = tk.StringVar()
    text = tk.Entry(root, textvariable= fpath)
    text.place(x=600, y=550, width=300, height=40)
    
    
    menus=tk.Menu(root)#在window上创建一个菜单栏menus
    num1=tk.Menu(menus)#在menus上面创建一个选项栏num1
    menus.add_cascade(label='文件',menu=num1)#将num1命名为Menu1
    num1.add_command(label='打开',command=getfile)#在num1上增加一个Open命令,执行的cod
    num1.add_command(label='退出',command=destory)#在num1上增加一个退出命令
    num2=tk.Menu(menus)#在menus上面创建一个选项num1
    menus.add_cascade(label='编辑',menu=num2)#将num2命名为Menu1
    num2.add_command(label='撤销')
    num2.add_command(label='复制',command=destory)#在num2上增加一个退出命令
    root.config(menu=menus)#将window的menu改为我们所定义的menus
    
    
    def threshold_demo(image):
            # 去噪声+二值化
         dst = cv.GaussianBlur(image,(3, 3), 0)
         gray = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
         ret, binary = cv.threshold(gray, 90, 255, cv.THRESH_BINARY)
         cv.imshow("binary", binary)
         return binary
        
    
        
    
    def canny_demo(image):
          t = 100
          canny_output = cv.Canny(image, t, t * 2)
          cv.imshow("canny_output", canny_output)
          return canny_output
        
    
    def contour(img_input):
          src = cv.imread(img_input)
    
    
          height,width = src.shape[:2]
    
          img=cv.resize(src,(width//2,height//2),interpolation=cv.INTER_CUBIC) 
    
          binary = threshold_demo(img)
    
        
    
        # 轮廓发现
          contours, hierarchy= cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    
          cv.drawContours(img, contours, -1, (0, 110, 255), 2)  # 2为像素大小,-1时填充轮廓
         
        
    
        # 显示
          cv.imshow("contours-demo",img)
        
          cv.waitKey(0)
          cv.destroyAllWindows()
         
              
          
          log= tk.Tk()
          log.title('output')
          log.geometry('630x630')
          
          scroll = tk.Scrollbar(log)
    # 放到窗口的右侧, 填充Y竖直方向
          
          txt = tk.Text(log)
          scroll.pack(side=tk.RIGHT,fill=tk.Y)
          txt.pack(side=tk.LEFT,fill=tk.Y)
    # 两个控件关联
          scroll.config(command=txt.yview)
          txt.config(yscrollcommand=scroll.set)
          
          
          txt.insert(tk.INSERT,contours)
          wb = Workbook()
          dest_filename = "Empty_book.xlsx"
          ws1 = wb.active
          ws1.title = 'TEMcontours'
          row= ws1.max_row
          print(row)
          col= ws1.max_column
          print(col)
          A= contours[0]
          B=A.tolist()
          L=len(B)
          print()
          for i in range(0,L):
                  C=B[i]
                  ws1.append(C[0])
          wb.save(dest_filename)
          log.mainloop()
    
    def start(e):
          window = tk.Tk()
          window.title('running')
          window.geometry('630x150')
     
    # 设置下载进度条
          tk.Label(window, text='程序运行中' ).place(x=50, y=60)
          canvas = tk.Canvas(window, width=465, height=22, bg="white")
          canvas.place(x=110, y=60)
          fill_line = canvas.create_rectangle(1.5, 1.5, 0, 23, width=0, fill="green")
          x = 300  # 未知变量,可更改
          n = 465 / x  # 465是矩形填充满的次数
          for i in range(x):
            n = n + 465 / x
            canvas.coords(fill_line, (0, 0, n, 60))
            window.update()
            time.sleep(0.001)  # 控制进度条流动的速度
     
        # 清空进度条
          fill_line = canvas.create_rectangle(1.5, 1.5, 0, 23, width=0, fill="white")
          x = 500  # 未知变量,可更改
          n = 465 / x  # 465是矩形填充满的次数
     
          for t in range(x):
             n = n + 465 / x
            # 以矩形的长度作为变量值更新
             canvas.coords(fill_line, (0, 0, n, 60))
             window.update()
             time.sleep(0)  # 时间为0,即飞速清空进度条
          window.destroy()
          
          
          img_path= fpath.get()
          contour(img_path)
          
          
    
    btn1.bind("<Button-1>", start)  # 将按钮和方法进行绑定,也就是创建了一个事件
    
    
    
    
    root.mainloop()  # 加上这一句,就可以看见窗口了


模块三:

# -*- coding: utf-8 -*-
"""
Created on Fri Aug 26 13:19:09 2022

@author: xujunkang
"""
from tkinter import (Tk, Text, Scrollbar)
from tkinter.constants import (HORIZONTAL, VERTICAL, RIGHT, LEFT, X, Y, BOTH, BOTTOM, YES, NONE, END, CURRENT)
import time
import tkinter as tk
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
import os
from tkinter import filedialog,ttk
from PIL import ImageTk, Image
from tkinter import StringVar
import botton


def get_img(filename, width, height):
    im = Image.open(filename).resize((width, height))
    im = ImageTk.PhotoImage(im)
    return im


模块四:excel

# -*- coding: utf-8 -*-
"""
Created on Mon Sep 19 14:32:51 2022

@author: xujunkang
"""
import openpyxl


workbook = openpyxl.load_workbook("X:/04 project/08python_study/open_cv/Empty_book.xlsx")
print(workbook.sheetnames)


# 2.通过 sheet 名称获取表格
sheet1 = workbook["TEMcontours"]
print(sheet1)
print(sheet1.dimensions)
A=sheet1.min_column
B=sheet1.max_column
C=sheet1.min_row
D=sheet1.max_row
print(A)
print(B)
print(C)
print(D)
points=[]
for i in range(1,D):
    for j in range(1,B):
        cell=sheet1.cell(row=i,column=j).value
        j=j+1
        cell2=sheet1.cell(row=i,column=j).value
        list1=(cell,cell2)
        points.append(list1)
print(points)

首次接触图像处理,通过次来记录自己的学习记录,以方便回忆。 //指针访问像素 void colorReduce(Mat& temImage, int div) { //行数 int rowNumber = temImage.rows; cout << "图像通道数:" << temImage.channels() << endl; //列数*通道数=每一行的元素个数 int colNumber = temImage.cols * temImage.channels(); for (int row = 0; row < rowNumber;row++) { uchar* data = temImage.ptr<uchar>(row); for (int col = 0; col < colNumber;col++) { data[col] = data[col] / div*div + div / 2; } } } //迭代器iterator操作像素 void iterColorReduce(Mat& temImage,int div) { Mat_<Vec3b>::iterator it = temImage.begin<Vec3b>(); Mat_<Vec3b>::iterator itend = temImage.end<Vec3b>(); //存取彩色图像的像素 while (it != itend) { //开始处理每个像素 (*it)[0] = (*it)[0] / div*div + div / 2; (*it)[1] = (*it)[1] / div*div + div / 2; (*it)[2] = (*it)[2] / div*div + div / 2; ++it; } } //动态地址计算像素 void atColorReduce(Mat& temImage, int div) { int rowNumber = temImage.rows; int colNumber = temImage.cols; //存取彩色图像 for (int row = 0; row < rowNumber; row++) { for (int col = 0; col < colNumber; col++) { //开始处理每个图像 //蓝色通道 temImage.at<Vec3b>(row, col)[0] = temImage.at<Vec3b>(row, col)[0] / div*div + div / 2; //绿色通道 temImage.at<Vec3b>(row, col)[1] = temImage.at<Vec3b>(row, col)[1] / div*div + div / 2; //红色通道 temImage.at<Vec3b>(row, col)[2] = temImage.at<Vec3b>(row, col)[2] / div*div + div / 2; } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值