当前位置: 首页 > article >正文

python 中使用tkinter构建一个图片的剪切器-附源码

由于项目需要,需要构建一个间的软件,方便查看图片的剪切的位置,并对其中的图像进行分析,实现如下的功能

  1. 简单的UI
  2. 加载图片
  3. 剪切图片
  4. 显示剪切后的图片
  • 针对图片的内容进行识别
  • 图片质量分析
    在这里插入图片描述

前端的具体代码如下,

有需要其他功能的,需定制化开发的,得加钱

import tkinter as tk  
from tkinter import filedialog  , Toplevel, Label 
from PIL import Image, ImageTk  
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg  
from matplotlib.figure import Figure  
from matplotlib.patches import Rectangle  
import matplotlib.pyplot as plt 



""" 

v8.修改整体的布局

"""

def img_analysis(img_name):
    img=cv2.imread(filename)
    part_img=img[540:673,371:702]##y1,y2,x1,x2    
    img_grey=cv2.cvtColor(part_img,cv2.COLOR_RGB2GRAY)#灰度图片#COLOR_BGR2GRAY  COLOR_RGB2GRAY IMREAD_GRAYSCALE
    img_grey_draw=img_grey#用于画图    
    hist = cv2.calcHist([img_grey],[0],None,[256],[0,255])  # 应用高斯模糊,以减少图像噪声  #统计直方图数据
    ret, thresh = cv2.threshold(img_grey, 80, 255, cv2.THRESH_BINARY)  #80# 应用二值化 
    # ------------计算黑色像素的数量
    black_pixels = np.count_nonzero(thresh == 0)# 计算黑色像素的数量    
    total_pixels = thresh.shape[0] * thresh.shape[1]# ------------计算总的像素数量
    black_ratio = black_pixels / total_pixels# ------------计算黑色像素的占比print(f"黑色像素的占比: {black_ratio:.4f}")   
    # 数据
    black = black_ratio*100
    white = 100-black
    # 标签
    labels = ['Black', 'White']    
    edges = cv2.Canny(thresh, threshold1=100, threshold2=200)# 应用Canny边缘检测    
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 寻找轮廓    
    cv2.drawContours(img_grey_draw, contours, -1, (0, 255, 0), 3)# 绘制轮廓

#new windows to show the feature of opencv

class ImageGridWindow(Toplevel):  
    def __init__(self, master, images):  
        super().__init__(master)  
        self.title("Image Grid")  
        # 返回按钮  
        self.return_button = tk.Button(self, text="Return", command=self.destroy)  
        self.return_button.pack(side=tk.BOTTOM, fill=tk.X, pady=10)  

        # 假设images是一个包含图片路径的列表,且长度为9  
        self.grid_size = 3  
        self.create_widgets(images)   
  
    def create_widgets(self, images):  
        for i, img_path in enumerate(images):  
            # 这里假设所有图片大小相同,或者您已经根据需要进行了调整  
            img = Image.open(img_path)  
            img = img.resize((100, 100), Image.ANTIALIAS)  # 假设每个图片调整为100x100  
            photo = ImageTk.PhotoImage(img)   
            label = Label(self, image=photo)  
            label.image = photo  # 避免垃圾回收  
            row, col = divmod(i, self.grid_size)  
            label.grid(row=row, column=col, padx=5, pady=5) 


#Everybody to reset your data. 
class ImageLabelerApp:  
    def __init__(self, root):  
        self.root = root  
        self.root.title("Image Labeler")  
        #------------------------ 顶部按钮 
        # 创建一个新的框架用于grid布局  
        top_frame = tk.Frame(root)  
        top_frame.pack(fill=tk.X, expand=False)    

        self.load_button = tk.Button(top_frame, text="Load Image", command=self.load_image)  
        self.load_button.grid(row=0, column=1, padx=10,pady=10)  
        # Tkinter reset button  
        self.reset_button = tk.Button(top_frame, text="Reset", command=self.reset) 
        self.reset_button.grid(row=0, column=2, padx=10) 
        # Tkinter button  
        self.button = tk.Button(top_frame, text="Show Cropped Image", command=self.show_cropped_image)  
        self.button.grid(row=0, column=3, padx=10)  
        # 添加打开图片网格的按钮  
        self.grid_button = tk.Button(top_frame, text="Open Image Grid", command=self.open_image_grid)  
        self.grid_button.grid(row=0, column=4,  padx=10)  
 
        #------------------------  中部图片
            # 底部左右两个图像显示区域  
        bottom_images_frame = tk.Frame(root)  
        bottom_images_frame.pack(fill=tk.BOTH, expand=True)  
        # ------------right_image_label  Label for cropped image    
        self.cropped_label = tk.Label(bottom_images_frame, bg='white')  #, width=40, height=20
        self.cropped_label.grid(row=0, column=1, sticky='nsew', padx=5, pady=5)  
        #------------left image 
       #left_image_label  = tk.Label(bottom_images_frame, bg='white', width=40, height=20)  
        #left_image_label.grid(row=0, column=0, sticky='nsew', padx=5, pady=5)
        self.fig, self.ax = plt.subplots(figsize=(6, 6))  
        self.canvas = FigureCanvasTkAgg(self.fig, master=bottom_images_frame)  
        self.canvas.get_tk_widget().grid(row=0, column=0, sticky='nsew', padx=5, pady=5) 
 
        # 添加文本框来显示矩形坐标 


        # #------------------------  底部文字
        self.coord_label = tk.Label(root, text="No rectangle selected", width=30, height=20)  
        self.coord_label.pack(side=tk.BOTTOM, fill=tk.X,padx=10) 

        self.img_path = None  
        self.img = None  
        self.rect = None  
        self.drawing = False  
        self.cropped_img = None  
        self.cropped_photo = None   
  
        # Connect events  
        self.canvas.mpl_connect('button_press_event', self.on_button_press)  
        self.canvas.mpl_connect('button_release_event', self.on_button_release) # 绑定事件以在鼠标释放时更新坐标  
        self.canvas.mpl_connect('motion_notify_event', self.on_mouse_move)                  
 
  
    def load_image(self):  
        path=filedialog.askopenfilename(filetypes=[("Image files", "*.jpg")])#;*.png;*.gif  09-07 only jpg,
        self.img_path = path  
        self.img = plt.imread(path)  
        self.ax.imshow(self.img)  
        self.ax.set_title('Original Image')  
        self.canvas.draw()  
  
    def on_button_press(self, event):  
        if not self.rect and event.button == 1:  
            self.x0, self.y0 = event.xdata, event.ydata  
            self.drawing = True  
  
    def on_mouse_move(self, event):  
        if self.drawing:  
            x1, y1 = event.xdata, event.ydata  
            if self.rect is None:  
                self.rect = Rectangle((self.x0, self.y0), 0, 0, edgecolor='r', facecolor='none')  
                self.ax.add_patch(self.rect)  
  
            self.rect.set_width(x1 - self.x0)  
            self.rect.set_height(y1 - self.y0)  
            self.canvas.draw()  
  
    def on_button_release(self, event):  
        if self.drawing and event.button == 1:  
            self.drawing = False  
        # -----------------检查是否正在绘制矩形  -----------------
        if self.rect is not None:  
            # 获取矩形的坐标(注意:这里获取的是数据坐标,不是像素坐标)  
            x0, y0 = self.rect.get_xy()  
            width, height = self.rect.get_width(), self.rect.get_height()  
            x1, y1 = x0 + width, y0 + height  
            # 格式化坐标字符串  
            coord_str = f"Rectangle Coordinates: ({x0:.2f}, {y0:.2f}) to ({x1:.2f}, {y1:.2f})"  
            # 更新文本框的文本  
            self.coord_label.config(text=coord_str) 

    def show_cropped_image(self):  
        if self.rect:  
            x0, y0 = int(self.rect.get_x()), int(self.rect.get_y())  
            width, height = int(self.rect.get_width()), int(self.rect.get_height())             
            cropped_img = self.img[y0:y0+height, x0:x0+width]  
            self.cropped_img = Image.fromarray(cropped_img)  
            self.cropped_photo = ImageTk.PhotoImage(self.cropped_img)  
            self.cropped_label.config(image=self.cropped_photo)  
            self.cropped_label.image = self.cropped_photo  # Keep a reference  
    def reset(self):  
        # 清除Axes上的所有内容(包括矩形)  
        self.ax.clear()  
        self.ax.imshow(self.img)  # 重新加载原始图像  
        self.ax.set_title('Original Image')  
        self.cropped_img = None  
        self.cropped_photo = None         
        self.rect = None   # 如果之前绘制了矩形,则将其设置为None           
        self.canvas.draw()# 重新绘制画布 
    def open_image_grid(self):  
        # 这里需要一个图片列表,这里只是示例  
        # 假设您已经有了一个包含9个图片路径的列表  
        image_paths = [  
            'path/to/image1.jpg', 'path/to/image2.jpg', 'path/to/image3.jpg',  
            'path/to/image4.jpg', 'path/to/image5.jpg', 'path/to/image6.jpg',  
            'path/to/image7.jpg', 'path/to/image8.jpg', 'path/to/image9.jpg'  
        ]  
        ImageGridWindow(self.root, image_paths) 
def main():  
    root = tk.Tk()  
    app = ImageLabelerApp(root)  
    root.mainloop()  
  
if __name__ == '__main__':  
    main()

http://www.kler.cn/a/295032.html

相关文章:

  • leetcode 2043.简易银行系统
  • 系统安全架构
  • android openGL中模板测试、深度测试功能的先后顺序
  • Python小白学习教程从入门到入坑------第二十八课 文件基础操作文件读写(语法进阶)
  • 计算机网络——TCP中的流量控制和拥塞控制
  • vue项目使用高德地图
  • 漫谈设计模式 [15]:观察者模式
  • 9. 相机控件OrbitControls
  • C++11线程池、多线程编程(附源码)
  • 信息熵|atttion矩阵的注意力熵
  • 设计并用Java实现一个简易的规则引擎
  • Python | Leetcode Python题解之第392题判断子序列
  • 【leetcode详解】爬楼梯:DP入门典例(附DP通用思路 同类进阶练习)
  • 使用Protocol Buffers传输数据
  • 在vscode中用virtual env的方法
  • git如何灵活切换本地账号对应远程github的两个账号
  • 代码随想录:279. 完全平方数
  • 如何在Selenium中使用Chrome进行网络限速
  • ComfyUI+Krea免费利用AI制作网站萌宠IP,五步搞定制作AI萌宠
  • React 响应事件
  • 【Godot4.3】多边形的斜线填充效果基础实现
  • 在Ubuntu 20.04上安装Nginx的方法
  • 懒人笔记-opencv4.8.0篇
  • 【详解 Java 注解】
  • 一些数学经验总结——关于将原一元二次函数增加一些限制条件后最优结果的对比(主要针对公平关切相关的建模)
  • 分数阶微积分MATLAB计算