由于项目需要,需要构建一个间的软件,方便查看图片的剪切的位置,并对其中的图像进行分析,实现如下的功能
- 简单的UI
- 加载图片
- 剪切图片
- 显示剪切后的图片
- 针对图片的内容进行识别
- 图片质量分析
前端的具体代码如下,
有需要其他功能的,需定制化开发的,得加钱
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_GRAYSCALEimg_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*100white = 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 opencvclass 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=20self.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()