Cách tạo ảnh ghép bằng Python
Ảnh ghép là một cách hay để giới thiệu những kỷ niệm và hiển thị các bộ hình ảnh. Các nhà sản xuất ảnh ghép trực tuyến có thể lo ngại về bảo mật và các ứng dụng ngoại tuyến có thể tốn tiền và thiếu các tính năng bạn yêu cầu.
Người ta có thể giảm bớt sự e ngại và duy trì quyền lực tuyệt đối bằng cách xây dựng trình tạo ảnh ghép của riêng mình. Do đó, làm cách nào để xây dựng một công cụ như vậy?
Mô-đun Tkinter và PIL
Để xây dựng giao diện người dùng đồ họa cho ứng dụng ghép ảnh, việc sử dụng cả thư viện Tkinter và Thư viện hình ảnh Python (PIL) là cần thiết. Cái trước cho phép tạo các ứng dụng dựa trên máy tính để bàn thông qua việc cung cấp các yếu tố hình ảnh hoặc “widget” khác nhau, giúp hợp lý hóa quy trình thiết kế Giao diện người dùng đồ họa (GUI).
Thư viện Pillow, một phiên bản phái sinh của Thư viện hình ảnh Python (PIL) được đánh giá cao, cung cấp một loạt các tính năng xử lý hình ảnh nhằm hỗ trợ các tác vụ như chỉnh sửa, tạo và lưu nhiều loại tệp phương tiện trực quan khác nhau.
Để cài đặt Tkinter và Pillow có thể được bắt đầu bằng cách mở giao diện dòng lệnh và thực hiện lệnh sau:
pip install tk pillow
Thiết lập GUI và thao tác hình ảnh
Người ta có thể định vị mã nguồn của dự án này trong kho GitHub chuyên dụng của nó, đóng vai trò là kho lưu trữ kỹ thuật số của tất cả các tệp và tài liệu liên quan đến nó.
Để bắt đầu, bắt buộc phải nhập các mô-đun cần thiết. Sau đó, chúng ta sẽ tạo một lớp mới có tên là ImageCollageApp
, lớp này sẽ đóng vai trò là đối tượng ứng dụng chính. Bước đầu tiên liên quan đến việc đặt tiêu đề và kích thước của cửa sổ. Sau đó, chúng tôi sẽ tạo một canvas bằng phương thức tk.Canvas()
và định cấu hình phần tử gốc, chiều rộng, chiều cao và màu nền của nó.
import tkinter as tk
from tkinter import filedialog, simpledialog, messagebox
from PIL import Image, ImageTk
class ImageCollageApp:
def __init__(self, root):
self.root = root
self.root.title("Image Collage Maker")
self.images = []
self.image_refs = []
self.collage_size = (600, 500)
self.collage_canvas = tk.Canvas(
self.root,
width=self.collage_size[0],
height=self.collage_size[1],
bg="white",
)
self.collage_canvas.pack()
Đảm bảo rằng người dùng đã cấp quyền nhập tệp trước khi tạo đối tượng FileReader để đọc tệp hình ảnh từ thiết bị của họ.
Bắt đầu cấu trúc dữ liệu có tên là “hình ảnh\_positions” để lưu trữ vị trí trực quan của các thành phần phương tiện trong giao diện người dùng đồ họa. Triển khai ba quy trình xử lý sự kiện riêng biệt để giải quyết các hành động chọn, di chuyển và giải phóng liên quan đến các thành phần phương tiện nói trên.
self.btn_add_image = tk.Button(
self.root,
text="Add Image",
command=self.add_images,
font=("Arial", 12, "bold"),
)
self.btn_add_image.pack(pady=10)
self.btn_create_collage = tk.Button(
self.root,
text="Create Collage",
command=self.create_collage,
font=("Arial", 12, "bold"),
)
self.btn_create_collage.pack(pady=5)
self.drag_data = {"x": 0, "y": 0, "item": None}
self.image_positions = []
self.collage_canvas.bind("<ButtonPress-1>", self.on_press)
self.collage_canvas.bind("<B1-Motion>", self.on_drag)
self.collage_canvas.bind("<ButtonRelease-1>", self.on_release)
Để triển khai chức năng được mô tả trong đoạn mã được cung cấp, trước tiên chúng ta cần xác định một phương thức có tên là “on\_press”. Phương pháp này được kích hoạt khi người dùng nhấp chuột trong khi vẽ trên khung vẽ. Mục tiêu của phương pháp này là truy xuất đối tượng canvas gần nhất đến điểm mà người dùng nhấp chuột và lưu trữ nó trong từ điển “drag\_data”. Ngoài ra, chúng tôi sẽ lưu trữ tọa độ X và Y của lần nhấp chuột để sau này chúng tôi có thể tính toán khoảng cách người dùng đã di chuyển chuột của họ trong quá trình kéo.
def on_press(self, event):
self.drag_data["item"] = self.collage_canvas.find_closest(event.x, event.y)[0]
self.drag_data["x"] = event.x
self.drag_data["y"] = event.y
Để triển khai chức năng được mô tả trong đoạn mã được cung cấp, cần xác định một phương thức có tên là “on\_drag” sẽ được kích hoạt khi người dùng di chuyển chuột trong khi giữ nút trái. Phương pháp này sẽ tính toán khoảng cách theo chiều ngang và chiều dọc mà con trỏ di chuyển trong quá trình kéo bằng cách sử dụng các biến “dx” và “dy”. Dựa trên các giá trị này, vị trí của hình ảnh sau đó có thể được cập nhật bằng cách sửa đổi thuộc tính “x” và “y” của đối tượng “hình ảnh” trong tiện ích “self.canvas”. Hơn nữa, tọa độ mới cho hình ảnh phải được lưu trữ trong từ điển “drag\_data” được liên kết với phiên bản hiện tại của lớp, cho phép chúng tồn tại trên nhiều khung.
def on_drag(self, event):
delta_x = event.x - self.drag_data["x"]
delta_y = event.y - self.drag_data["y"]
self.collage_canvas.move(self.drag_data["item"], delta_x, delta_y)
self.drag_data["x"] = event.x
self.drag_data["y"] = event.y
Để xóa mọi tham chiếu còn sót lại đối với hình ảnh được kéo trước đó và tính toán lại vị trí của tất cả các thành phần hình ảnh trên khung vẽ để phản hồi sự kiện phát hành, bạn có thể triển khai phương thức “on\_release” để giải quyết những mối lo ngại này. Cụ thể, phương pháp này sẽ xóa tham chiếu đến hình ảnh đi kèm với con trỏ của người dùng trong quá trình kéo, đồng thời gọi chức năng “update\_image\_positions” để sửa lại bố cục của tất cả các hình ảnh được hiển thị sau ngừng tương tác của người dùng.
def on_release(self, event):
self.drag_data["item"] = None
self.drag_data["x"] = 0
self.drag_data["y"] = 0
self.update_image_positions()
Một cách trang nhã, chúng ta sẽ mô tả một hàm có tên “update\_image\_positions”, hàm này đòi hỏi phải xóa nội dung của mảng “image\_positions” và lặp qua mọi thành phần của khung vẽ. Trong quá trình này, đối với mỗi thành phần, chúng tôi sẽ xác định dữ liệu vị trí của nó và nối nó vào mảng nói trên.
def update_image_positions(self):
self.image_positions.clear()
for item in self.collage_canvas.find_all():
x, y = self.collage_canvas.coords(item)
self.image_positions.append((x, y))
Chắc chắn! Dưới đây là một ví dụ triển khai bằng Python bằng cách sử dụng Tkinter và thư viện Gối:pythonimport tkinter as tkfrom tkinter import filedialogimport osfrom PIL import Imagedef add_images():# create a new windowwindow=tk.Toplevel(root)# hỏi người dùng xem họ muốn bao nhiêu hình ảnh uploadnum_images=tk.Entry(window)num_images.pack()num_entries=tk.Label(window, text=“Nhập số lượng hình ảnh:")num_entries.pack()# lấy giá trị từ trường mục nhậpnum_values =num_images.get()if num_values.isdigit() và int(
Sử dụng chức năng size\_image
để thay đổi tỷ lệ hình ảnh hiện tại trong bộ nhớ, tạo một PhotoImage
mới tương thích với Tkinter. Sau đó, thêm tham chiếu đã cập nhật này vào danh sách image\_refs
trước khi cập nhật canvas bằng phương thức update\_canvas
.
def add_images(self):
num_images = simpledialog.askinteger(
"Number of Images", "Enter the number of images:"
)
if num_images is not None:
file_paths = filedialog.askopenfilenames(
filetypes=[("Image files", "*.png;*.jpg;*.jpeg;*.gif")]
)
if file_paths:
for i in range(min(num_images, len(file_paths))):
file_path = file_paths[i]
image = Image.open(file_path)
resized_image = self.resize_image(image)
self.images.append(resized_image)
self.image_refs.append(ImageTk.PhotoImage(resized_image))
self.update_canvas()
Dưới đây là một ví dụ triển khai phương thức resize\_image
trong Python:pythondef thay đổi kích thước_image(self, image):# Lấy kích thước hiện tại của imageimg_width, img_height=image.size# Tính tỷ lệ khung hình của imageaspect_ratio=img_height/img_width# Kiểm tra nếu tỷ lệ khung hình lớn hơn 1 (tức là hướng dọc) nếu tỷ lệ khung hình > 1:# Đặt chiều rộng mới bằng một nửa chiều rộng của ảnh ghépnew_width=self.collage_width/2# Tính chiều cao mới tương ứng trong khi duy trì tỷ lệ khung hìnhnew_height=int ((
Nếu tỷ lệ khung hình của ảnh ghép nhỏ hơn một, chúng tôi sẽ giảm một nửa cả chiều cao và chiều rộng bằng cách tính toán kích thước phù hợp dựa trên kích thước ban đầu của ảnh ghép. Sau đó, chúng ta có thể sử dụng chức năng thay đổi kích thước
của Gối để tạo phiên bản phóng to của ảnh ghép với các phép đo được điều chỉnh này trong khi vẫn duy trì tỷ lệ của nó.
def resize_image(self, image):
img_width, img_height = image.size
aspect_ratio = img_width / img_height
if aspect_ratio > 1:
new_width = self.collage_size[0] // 2
new_height = int(new_width/aspect_ratio)
else:
new_height = self.collage_size[1] // 2
new_width = int(new_height * aspect_ratio)
return image.resize((new_width, new_height))
Xác định một phương thức có tên là “update\_canvas” với các bước sau:1. Xóa tất cả các mục trên canvas bằng cách xóa các liên kết có thể nhấp tương ứng được liên kết với từng mục khỏi cách sắp xếp hình ảnh trước đó.2. Cung cấp cho người dùng cơ hội nhập số hàng và cột mong muốn thông qua hộp thoại tệp. Các kích thước được cung cấp phải nhất quán với các thông số kỹ thuật được đưa ra trước đó trong tài liệu này.3. Xác định tổng số cột cần thiết dựa trên số hàng được người dùng nhập vào. Trong ví dụ của chúng tôi, chúng tôi sẽ giả định rằng có sáu cột trên mỗi hàng. Tính toán chiều rộng và chiều cao của ảnh ghép cho phù hợp. Điều này có nghĩa là nếu người dùng chọn bốn hàng thì chiều rộng sẽ gấp đôi chiều rộng của một cột (6) cộng với một khoảng cách giữa chúng. Do đó
def update_canvas(self):
self.collage_canvas.delete("all")
rows = simpledialog.askinteger("Number of Rows", "Enter the number of rows:")
cols = simpledialog.askinteger(
"Number of Columns", "Enter the number of columns:"
)
collage_width = self.collage_size[0] * cols // 2
collage_height = self.collage_size[1] * rows // 2
self.collage_canvas.config(width=collage_width, height=collage_height)
self.image_positions.clear()
x_offset, y_offset = 0, 0
Lặp lại qua từng mục trong danh sách image\_refs
, tạo bản trình bày trực quan về mục đó trên khung vẽ bằng cách sử dụng phần bù được cung cấp. Định vị góc trên bên trái của hình ảnh tại tọa độ được chỉ định bằng cách đặt điểm neo của nó ở góc tây bắc. Ngoài ra, hãy thêm tọa độ tương ứng vào danh sách image\_positions
để tham khảo thêm.
Để sắp xếp hiệu quả hình ảnh tiếp theo trong lưới, điều cần thiết là phải cập nhật biến x\_offset
bằng cách thêm một nửa ảnh ghép
for i, image_ref in enumerate(self.image_refs):
self.collage_canvas.create_image(
x_offset, y_offset, anchor=tk.NW, image=image_ref
)
self.image_positions.append((x_offset, y_offset))
x_offset \+= self.collage_size[0] // 2
if (i \+ 1) % cols == 0:
x_offset = 0
y_offset \+= self.collage_size[1] // 2
Tạo ảnh ghép và lưu nó
Để tạo ra hình ảnh trực quan hấp dẫn của nhiều nội dung kỹ thuật số khác nhau, chúng tôi sẽ phát triển một chức năng được gọi là create\_collage
. Thuật toán này trước tiên sẽ kiểm tra xem có bất kỳ mục phương tiện nào đã được đưa vào bố cục hay không. Trong trường hợp không tồn tại, nó sẽ hiển thị một thông báo cảnh báo. Sau đó, kỹ thuật này sẽ xác định kích thước của đoạn phim điện tử bằng cách thu được chiều rộng và tầm vóc của nó. Tiếp theo, nó sẽ xây dựng một đối tượng Pillow Image trống mới có phông nền trắng nguyên sơ. Sau đó, hàm sẽ lặp lại danh mục tệp và đặt chúng một cách chính xác trên khung vẽ ở tọa độ được xác định trước bằng cách sử dụng thư viện PIL mạnh mẽ của Python để thao tác dữ liệu hình ảnh một cách hiệu quả.
Sử dụng trình xem hình ảnh cài sẵn để hiển thị ảnh ghép kỹ thuật số bằng cách lưu nó trước, tận dụng các khả năng tích hợp của nó để hiển thị tối ưu.
def create_collage(self):
if len(self.images) == 0:
messagebox.showwarning("Warning", "Please add images first!")
return
collage_width = self.collage_canvas.winfo_width()
collage_height = self.collage_canvas.winfo_height()
background = Image.new("RGB", (collage_width, collage_height), "white")
for idx, image in enumerate(self.images):
x_offset, y_offset = self.image_positions[idx]
x_offset, y_offset = int(x_offset), int(y_offset)
paste_box = (
x_offset,
y_offset,
x_offset \+ image.width,
y_offset \+ image.height,
)
background.paste(image, paste_box)
background.save("collage_with_white_background.jpg")
background.show()
Tận dụng các khả năng của thư viện Tkinter bằng cách khởi tạo một phiên bản mới của ứng dụng ImageCollage, được trang bị các thuộc tính và phương pháp cần thiết để tạo ảnh ghép trực quan dựa trên đầu vào của người dùng. Sau khi được thiết lập, hãy bắt đầu thực thi vòng lặp sự kiện Tkinter bằng phương pháp mainloop(). Lệnh này hướng dẫn trình thông dịch Python liên tục theo dõi và xử lý mọi sự kiện xảy ra trong cửa sổ, duy trì trạng thái của cửa sổ một cách hiệu quả cho đến khi người dùng cuối đóng cửa sổ theo cách thủ công.
if __name__ == "__main__":
root = tk.Tk()
app = ImageCollageApp(root)
root.mainloop()
Thử nghiệm các tính năng khác nhau của Trình tạo ảnh ghép
Khi thực thi ứng dụng, một giao diện có hai tùy chọn sẽ được hiển thị-“Thêm hình ảnh” và “Tạo ảnh ghép”. Khi nhấp vào tùy chọn “Thêm hình ảnh”, một cửa sổ bật lên truy vấn thông tin đầu vào của người dùng về tổng số ảnh họ muốn đưa vào ảnh ghép sẽ xuất hiện. Sau khi nhập'5’làm số lượng hình ảnh mong muốn và chọn chúng từ danh sách nhất định, một hộp thoại tiếp theo sẽ xuất hiện yêu cầu thông tin về cả số hàng ngang và cột dọc sẽ được sử dụng để tạo ảnh ghép.
Khi chèn hai hàng và ba cột của các phần tử hình ảnh trong không gian ranh giới được chỉ định, giao diện người dùng đồ họa sẽ sắp xếp chúng một cách có hệ thống dưới dạng cấu hình mảng hoặc ma trận, tạo ra một màn hình gắn kết nhấn mạnh vị trí và thứ tự của từng thành phần riêng lẻ.
Bản xem trước cho phép thao tác với hình ảnh bằng cách định vị lại chúng theo sở thích của một người. Khi nhấp vào nút “Tạo ảnh ghép”, phần mềm sẽ lưu hình ảnh thu được.
Khi kiểm tra hình ảnh trực quan của ảnh ghép được tạo, rõ ràng là ứng dụng phần mềm đã đạt được mục tiêu dự định về việc tập hợp một bộ sưu tập hình ảnh gắn kết và hấp dẫn về mặt hình ảnh.
Nâng cao chức năng của Trình tạo ảnh ghép
Thay vì sử dụng cấu trúc dựa trên bảng, có thể cung cấp cho người dùng nhiều mẫu được xác định trước để lựa chọn. Ngoài ra, hãy kết hợp các chức năng cho phép thay đổi màu nền, ghi nội dung bằng văn bản, áp dụng các tính năng cải tiến hình ảnh và tích hợp các yếu tố trang trí có nguồn gốc từ các nguồn trực tuyến.
Trong khi kết hợp các chức năng này, hãy kích hoạt một phương pháp đơn giản để sửa đổi hình ảnh tổng hợp bằng cách cung cấp các tùy chọn cho các thao tác hoàn tác hoặc vẽ lại. Hơn nữa, cho phép người dùng điều chỉnh việc cắt xén, thay đổi kích thước và hướng của từng hình ảnh theo sở thích của họ. Ngoài ra, còn bao gồm một tính năng cho phép lưu kết quả cuối cùng ở định dạng tệp đã chọn.