diff --git a/study_python/tkinter-opencv/main.py b/study_python/tkinter-opencv/main.py new file mode 100644 index 0000000..e4439b6 --- /dev/null +++ b/study_python/tkinter-opencv/main.py @@ -0,0 +1,176 @@ +import cv2 +import numpy as np +import os +from tkinter import Tk +from tkinter.filedialog import askopenfilename + +# 创建一个 Tkinter 根窗口 +root = Tk() +root.withdraw() + +# 打开文件对话框,选择图片文件 +filename = askopenfilename(title='选择图片', filetypes=[('Image Files', ('*.jpg', '*.jpeg', '*.png', '*.bmp'))]) + +# 检查是否选择了文件 +if filename: + # 读取选中的图片文件 + image = cv2.imread(filename) + + # 定义全局变量 + points = [] + completed = False + extracted_image = None + + # 定义鼠标回调函数 + def mouse_callback(event, x, y, flags, param): + global points, completed, extracted_image + + if event == cv2.EVENT_LBUTTONDOWN: + # 存储点击的坐标 + points.append((x, y)) + + # 绘制已选择的点 + cv2.circle(image, (x, y), 5, (0, 0, 255), -1) + + # 绘制连接的线段 + if len(points) > 1: + cv2.line(image, points[-2], points[-1], (0, 0, 255), 5) + + # 绘制最后一个点与第一个点的连线 + if len(points) == 4: + cv2.line(image, points[-1], points[0], (0, 0, 255), 5) + completed = True + + # 创建窗口并注册鼠标回调函数 + cv2.namedWindow('image') + cv2.setMouseCallback('image', mouse_callback) + + while True: + # 显示图像 + cv2.imshow('image', image) + + # 按下 'Esc' 键退出循环 + if cv2.waitKey(1) == 27: + break + + # 检查是否成功获取四边形 + if completed: + # 创建与原图像大小相同的掩膜图像 + mask = np.zeros_like(image[:, :, 0]) + + # 使用填充多边形函数将四边形区域设置为白色 + cv2.fillPoly(mask, [np.array(points)], 255) + + # 将掩膜应用到原图像上,提取方框内的内容 + extracted_image = cv2.bitwise_and(image, image, mask=mask) + + # 将方框外的像素值设置为0 + extracted_image[np.where(extracted_image == 0)] = 0 + + # 显示提取的图像 + cv2.imshow('extracted_image', extracted_image) + + # 获取文件名和扩展名 + file_dir = os.path.dirname(filename) + file_name = os.path.basename(filename) + file_name, file_ext = os.path.splitext(file_name) + + # 构建新的文件名 + extracted_image_file_name = os.path.join(file_dir, file_name + "_boundary" + file_ext) + + # 保存提取后的图像 + cv2.imwrite(extracted_image_file_name, extracted_image) + + # 转换提取后的图像到 LAB 色彩空间 + lab_image = cv2.cvtColor(extracted_image, cv2.COLOR_BGR2LAB) + segmented_image = [] + combined_image = [] + + # 定义鼠标事件回调函数 + def mouse_callback1(event, x, y, flags, param): + global segmented_image, combined_image + + if event == cv2.EVENT_LBUTTONDOWN: + if combined_image[y, x, 0] == 0 and combined_image[y, x, 1] == 0 and combined_image[y, x, 2] == 0: + # 创建临时变量用于处理连通域 + segmented_image[y-8:y+8, x-8:x+8] = 255 + colored_segmented_image = cv2.cvtColor(segmented_image, cv2.COLOR_GRAY2BGR) + combined_image = cv2.bitwise_and(extracted_image, colored_segmented_image) + cv2.imshow('segmented_image', combined_image) + + leaf_image_file_name = os.path.join(file_dir, file_name + "_leaf" + file_ext) + cv2.imwrite(leaf_image_file_name, combined_image) + nonzero_pixels_b = np.count_nonzero(extracted_image[:, :, 0]) + nonzero_pixels_leaf = np.count_nonzero(combined_image[:, :, 0]) + result_file = os.path.join(file_dir, file_name + "_result.txt") + file = open(result_file, 'w') + file.truncate(0) + file.write('采样框像素点数为' + str(nonzero_pixels_b)) + file.write('采样框内绿叶像素点数为' + str(nonzero_pixels_leaf)) + file.close() + + # 定义滑动条的回调函数 + def on_trackbar(value): + global segmented_image + global combined_image + lower_th = cv2.getTrackbarPos('L', 'segmented_image') + upper_th = cv2.getTrackbarPos('A', 'segmented_image') + v_value = cv2.getTrackbarPos('B', 'segmented_image') + + # 根据滑动条的值创建阈值范围 + lower = np.array([lower_th, upper_th, v_value], dtype=np.uint8) + upper = np.array([255, 255, 255], dtype=np.uint8) + + # 对 LAB 图像进行阈值分割 + segmented_image = cv2.inRange(lab_image, lower, upper) + + # 反转二值图像 + segmented_image = cv2.bitwise_not(segmented_image) + + # 将二值图像转换为彩色图像 + colored_segmented_image = cv2.cvtColor(segmented_image, cv2.COLOR_GRAY2BGR) + # 进行位逻辑与操作,将彩色分割图像与提取图像进行合并 + combined_image = cv2.bitwise_and(extracted_image, colored_segmented_image) + # 显示合并后的图像 + cv2.imshow('segmented_image', combined_image) + leaf_image_file_name = os.path.join(file_dir, file_name + "_leaf" + file_ext) + cv2.imwrite(leaf_image_file_name, combined_image) + nonzero_pixels_b = np.count_nonzero(extracted_image[:, :, 0]) + nonzero_pixels_leaf = np.count_nonzero(combined_image[:, :, 0]) + result_file = os.path.join(file_dir, file_name + "_result.txt") + file = open(result_file, 'w') + file.truncate(0) + file.write('采样框像素点数为' + str(nonzero_pixels_b)) + file.write('采样框内绿叶像素点数为' + str(nonzero_pixels_leaf)) + file.close() + + # 创建窗口用于显示分割结果 + cv2.namedWindow('segmented_image') + cv2.setMouseCallback('segmented_image', mouse_callback1) + + # 创建滑动条 + cv2.createTrackbar('L', 'segmented_image', 0, 255, on_trackbar) + cv2.createTrackbar('A', 'segmented_image', 0, 255, on_trackbar) + cv2.createTrackbar('B', 'segmented_image', 0, 255, on_trackbar) + + # 初始化滑动条的值 + cv2.setTrackbarPos('L', 'segmented_image', 0) + cv2.setTrackbarPos('A', 'segmented_image', 115) + cv2.setTrackbarPos('B', 'segmented_image', 0) + + while True: + # 按下 'Esc' 键退出循环 + if cv2.waitKey(1) == 27: + break + + # 重置标志和列表,以便选择下一个方框 + completed = False + points.clear() + + # 退出循环 + break + + # 释放窗口和销毁所有窗口 + cv2.destroyAllWindows() +else: + print("未选择图像文件") diff --git a/study_python/tkinter-opencv/main.spec b/study_python/tkinter-opencv/main.spec new file mode 100644 index 0000000..e03e1a6 --- /dev/null +++ b/study_python/tkinter-opencv/main.spec @@ -0,0 +1,44 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['main.py'], + pathex=[], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + [], + exclude_binaries=True, + name='main', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + console=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +) +coll = COLLECT( + exe, + a.binaries, + a.datas, + strip=False, + upx=True, + upx_exclude=[], + name='main', +) diff --git a/study_python/tkinter-opencv/requirements.txt b/study_python/tkinter-opencv/requirements.txt new file mode 100644 index 0000000..c394276 --- /dev/null +++ b/study_python/tkinter-opencv/requirements.txt @@ -0,0 +1,2 @@ +numpy==2.0.0 +opencv_python==4.10.0.84