Contents

วิธีสร้างภาพต่อกันโดยใช้ Python

ภาพต่อกันเป็นวิธีที่สวยงามในการแสดงความทรงจำและแสดงชุดรูปภาพ เครื่องมือสร้างภาพตัดปะออนไลน์อาจมีข้อกังวลด้านความปลอดภัย และแอปออฟไลน์อาจต้องเสียค่าใช้จ่ายและขาดคุณสมบัติที่คุณต้องการ

เราอาจบรรเทาความวิตกกังวลและรักษาอำนาจโดยสมบูรณ์โดยการสร้างโปรแกรมสร้างภาพต่อกันของตนเอง แล้วเราจะสร้างเครื่องมือดังกล่าวได้อย่างไร?

โมดูล Tkinter และ PIL

ในการสร้างอินเทอร์เฟซผู้ใช้แบบกราฟิกสำหรับแอปพลิเคชันภาพตัดปะ จำเป็นต้องใช้ทั้งไลบรารี Tkinter และ Python Imaging Library (PIL) แบบแรกช่วยให้สามารถสร้างแอปพลิเคชันบนเดสก์ท็อปผ่านการจัดเตรียมองค์ประกอบภาพต่างๆ หรือ"วิดเจ็ต"ซึ่งปรับปรุงกระบวนการออกแบบอินเทอร์เฟซผู้ใช้แบบกราฟิก (GUI)

ไลบรารี Pillow ซึ่งเป็นอนุพันธ์ของ Python Imaging Library (PIL) ที่ได้รับการยอมรับอย่างดี นำเสนอฟีเจอร์การจัดการรูปภาพที่หลากหลาย ซึ่งอำนวยความสะดวกให้กับงานต่างๆ เช่น การแก้ไข การสร้าง และการบันทึกไฟล์สื่อภาพประเภทต่างๆ

ในการติดตั้ง Tkinter และ Pillow สามารถเริ่มต้นได้โดยการเปิดอินเทอร์เฟซบรรทัดคำสั่งและดำเนินการคำสั่งต่อไปนี้:

 pip install tk pillow 

การตั้งค่า GUI และการจัดการรูปภาพ

อาจค้นหาซอร์สโค้ดสำหรับโปรเจ็กต์นี้ภายในพื้นที่เก็บข้อมูล GitHub เฉพาะ ซึ่งทำหน้าที่เป็นพื้นที่เก็บข้อมูลดิจิทัลของไฟล์และเอกสารทั้งหมดที่เกี่ยวข้อง

ในการเริ่มต้น จำเป็นต้องนำเข้าโมดูลที่จำเป็น ต่อจากนั้น เราจะสร้างคลาสใหม่ที่เรียกว่า ImageCollageApp ซึ่งจะทำหน้าที่เป็นออบเจ็กต์แอปพลิเคชันหลัก ขั้นตอนแรกเกี่ยวข้องกับการตั้งชื่อและขนาดของหน้าต่าง จากนั้นเราจะสร้างแคนวาสโดยใช้เมธอด tk.Canvas() และกำหนดค่าองค์ประกอบหลัก ความกว้าง ความสูง และสีพื้นหลัง

 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()

ตรวจสอบให้แน่ใจว่าผู้ใช้ได้ให้สิทธิ์ในการป้อนข้อมูลไฟล์ก่อนที่จะสร้างออบเจ็กต์ FileReader เพื่ออ่านไฟล์ภาพจากอุปกรณ์ของตน

เริ่มต้นโครงสร้างข้อมูลที่เรียกว่า"image\_positions"สำหรับจัดเก็บตำแหน่งที่มองเห็นได้ขององค์ประกอบสื่อภายในอินเทอร์เฟซผู้ใช้แบบกราฟิก ใช้ขั้นตอนการจัดการเหตุการณ์สามขั้นตอนที่แยกจากกันเพื่อจัดการกับการเลือก การย้าย และการยกเลิกการดำเนินการที่เกี่ยวข้องกับองค์ประกอบสื่อดังกล่าว

         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) 

เพื่อที่จะใช้ฟังก์ชันการทำงานที่อธิบายไว้ในโค้ดที่ให้มา เราต้องกำหนดวิธีการที่เรียกว่า"on\_press"ก่อน วิธีการนี้จะเกิดขึ้นเมื่อผู้ใช้คลิกเมาส์ขณะวาดภาพบนผืนผ้าใบ เป้าหมายของวิธีนี้คือการดึงออบเจ็กต์ Canvas ที่ใกล้ที่สุดไปยังจุดที่ผู้ใช้คลิกเมาส์และจัดเก็บไว้ในพจนานุกรม"drag\_data"นอกจากนี้ เราจะจัดเก็บพิกัด X และ Y ของการคลิกเมาส์ เพื่อที่เราจะได้คำนวณในภายหลังว่าผู้ใช้ขยับเมาส์ไปไกลแค่ไหนในระหว่างการลาก

     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 

เพื่อที่จะใช้ฟังก์ชันการทำงานที่อธิบายไว้ในโค้ดที่ให้มา จำเป็นต้องกำหนดวิธีการที่เรียกว่า"on\_drag"ซึ่งจะเริ่มทำงานเมื่อผู้ใช้เลื่อนเมาส์ขณะที่กดปุ่มซ้ายค้างไว้ วิธีนี้จะคำนวณระยะทางแนวนอนและแนวตั้งที่เคอร์เซอร์เคลื่อนที่ระหว่างการลากโดยใช้ตัวแปร"dx"และ"dy"ตามค่าเหล่านี้ ตำแหน่งของรูปภาพสามารถอัปเดตได้โดยการแก้ไขแอตทริบิวต์"x"และ"y"ของออบเจ็กต์"รูปภาพ"ภายในวิดเจ็ต"self.canvas"นอกจากนี้ พิกัดใหม่สำหรับรูปภาพควรเก็บไว้ในพจนานุกรม “drag\_data” ที่เชื่อมโยงกับอินสแตนซ์ปัจจุบันของคลาส ซึ่งช่วยให้สามารถคงอยู่ในหลายเฟรมได้

     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 

เพื่อล้างการอ้างอิงที่ค้างอยู่ไปยังรูปภาพที่ลากไปก่อนหน้านี้ และคำนวณตำแหน่งขององค์ประกอบภาพทั้งหมดบนผืนผ้าใบใหม่เพื่อตอบสนองต่อเหตุการณ์การเปิดตัว คุณสามารถใช้วิธี"on\_release"ที่จัดการกับข้อกังวลเหล่านี้ โดยเฉพาะอย่างยิ่ง วิธีการนี้ควรล้างการอ้างอิงถึงรูปภาพที่มีเคอร์เซอร์ของผู้ใช้มาด้วยในระหว่างการลาก ในขณะเดียวกันก็เรียกใช้ฟังก์ชัน"อัปเดต\_รูปภาพ\_ตำแหน่ง"เพื่อแก้ไขเค้าโครงของรูปภาพที่แสดงทั้งหมดภายหลังจาก การยุติการโต้ตอบของผู้ใช้

     def on_release(self, event):
        self.drag_data["item"] = None
        self.drag_data["x"] = 0
        self.drag_data["y"] = 0
        self.update_image_positions() 

ในลักษณะที่หรูหรา เราจะอธิบายฟังก์ชันที่มีชื่อว่า “update\_image\_positions” ซึ่งเกี่ยวข้องกับการเปิดเผยเนื้อหาของอาร์เรย์ “image\_positions” และวนซ้ำทุกองค์ประกอบของผืนผ้าใบ ในระหว่างกระบวนการนี้ สำหรับแต่ละส่วนประกอบ เราจะระบุข้อมูลตำแหน่งและผนวกเข้ากับอาร์เรย์ดังกล่าว

     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)) 

แน่นอน! นี่คือตัวอย่างการใช้งานใน Python โดยใช้ Tkinter และ Pillow Library:pythonimport tkinter as tkfrom tkinter import filedialogimport osfrom PIL import Imagedef add_images():# create a new windowwindow=tk.Toplevel(root)# ถามผู้ใช้ว่าต้องการกี่ภาพ uploadnum_images=tk.Entry(window)num_images.pack()num_entries=tk.Label(window, text=“ป้อนจำนวนภาพ:")num_entries.pack()# รับค่าจากรายการ fieldnum_values ​​=num_images.get()if num_values.isdigit() และ int(

ใช้ฟังก์ชัน resize\_image เพื่อปรับขนาดภาพปัจจุบันในหน่วยความจำ สร้าง PhotoImage ที่เข้ากันได้กับ Tkinter ใหม่ จากนั้น ให้เพิ่มการอ้างอิงที่อัปเดตนี้ต่อท้ายรายการ image\_refs ก่อนที่จะอัปเดตแคนวาสด้วยเมธอด 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() 

นี่คือตัวอย่างการใช้งานเมธอด resize\_image ใน Python:pythondef resize_image(self, image):# รับขนาดปัจจุบันของ imageimg_width, img_height=image.size# คำนวณอัตราส่วนภาพของ imageaspect_ratio=img_height/img_width# ตรวจสอบ หากอัตราส่วนกว้างยาวมากกว่า 1 (เช่น การวางแนวแนวตั้ง) หากอัตราส่วนภาพ > 1:# ตั้งค่าความกว้างใหม่ให้เป็นครึ่งหนึ่งของ widthnew_width=self.collage_width/2# คำนวณความสูงใหม่ที่สอดคล้องกันในขณะที่ยังคงรักษาอัตราส่วนกว้างยาว new_height=int ((

หากอัตราส่วนภาพของภาพต่อกันน้อยกว่าหนึ่ง เราจะลดทั้งความสูงและความกว้างลงครึ่งหนึ่งโดยการคำนวณขนาดที่เหมาะสมตามขนาดดั้งเดิมของภาพต่อกัน จากนั้นเราสามารถใช้ฟังก์ชัน ปรับขนาด ของ Pillow เพื่อสร้างภาพตัดปะที่ขยายใหญ่ขึ้นด้วยการวัดที่ปรับเหล่านี้โดยยังคงรักษาสัดส่วนไว้

     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)) 

กำหนดวิธีการชื่อ “update\_canvas” ด้วยขั้นตอนต่อไปนี้:1. ล้างรายการทั้งหมดบนผืนผ้าใบโดยลบลิงก์ที่คลิกได้ซึ่งเชื่อมโยงกับแต่ละรายการออกจากการจัดเรียงรูปภาพก่อนหน้านี้2. นำเสนอโอกาสให้ผู้ใช้ป้อนจำนวนแถวและคอลัมน์ที่ต้องการผ่านกล่องโต้ตอบไฟล์ ขนาดที่ให้ไว้ควรสอดคล้องกับข้อกำหนดที่ระบุก่อนหน้าในเอกสารนี้3. กำหนดจำนวนคอลัมน์ทั้งหมดที่ต้องการตามจำนวนแถวที่ผู้ใช้ป้อน ในตัวอย่างของเรา เราจะสมมติว่ามีหกคอลัมน์ต่อแถว คำนวณความกว้างและความสูงของภาพตัดปะตามลำดับ ซึ่งหมายความว่าหากผู้ใช้เลือกสี่แถว ความกว้างจะเป็นสองเท่าของความกว้างของหนึ่งคอลัมน์ (6) บวกด้วยระยะขอบของช่องว่างระหว่างแถวเหล่านั้น เพราะเหตุนี้

     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 

วนซ้ำแต่ละรายการในรายการ image\_refs สร้างการแสดงภาพบนผืนผ้าใบโดยใช้ออฟเซ็ตที่ให้มา วางตำแหน่งมุมซ้ายบนของรูปภาพตามพิกัดที่กำหนดโดยกำหนดจุดยึดไปที่มุมตะวันตกเฉียงเหนือ นอกจากนี้ ให้เพิ่มพิกัดที่เกี่ยวข้องต่อท้ายรายการ image\_positions เพื่อใช้อ้างอิงเพิ่มเติม

เพื่อที่จะจัดเรียงรูปภาพถัดไปภายในตารางได้อย่างมีประสิทธิภาพ จำเป็นต้องอัปเดตตัวแปร x\_offset โดยการเพิ่มครึ่งหนึ่งของภาพตัดปะ

         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 

การสร้างภาพต่อกันและการบันทึก

เพื่อสร้างการแสดงภาพสินทรัพย์ดิจิทัลต่างๆ ที่น่าดึงดูดใจ เราจะพัฒนาฟังก์ชันที่เรียกว่า create\_collage อัลกอริธึมนี้จะตรวจสอบก่อนว่ามีรายการสื่อใดรวมอยู่ในการเรียบเรียงหรือไม่ หากไม่มีก็จะแสดงข้อความเตือน จากนั้นเทคนิคนี้จะกำหนดขนาดของภาพตัดต่ออิเล็กทรอนิกส์โดยพิจารณาจากความกว้างและความสูง ถัดไป มันจะสร้างออบเจ็กต์ Pillow Image ที่ว่างเปล่าใหม่ซึ่งมีฉากหลังสีขาวบริสุทธิ์ จากนั้น ฟังก์ชันจะวนซ้ำแค็ตตาล็อกของไฟล์และวางไว้อย่างแม่นยำบนผืนผ้าใบตามพิกัดที่กำหนดไว้ล่วงหน้า โดยใช้ไลบรารี PIL อันทรงพลังของ Python เพื่อการจัดการข้อมูลรูปภาพอย่างมีประสิทธิภาพ

ใช้โปรแกรมดูรูปภาพที่กำหนดไว้ล่วงหน้าเพื่อแสดงภาพตัดปะดิจิทัลโดยการบันทึกไว้ก่อน โดยใช้ประโยชน์จากความสามารถในตัวเพื่อการแสดงภาพที่ดีที่สุด

     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() 

ใช้ความสามารถของไลบรารี Tkinter โดยสร้างอินสแตนซ์ใหม่ของแอปพลิเคชัน ImageCollage ซึ่งมาพร้อมกับคุณลักษณะและวิธีการที่จำเป็นในการสร้างภาพต่อกันตามการป้อนข้อมูลของผู้ใช้ เมื่อสร้างเสร็จแล้ว ให้เริ่มต้นการดำเนินการของลูปเหตุการณ์ Tkinter โดยใช้วิธีการ mainloop() คำสั่งนี้สั่งให้ล่าม Python ตรวจสอบและประมวลผลเหตุการณ์ใด ๆ ที่เกิดขึ้นภายในหน้าต่างอย่างต่อเนื่อง โดยคงสถานะไว้อย่างมีประสิทธิภาพจนกว่าผู้ใช้ปลายทางจะปิดด้วยตนเอง

 if __name__ == "__main__":
    root = tk.Tk()
    app = ImageCollageApp(root)
    root.mainloop() 

การทดสอบคุณสมบัติต่างๆ ของ Image Collage Maker

เมื่อรันแอปพลิเคชัน อินเทอร์เฟซที่มีสองตัวเลือกจะปรากฏขึ้น-“เพิ่มรูปภาพ"และ"สร้างภาพต่อกัน"เมื่อคลิกที่ตัวเลือก"เพิ่มรูปภาพ"ป๊อปอัปเพื่อสอบถามข้อมูลผู้ใช้สำหรับจำนวนรูปภาพทั้งหมดที่ต้องการรวมไว้ในภาพตัดปะจะปรากฏขึ้น เมื่อป้อน'5’เป็นจำนวนรูปภาพที่ต้องการ และเลือกจากรายการที่กำหนด กล่องโต้ตอบเพิ่มเติมจะปรากฏขึ้นเพื่อขอข้อมูลเกี่ยวกับจำนวนแถวแนวนอนและคอลัมน์แนวตั้งที่ควรใช้ในการสร้างภาพต่อกัน

/th/images/start-screen-of-image-collage-application.jpg

เมื่อแทรกองค์ประกอบภาพสองแถวและสามคอลัมน์ภายในพื้นที่ขอบเขตที่กำหนด อินเทอร์เฟซผู้ใช้แบบกราฟิกจะจัดเรียงองค์ประกอบเหล่านั้นอย่างเป็นระบบเป็นการกำหนดค่าอาร์เรย์หรือเมทริกซ์ สร้างจอแสดงผลที่สอดคล้องกันซึ่งเน้นตำแหน่งและลำดับของแต่ละองค์ประกอบ

/th/images/image-collage-default-preview-for-5-images-in-2-rows-3-columns.jpg

การแสดงตัวอย่างช่วยให้สามารถจัดการรูปภาพได้โดยการเปลี่ยนตำแหน่งใหม่ตามความต้องการ เมื่อคลิกที่ปุ่ม"สร้างภาพต่อกัน"ซอฟต์แวร์จะบันทึกภาพที่ได้

/th/images/dragging-images-to-desired-positions-within-canvas.jpg

เมื่อตรวจสอบการแสดงภาพของภาพตัดปะที่สร้างขึ้น จะเห็นได้ชัดว่าแอปพลิเคชันซอฟต์แวร์บรรลุวัตถุประสงค์ตามที่ตั้งใจไว้ในส่วนที่เกี่ยวกับการรวบรวมคอลเลกชันรูปภาพที่เหนียวแน่นและดึงดูดสายตา

/th/images/desired-collage-image.jpg

ปรับปรุงฟังก์ชันการทำงานของ Image Collage Maker

แทนที่จะใช้โครงสร้างแบบตาราง คุณสามารถเสนอตัวเลือกเทมเพลตที่กำหนดไว้ล่วงหน้าให้กับผู้ใช้ได้ นอกจากนี้ ยังรวมฟังก์ชันที่ช่วยให้สามารถเปลี่ยนเฉดสีพื้นหลัง เขียนเนื้อหา ปรับใช้การปรับปรุงรูปภาพ และบูรณาการองค์ประกอบตกแต่งที่ได้มาจากแหล่งข้อมูลออนไลน์

ในขณะที่รวมฟังก์ชันเหล่านี้ไว้ ให้เปิดใช้งานวิธีการที่ตรงไปตรงมาในการแก้ไขภาพคอมโพสิตโดยให้ตัวเลือกสำหรับการยกเลิกหรือการวาดใหม่ นอกจากนี้ อนุญาตให้ผู้ใช้ปรับการครอบตัด การปรับขนาด และการวางแนวของแต่ละภาพได้ตามความต้องการ นอกจากนี้ ยังมีคุณลักษณะที่ช่วยให้สามารถบันทึกเอาต์พุตสุดท้ายในรูปแบบไฟล์ที่เลือกได้