计算机视觉(Python)
题目: 使用 Python 和 OpenCV 实现一个简单的物体边缘检测程序。
要求通过以下四个按钮实现:
读取一张本地的彩色图片。
将彩色图片转换为灰度图片。
使用 Canny 边缘检测算法对灰度图片进行边缘检测。
显示原始彩色图片和边缘检测后的图片(在窗口的左侧)。

import cv2
import numpy as np
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
class ImageProcessingApp:
def __init__(self, root):
self.root = root
self.root.title("Image Processing")
self.image = None
self.gray = None
self.edges = None
# 创建左侧图像显示区域
self.image_frame = tk.Frame(root)
self.image_frame.pack(side=tk.LEFT, padx=10, pady=10)
# 创建右侧按钮区域
self.button_frame = tk.Frame(root)
self.button_frame.pack(side=tk.RIGHT, padx=10, pady=10)
# 创建按钮
self.read_button = tk.Button(self.button_frame, text="读取一张本地的彩色图片", command=self.read_image)
self.read_button.pack(pady=5)
self.gray_button = tk.Button(self.button_frame, text="将彩色图片转换为灰度图片", command=self.convert_to_gray,
state=tk.DISABLED)
self.gray_button.pack(pady=5)
self.canny_button = tk.Button(self.button_frame, text="使用 Canny 边缘检测算法对灰度图片进行边缘检测",
command=self.apply_canny, state=tk.DISABLED)
self.canny_button.pack(pady=5)
self.display_button = tk.Button(self.button_frame, text="显示原始彩色图片和边缘检测后的图片",
command=self.display_images,
state=tk.DISABLED)
self.display_button.pack(pady=5)
# 创建图像显示标签
self.original_label = tk.Label(self.image_frame)
self.original_label.pack(pady=5)
self.edges_label = tk.Label(self.image_frame)
self.edges_label.pack(pady=5)
self.combined_label = tk.Label(self.image_frame)
self.combined_label.pack(pady=5)
def read_image(self):
file_path = filedialog.askopenfilename(filetypes=[("Image files", "*.jpg;*.png;*.jpeg")])
if file_path:
self.image = cv2.imread(file_path)
if self.image is not None:
# 获取屏幕尺寸
screen_width = 1920
screen_height = 1080
# 计算压缩后的尺寸
target_width = int(screen_width / 4)
target_height = int(screen_height / 4)
# 压缩图像
self.image = cv2.resize(self.image, (target_width, target_height))
self.show_image(self.original_label, self.image)
self.gray_button.config(state=tk.NORMAL)
self.read_button.config(state=tk.DISABLED)
def convert_to_gray(self):
self.gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)
self.canny_button.config(state=tk.NORMAL)
self.gray_button.config(state=tk.DISABLED)
def apply_canny(self):
self.edges = cv2.Canny(self.gray, 100, 200)
edges_color = cv2.cvtColor(self.edges, cv2.COLOR_GRAY2BGR)
self.show_image(self.edges_label, edges_color)
self.display_button.config(state=tk.NORMAL)
self.canny_button.config(state=tk.DISABLED)
def display_images(self):
edges_color = cv2.cvtColor(self.edges, cv2.COLOR_GRAY2BGR)
combined_image = np.hstack((self.image, edges_color))
self.show_image(self.combined_label, combined_image)
self.display_button.config(state=tk.DISABLED)
def show_image(self, label, img):
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = Image.fromarray(img)
img = ImageTk.PhotoImage(image=img)
label.config(image=img)
label.image = img
if __name__ == "__main__":
root = tk.Tk()
app = ImageProcessingApp(root)
root.mainloop()
整体功能概述
这段 Python 代码借助 tkinter 库构建图形用户界面(GUI),同时使用 OpenCV 库来处理图像。GUI 界面分为左右两部分,左侧用于展示图像,右侧有四个按钮,用户点击这些按钮能依次完成图像的读取、灰度转换、边缘检测以及图像合并显示等操作。
代码详细解释
1. 导入必要的库
python
import cv2
import numpy as np
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
cv2:OpenCV 库,用于图像处理。numpy:用于处理数组和矩阵,在图像数据处理中经常用到。tkinter:Python 的标准 GUI 库,用于创建图形用户界面。filedialog:tkinter的子模块,用于打开文件选择对话框。Image和ImageTk:PIL(Python Imaging Library)库的一部分,用于处理和显示图像。
2. 定义 ImageProcessingApp 类
python
class ImageProcessingApp:
def __init__(self, root):
self.root = root
self.root.title("Image Processing")
self.image = None
self.gray = None
self.edges = None
__init__是类的构造函数,在创建类的实例时会自动调用。self.root:存储tkinter的主窗口对象。self.root.title("Image Processing"):设置主窗口的标题为 "Image Processing"。self.image、self.gray和self.edges:分别用于存储原始彩色图像、灰度图像和边缘检测后的图像,初始值为None。
3. 创建界面布局
python
# 创建左侧图像显示区域
self.image_frame = tk.Frame(root)
self.image_frame.pack(side=tk.LEFT, padx=10, pady=10)
# 创建右侧按钮区域
self.button_frame = tk.Frame(root)
self.button_frame.pack(side=tk.RIGHT, padx=10, pady=10)
tk.Frame:用于创建一个框架,可作为容器来组织其他组件。pack方法:用于将框架放置在主窗口中,side=tk.LEFT表示将图像显示区域放在左侧,side=tk.RIGHT表示将按钮区域放在右侧,padx和pady用于设置组件的内外边距。
4. 创建按钮
python
# 创建按钮
self.read_button = tk.Button(self.button_frame, text="读取一张本地的彩色图片", command=self.read_image)
self.read_button.pack(pady=5)
self.gray_button = tk.Button(self.button_frame, text="将彩色图片转换为灰度图片", command=self.convert_to_gray,
state=tk.DISABLED)
self.gray_button.pack(pady=5)
self.canny_button = tk.Button(self.button_frame, text="使用 Canny 边缘检测算法对灰度图片进行边缘检测",
command=self.apply_canny, state=tk.DISABLED)
self.canny_button.pack(pady=5)
self.display_button = tk.Button(self.button_frame, text="显示原始彩色图片和边缘检测后的图片", command=self.display_images,
state=tk.DISABLED)
self.display_button.pack(pady=5)
tk.Button:用于创建按钮,text参数设置按钮上显示的文本,command参数指定按钮被点击时调用的函数。state=tk.DISABLED:将按钮初始状态设置为禁用,只有在满足一定条件时才启用。pack方法:将按钮放置在按钮区域中,pady=5用于设置按钮之间的垂直间距。
5. 创建图像显示标签
python
# 创建图像显示标签
self.original_label = tk.Label(self.image_frame)
self.original_label.pack(pady=5)
self.edges_label = tk.Label(self.image_frame)
self.edges_label.pack(pady=5)
self.combined_label = tk.Label(self.image_frame)
self.combined_label.pack(pady=5)
tk.Label:用于创建标签,可用于显示文本或图像。pack方法:将标签放置在图像显示区域中,pady=5用于设置标签之间的垂直间距。
6. 读取图像的函数
python
def read_image(self):
file_path = filedialog.askopenfilename(filetypes=[("Image files", "*.jpg;*.png;*.jpeg")])
if file_path:
self.image = cv2.imread(file_path)
if self.image is not None:
# 获取屏幕尺寸
screen_width = 1920
screen_height = 1080
# 计算压缩后的尺寸
target_width = int(screen_width / 4)
target_height = int(screen_height / 4)
# 压缩图像
self.image = cv2.resize(self.image, (target_width, target_height))
self.show_image(self.original_label, self.image)
self.gray_button.config(state=tk.NORMAL)
self.read_button.config(state=tk.DISABLED)
filedialog.askopenfilename:打开文件选择对话框,让用户选择一张本地图片,filetypes参数指定可选择的文件类型。cv2.imread:读取用户选择的图片。cv2.resize:将图像压缩到屏幕尺寸的 1/4。self.show_image:调用显示图像的函数,将原始图像显示在self.original_label标签中。self.gray_button.config(state=tk.NORMAL):启用 “将彩色图片转换为灰度图片” 按钮。self.read_button.config(state=tk.DISABLED):禁用 “读取一张本地的彩色图片” 按钮,防止用户重复读取图片。
7. 转换为灰度图像的函数
python
def convert_to_gray(self):
self.gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)
self.canny_button.config(state=tk.NORMAL)
self.gray_button.config(state=tk.DISABLED)
cv2.cvtColor:将彩色图像转换为灰度图像。self.canny_button.config(state=tk.NORMAL):启用 “使用 Canny 边缘检测算法对灰度图片进行边缘检测” 按钮。self.gray_button.config(state=tk.DISABLED):禁用 “将彩色图片转换为灰度图片” 按钮,防止用户重复转换。
8. 应用 Canny 边缘检测的函数
python
def apply_canny(self):
self.edges = cv2.Canny(self.gray, 100, 200)
edges_color = cv2.cvtColor(self.edges, cv2.COLOR_GRAY2BGR)
self.show_image(self.edges_label, edges_color)
self.display_button.config(state=tk.NORMAL)
self.canny_button.config(state=tk.DISABLED)
cv2.Canny:对灰度图像应用 Canny 边缘检测算法,100和200是阈值参数。cv2.cvtColor:将边缘检测后的灰度图像转换为彩色图像,以便在tkinter中显示。self.show_image:将边缘检测后的图像显示在self.edges_label标签中。self.display_button.config(state=tk.NORMAL):启用 “显示原始彩色图片和边缘检测后的图片” 按钮。self.canny_button.config(state=tk.DISABLED):禁用 “使用 Canny 边缘检测算法对灰度图片进行边缘检测” 按钮,防止用户重复检测。
9. 显示合并图像的函数
python
def display_images(self):
edges_color = cv2.cvtColor(self.edges, cv2.COLOR_GRAY2BGR)
combined_image = np.hstack((self.image, edges_color))
self.show_image(self.combined_label, combined_image)
self.display_button.config(state=tk.DISABLED)
cv2.cvtColor:将边缘检测后的灰度图像转换为彩色图像。np.hstack:将原始彩色图像和边缘检测后的图像水平拼接。self.show_image:将合并后的图像显示在self.combined_label标签中。self.display_button.config(state=tk.DISABLED):禁用 “显示原始彩色图片和边缘检测后的图片” 按钮,防止用户重复显示。
10. 显示图像的辅助函数
python
def show_image(self, label, img):
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = Image.fromarray(img)
img = ImageTk.PhotoImage(image=img)
label.config(image=img)
label.image = img
cv2.cvtColor:将 OpenCV 的 BGR 颜色空间转换为 RGB 颜色空间,因为tkinter使用 RGB 颜色空间。Image.fromarray:将 NumPy 数组转换为PIL图像对象。ImageTk.PhotoImage:将PIL图像对象转换为tkinter可显示的图像对象。label.config(image=img):将图像显示在指定的标签中。label.image = img:保存图像对象的引用,防止图像被垃圾回收。
11. 主程序入口
python
if __name__ == "__main__":
root = tk.Tk()
app = ImageProcessingApp(root)
root.mainloop()
tk.Tk():创建tkinter的主窗口对象。ImageProcessingApp(root):创建ImageProcessingApp类的实例,并将主窗口对象传递给构造函数。root.mainloop():启动tkinter的事件循环,使窗口保持显示并响应用户操作。
通过以上步骤,代码实现了一个简单的图像处理器,用户可以通过点击按钮逐步完成图像的读取、处理和显示操作。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)