File size: 4,057 Bytes
aedbeed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import gradio as gr
import pandas as pd
import subprocess
import os
from tempfile import mkdtemp
from timeit import default_timer as timer

# Download model and libraries from repo
try:
    token = os.environ.get("model_token")
    subprocess.run(["git", "clone", f"https://oauth2:{token}@huggingface.co/vincentlui/bridge_hand_detect"])
except:
    print('Fail to download code')

try:
    from bridge_hand_detect2.predict import CardDetectionModel, draw_bboxes
    from bridge_hand_detect2.pbn import create_pbn_file
    model_dir = 'bridge_hand_detect2/model.onnx'
except:
    from bridge_hand_detect.predict import CardDetectionModel, draw_bboxes
    from bridge_hand_detect.pbn import create_pbn_file
    model_dir = 'bridge_hand_detect/model.onnx'

custom_css = \
"""
/* Hide sort buttons at gr.DataFrame */
.sort-button {
    display: none !important;
}
"""

INPUT_IMG_HEIGHT = 480
OUTPUT_IMG_HEIGHT = 320 
css = ".output_img {display:block; margin-left: auto; margin-right: auto}"
model = CardDetectionModel(model_dir)

def predict(image_path):
    start = timer()
    df = None
    try:
        hands, (width,height) = model(image_path)
        print(hands)
        # Output dataframe
        df = pd.DataFrame(['♠', '♥', '♦', '♣'], columns=[''])
        for hand in hands:
            df[hand.direction] = [''.join(c) for c in hand.cards]
    except:
        gr.Error('Cannot process image')

    end = timer()
    print(f'Process time: {end - start:.02f} seconds')
    
    return df
    

default_df = df = pd.DataFrame({'':['♠', '♥', '♦', '♣'], 
                                'N': ['']*4, 
                                'E': ['']*4, 
                                'S': ['']*4, 
                                'W': ['']*4})


def save_file2(df, cache_dir, total):
    d = cache_dir
    if cache_dir is None:
        d = mkdtemp()
    total += 1
    file_name = f'bridgehand{total:03d}.pbn'
    file_path = os.path.join(d,file_name)
    with open(file_path, 'w') as f:
        pbn_str = create_pbn_file(df)
        f.write(pbn_str)

    return file_path, d, total

with gr.Blocks(css=custom_css) as demo:
    gr.Markdown(
        """
        # Bridge Hand Scanner - Read all four hands from an image

        This app scans an image taken from (e.g. your smartphone) and reads all 52 cards. The top hand is regarded as North.
        The results can be exported as a PBN file, which can be imported to other bridge software such as double dummy solvers.
        1. Upload an image showing all four hands fanned as shown in the example.
        2. Click *Submit*. The scan result will be displayed in the table.
        3. Verify the output and correct any missing or wrong card in the table. Then click *Save* to generate a PBN file.

        Tips:
        - This AI reads the values at the top left corner of the playing cards. Make sure they are visible and as large as possible.
        - To get the best accuracy, place the cards following the layout in the examples. 

        I need your feedback to make this app more useful. Please send your comments to <vincentlui123@gmail.com>.
        """)

    total = gr.State(0)
    gradio_cache_dir = gr.State()
    
    with gr.Row():
        with gr.Column():
            a1 = gr.Image(type="filepath",sources=['upload'],interactive=True,height=INPUT_IMG_HEIGHT)
            with gr.Row():
                a2 = gr.ClearButton()
                a3 = gr.Button('Submit',variant="primary")
            a4 = gr.Examples('examples', a1)

        with gr.Column():
            b1 = gr.Dataframe(value=default_df, datatype="str", row_count=(4,'fixed'), col_count=(5,'fixed'), 
                            headers=['', 'N', 'E', 'S', 'W'],
                            interactive=True, column_widths=['8%', '23%','23%','23%','23%'])
            b2 = gr.Button('Save')
            b3 = gr.File(interactive=False)

    a2.add([a1, b1, b3])
    a3.click(predict, [a1], [b1])
    b2.click(save_file2, [b1, gradio_cache_dir, total], [b3, gradio_cache_dir, total])

demo.queue().launch()