GUI image cropping tool made with Python + Tkinter

"I want a GUI trimming tool that runs on Python!"

When dealing with images in Python, there are many people who want to crop with GUI operations.

I searched for a reference article on the net, but this is quite good! I couldn't meet anything like that, so I'll leave it here.

Introduction

Tkinter is a kit that allows you to easily create GUI tools in Python. I usually use Jupyter Notebook and I used ipywidgets when I needed GUI operation, but this is not enough and I used Tkinter this time.

GUI tool to cut out a rectangle from an image

I will cut out a part of the image and save it in Python. I didn't just want to do this trimming part I wanted to do a process like [image processing → trimming → image processing]. The motivation for this time was that I wanted to do it consistently with Python.

Code and commentary

code

crop.py


from tkinter import *
from PIL import Image
import os
os.chdir("c:\\users\\username")

#----------------------------------------------------------------------


def filenameMaker(num):
    return "%03d.png " % num


class MainWindow():

    #----------------

    def __init__(self, main):
        #Make a canvas to display the image
        self.canvas = Canvas(main, width=200, height=200)
        self.canvas.grid(row=0, column=0, columnspan=2, rowspan=4)

        #image(000.png to 004.5 pieces of png)To capture
        self.my_images = []
        self.file_num = 0
        for i in range(0, 5):
            self.my_images.append(PhotoImage(file=filenameMaker(i)))
        self.my_image_number = 0

        #Secure a number for storage
        self.save_file_num = 0

        #Set the first image
        self.image_on_canvas = self.canvas.create_image(
            0, 0, anchor=NW, image=self.my_images[self.my_image_number])

        #Make various buttons
        #Button to display the next image
        self.button_next = Button(
            main, text="Next", command=self.onNextButton, width=20, height=5)
        self.button_next.grid(row=2, column=4, columnspan=2, rowspan=2)
        #Button to display the previous image
        self.button_back = Button(
            main, text="Back", command=self.onBackButton, width=20)
        self.button_back.grid(row=4, column=4, columnspan=2)
        #Button to save selection
        self.button_save = Button(
            main, text="Save", command=self.onSaveButton, width=25, height=5)
        self.button_save.grid(row=2, column=6, columnspan=3, rowspan=2)
        #Button to return one save number
        self.button_saveb = Button(
            main, text="Save Back", command=self.onSavebButton, width=25)
        self.button_saveb.grid(row=4, column=6, columnspan=3)

        #Make an Entry to display a message
        #Entry to display the current image number
        self.message_num = Entry(width=50)
        self.message_num.insert(
            END, ("This image is " + filenameMaker(self.my_image_number)))
        self.message_num.grid(row=6, column=4, columnspan=5)
        #Entry to display the next save number
        self.message = Entry(width=50)
        self.message.insert(END, ("Next save-name is " +
                                  "save-" + filenameMaker(self.save_file_num)))
        self.message.grid(row=7, column=4, columnspan=5)

        #Reserve variables for sliders
        self.left = 0
        self.right = 0
        self.top = 0
        self.bottom = 0

        #Draw a line for image cropping on the canvas
        self.canvas.create_line(self.left, 0, self.left,
                                200, tag="left_line", fill='green')
        self.canvas.create_line(self.right, 0, self.right,
                                200, tag="right_line", fill='red')
        self.canvas.create_line(
            0, self.top, 200, self.top, tag="top_line", fill='green')
        self.canvas.create_line(0, self.bottom, 200,
                                self.bottom, tag="bottom_line", fill='red')

        #Make a slider for image cropping
        self.left = Scale(main, label='left', orient='h',
                          from_=0, to=200, length=200, command=self.onSliderLeft)
        self.left.grid(row=4, column=0, columnspan=2, rowspan=2)

        self.right = Scale(main, label='right', orient='h',
                           from_=0, to=200, length=200, command=self.onSliderRight)
        self.right.grid(row=6, column=0, columnspan=2, rowspan=2)

        self.top = Scale(main, label='top', orient='v',
                         from_=0, to=200, length=200, command=self.onSliderTop)
        self.top.grid(row=4, column=2, rowspan=4)

        self.bottom = Scale(main, label='bottom', orient='v',
                            from_=0, to=200, length=200, command=self.onSliderBottom)
        self.bottom.grid(row=4, column=3, rowspan=4)

        #Move the line for cropping the image according to the displayed image
        self.left.set(0)
        self.right.set(self.my_images[self.my_image_number].width())
        self.top.set(0)
        self.bottom.set(self.my_images[self.my_image_number].height())

    #----------------

    def onBackButton(self):
        #Return to last image
        if self.my_image_number == 0:
            self.my_image_number = len(self.my_images) - 1
        else:
            #Go back one
            self.my_image_number -= 1

        #Update display image
        self.canvas.itemconfig(self.image_on_canvas,
                               image=self.my_images[self.my_image_number])

        #Updated the position of the line for cutting out the image according to the displayed image
        self.left.set(0)
        self.right.set(self.my_images[self.my_image_number].width())
        self.top.set(0)
        self.bottom.set(self.my_images[self.my_image_number].height())


        #Update the contents of Entry
        self.message_num.delete(0, END)
        self.message_num.insert(
            END, ("This image is " + filenameMaker(self.my_image_number)))

    def onNextButton(self):
        #Go one step forward
        self.my_image_number += 1

        #Return to first image
        if self.my_image_number == len(self.my_images):
            self.my_image_number = 0

        #Update display image
        self.canvas.itemconfig(self.image_on_canvas,
                               image=self.my_images[self.my_image_number])

        #Updated the position of the line for cutting out the image according to the displayed image
        self.left.set(0)
        self.right.set(self.my_images[self.my_image_number].width())
        self.top.set(0)
        self.bottom.set(self.my_images[self.my_image_number].height())

        #Update the contents of Entry
        self.message_num.delete(0, END)
        self.message_num.insert(
            END, ("This image is " + filenameMaker(self.my_image_number)))

    def onSaveButton(self):
        #Capture the display image
        self.temp_image = Image.open(filenameMaker(self.my_image_number))
        #Cut out at the selected position
        self.cropped_image = self.temp_image.crop(
            (self.left.get(), self.top.get(), self.right.get(), self.bottom.get()))
        #Save
        self.cropped_image.save("save-" + filenameMaker(self.save_file_num))

        self.save_file_num += 1

        #Update the contents of Entry
        self.message.delete(0, END)
        self.message.insert(END, ("Next save-name is " +
                                  "save-" + filenameMaker(self.save_file_num)))

    def onSavebButton(self):
        self.save_file_num -= 1

        if self.save_file_num == -1:
            self.save_file_num = 0

        #Update the contents of Entry
        self.message.delete(0, END)
        self.message.insert(END, ("Next save-name is " +
                                  "save-" + filenameMaker(self.save_file_num)))

    def onSliderLeft(self, args):
        # change line
        self.canvas.delete("left_line")
        self.canvas.create_line(
            self.left.get(), 0, self.left.get(), 200, tag="left_line", fill='green')

    def onSliderRight(self, args):
        # change line
        self.canvas.delete("right_line")
        self.canvas.create_line(
            self.right.get(), 0, self.right.get(), 200, tag="right_line", fill='red')

    def onSliderTop(self, args):
        # change line
        self.canvas.delete("top_line")
        self.canvas.create_line(0, self.top.get(), 200,
                                self.top.get(), tag="top_line", fill='green')

    def onSliderBottom(self, args):
        # change line
        self.canvas.delete("bottom_line")
        self.canvas.create_line(0, self.bottom.get(), 200,
                                self.bottom.get(), tag="bottom_line", fill='red')


#----------------------------------------------------------------------

root = Tk()
MainWindow(root)
root.mainloop()

Commentary

The execution screen is shown below. The operation content is to select the cutout position with each slider Display the next image with the Next button Display the previous image with the Back button Save the cutout range with the Save button Save back one image number with the Save Back button 図1.png

Each widget is created with def __init __ (self, main): to define the display position. .grid is used to define the display position. When loading an image, I use PhotoImage, and when I save it withdef onSaveButton (self):, I use PIL's ʻImage, which seems to be awkward. I couldn't do it, and I couldn't read it properly with ʻImage.

↓ Saved image. save-000.png

Referenced site

--Try using Python's Tkinter --Qiita http://qiita.com/nnahito/items/ad1428a30738b3d93762

--Introduction to Easy Python / Tkinter http://www.geocities.jp/m_hiroi/light/pytk01.html

Recommended Posts

GUI image cropping tool made with Python + Tkinter
[Python] Python and security-② Port scanning tool made with Python
I made a GUI application with Python + PyQt5
[Python] I made a Youtube Downloader with Tkinter.
Image processing with Python
Simple sales tool creation with Python GUI: Quote creation
Image processing with Python (Part 2)
Programming with Python and Tkinter
Image editing with python OpenCV
I made blackjack with python!
Sorting image files with Python (2)
Sorting image files with Python (3)
Create Image Viewer with Tkinter
Image processing with Python (Part 1)
[GUI with Python] PyQt5-Layout management-
Tweet with image in Python
Sorting image files with Python
Image processing with Python (Part 3)
Run Label with tkinter [Python]
I made blackjack with Python.
[GUI with Python] PyQt5 -Preparation-
Othello made with python (GUI-like)
I made wordcloud with Python.
[Python] Image processing with scikit-image
[GUI with Python] PyQt5 -Paint-
I made a simple typing game with tkinter in Python
Solution when the image cannot be displayed with tkinter [python]
Simple sales tool creation with Python GUI: Employee number search
[I made it with Python] XML data batch output tool
Creating a GUI as easily as possible with python [tkinter edition]
I made a puzzle game (like) with Tkinter in Python
Simple sales tool creation with Python GUI: Cost rate calculation
I tried to make GUI tic-tac-toe with Python and Tkinter
Simple sales tool creation with Python GUI: Desktop application released
Cut out an image with python
SNS Python basics made with Flask
[Python] Using OpenCV with Python (Image Filtering)
Create a python GUI using tkinter
Let's make a GUI with python.
Numer0n with items made in Python
I made a fortune with Python.
[GUI with Python] PyQt5-The first step-
Image processing with Python 100 knocks # 3 Binarization
Easy GUI app with Tkinter Text
[GUI with Python] PyQt5-Drag and drop-
Othello game development made with Python
Let's do image scraping with Python
Find image similarity with Python + OpenCV
Image processing with Python 100 knocks # 2 Grayscale
[GUI with Python] PyQt5 -Custom Widget-
I made a daemon with Python
[Python] Creating multiple windows with Tkinter
Send image with python, save with php
Gradation image generation with Python [1] | np.linspace
GUI creation in python using tkinter 2
Life game with Python [I made it] (on the terminal & Tkinter)
Difference in behavior of transparent Frame made with tkinter in pyinstaller [Python]
[Python] I made an image viewer with a simple sorting function.
Play video with sound with python !! (tkinter / imageio)
Basics of binarized image processing with Python
Image processing with Python 100 knock # 10 median filter