yrarchi / household_accounts

レシートのデータ化
19 stars 8 forks source link

OCRで読み取った内容の修正を簡単に行えるようにしたい #6

Closed yrarchi closed 4 years ago

yrarchi commented 4 years ago

https://github.com/yrarchi/household_accounts/issues/4, https://github.com/yrarchi/household_accounts/issues/5 で行ったOCRにより、レシートから文字を取り出すことができたものの、精度としてはさほど高くない。 精度を上げる模索と並行して、以下のような要件で確認・修正を簡単に行えるようにしたい。

yrarchi commented 4 years ago

デスクトップアプリ

修正と確認はローカルで行えればよいので、PythonでGUIで操作できる仕組みを作るにはどうすればよいか調べた。 以下のようなライブラリを利用すると、実現できるようだった

今回は、標準ライブラリであるtkinterを利用してみることにした。

yrarchi commented 4 years ago

tkinter

Pythonのマニュアル(https://docs.python.org/ja/3/library/tkinter.html )に示されている以下のリンク先を主に参考にした

基本的な考え

基本的には以下の2工程で作成できると理解した

配置については複数の方法があるが、以下のやり方が理解しやすそうだと考えた

色々触って概要を理解する

import tkinter as tk

root = tk.Tk()
root.title('読み取り内容修正')
root.geometry("600x400")

receipt_img_frame = tk.Frame(root, bg="gray", width=200, height=400)
receipt_img_frame.grid(row=0, column=0, rowspan=2, sticky=(tk.N, tk.S))

receipt_info_frame = tk.Frame(root, bg="white", width=400, height=150)
receipt_info_frame.grid(row=0, column=1)

item_frame = tk.Frame(root, bg="black", width=400, height=250)
item_frame.grid(row=1, column=1)

root.mainloop()

rowspan=2, sticky=(tk.N, tk.S) rowspanは何行に渡って配置するかで、stickyは配置と引き伸ばし(NとSで指定すると南北方向に引きのばすことになる)

yrarchi commented 4 years ago

ページ遷移

tkinterでボタンを押したらページ遷移するようにしたい(別ウィンドウを開くのでなく、ウィンドウは一つにしたい)

以下の考えでできた

以下、2パターン(各々もっとスマートな書き方あるかもしれない)

一つのファイル内で全てのページのコードがある場合

import tkinter as tk

class MakePages(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("Tkinter change page")
        self.geometry("200x100")
        self.make_pages()
        self.change_page(self.page1)

    def make_pages(self):
        self.page1 = tk.Frame()
        self.page1.grid(row=0, column=0, sticky="nsew")
        self.page2 = tk.Frame()
        self.page2.grid(row=0, column=0, sticky="nsew")

    def change_page(self, page):
        page.tkraise()

class MakePage1():
    def __init__(self, page1, page2):
        self.page1 = page1
        self.page2 = page2
        self.put_item_page1()

    def put_item_page1(self):
        self.titleLabel = tk.Label(self.page1, text="Page 1")
        self.titleLabel.grid(row=0, column=0)

        self.change_pageButton = tk.Button(self.page1, text="Go to page2", command=lambda : MakePages.change_page("_", self.page2))
        self.change_pageButton.grid(row=1, column=0)

class MakePage2():
    def __init__(self, page1, page2):
        self.page1 = page1
        self.page2 = page2
        self.put_item_page2()

    def put_item_page2(self):
        self.titleLabel = tk.Label(self.page2, text="Frame 2")
        self.titleLabel.grid(row=0, column=0)

        self.back_button = tk.Button(self.page2, text="Back", command=lambda : MakePages.change_page("_", self.page1))
        self.back_button.grid(row=1, column=0)

def main():
    app = MakePages()
    page1 = MakePage1(app.page1, app.page2)
    page2 = MakePage2(app.page1, app.page2)
    app.mainloop()

if __name__ == "__main__":
    main()

それぞれのページを別ファイルに分ける場合(今回、こっちにした方が明確になりそう)

main.py 実行用のファイル

from div_file_origin import MakePages
from div_file_page1 import MakePage1 
from div_file_page2 import MakePage2

app = MakePages()
MakePage1(app.page1, app.page2)
MakePage2(app.page1, app.page2)
app.mainloop()

div_file_origin.py 2つのページを作る

import tkinter as tk

class MakePages(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Tkinter change page")
        self.geometry("200x100")
        self.make_pages()
        change_page(self.page1)

    def make_pages(self):
        self.page1 = tk.Frame()
        self.page1.grid(row=0, column=0, sticky="nsew")
        self.page2 = tk.Frame()
        self.page2.grid(row=0, column=0, sticky="nsew")

def change_page(page):
    page.tkraise()

div_file_page1.py 1ページ目の内容

import tkinter as tk
from div_file_origin import change_page

class MakePage1():
    def __init__(self, page1, page2):
        self.page1 = page1
        self.page2 = page2
        self.put_item_page1()

    def put_item_page1(self):
        self.titleLabel = tk.Label(self.page1, text="Page 1")
        self.titleLabel.grid(row=0, column=0)

        self.change_pageButton = tk.Button(self.page1, text="Go to page2", command=lambda : change_page(self.page2))
        self.change_pageButton.grid(row=1, column=0)

div_file_page2.py 2ページ目の内容

import tkinter as tk
from div_file_origin import change_page

class MakePage2():
    def __init__(self, page1, page2):
        self.page1 = page1
        self.page2 = page2
        self.put_item_page2()

    def put_item_page2(self):
        self.titleLabel = tk.Label(self.page2, text="Frame 2")
        self.titleLabel.grid(row=0, column=0)

        self.back_button = tk.Button(self.page2, text="Back", command=lambda : change_page(self.page1))
        self.back_button.grid(row=1, column=0)