SSEONG commited on
Commit
6fae35d
ยท
verified ยท
1 Parent(s): 66d399c

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +151 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,153 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
1
+ # app.py
 
 
2
  import streamlit as st
3
+ import cv2
4
+ import numpy as np
5
+ from PIL import Image
6
+ import easyocr
7
+ from streamlit_paste_button import paste_image_button as pbutton
8
+
9
+ color_ranges = {
10
+ 'fire': 'B50B0E',
11
+ 'water': '015AB6',
12
+ 'wind': '1F6A0B',
13
+ 'earth': '623F23',
14
+ 'light': 'DA8D09',
15
+ 'dark': '502181'
16
+ }
17
+
18
+ def hex_to_rgb(hex_code):
19
+ return tuple(int(hex_code[i:i+2], 16) for i in (0, 2, 4))
20
+
21
+ # ์บ์‹ฑ์œผ๋กœ Reader๋ฅผ ํ•œ ๋ฒˆ๋งŒ ๋กœ๋“œ
22
+ @st.cache_resource
23
+ def load_reader():
24
+ return easyocr.Reader(['en'], gpu=False, verbose=False)
25
+
26
+ def extract_number(region, reader):
27
+ try:
28
+ gray = cv2.cvtColor(region, cv2.COLOR_BGR2GRAY)
29
+ resized = cv2.resize(gray, None, fx=6, fy=6, interpolation=cv2.INTER_CUBIC)
30
+ results = reader.readtext(resized, allowlist='0123456789', paragraph=False)
31
+
32
+ if results:
33
+ text = results[0][1]
34
+ return int(text.strip())
35
+ except Exception as e:
36
+ st.error(f"์ˆซ์ž ์ถ”์ถœ ์˜ค๋ฅ˜: {e}")
37
+ return 0
38
+
39
+ def find_items(img_array, color_range, reader):
40
+ img_rgb = cv2.cvtColor(img_array, cv2.COLOR_BGR2RGB)
41
+ results = {}
42
+
43
+ for type, hex_color in color_range.items():
44
+ target_rgb = hex_to_rgb(hex_color)
45
+ lower_c = np.array([max(0, c - 10) for c in target_rgb])
46
+ upper_c = np.array([min(255, c + 10) for c in target_rgb])
47
+
48
+ mask = cv2.inRange(img_rgb, lower_c, upper_c)
49
+ contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
50
+
51
+ if contours:
52
+ largest = max(contours, key=cv2.contourArea)
53
+ if cv2.contourArea(largest) > 100:
54
+ x, y, w, h = cv2.boundingRect(largest)
55
+ number_region = img_rgb[y+h:y+int(h*2), x+w:x+int(w*2.3)]
56
+ count = extract_number(number_region, reader)
57
+ results[type] = count
58
+ else:
59
+ results[type] = 0
60
+ else:
61
+ results[type] = 0
62
+
63
+ return results
64
+
65
+
66
+ def process_image(img):
67
+ st.image(cv2.cvtColor(img, cv2.COLOR_BGR2RGB), caption='์—…๋กœ๋“œ๋œ ์ด๋ฏธ์ง€', use_container_width=True)
68
+
69
+ with st.spinner('์•„์ดํ…œ ๊ฐœ์ˆ˜๋ฅผ ์„ธ๋Š” ์ค‘... (์ฒ˜์Œ ์‹คํ–‰์‹œ ๋ชจ๋ธ ๋กœ๋”ฉ์œผ๋กœ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค)'):
70
+ try:
71
+ reader = load_reader()
72
+ results = find_items(img, color_ranges, reader)
73
+
74
+ # ๊ฒฐ๊ณผ ํ‘œ์‹œ
75
+ st.success('โœ… ๋ถ„์„ ์™„๋ฃŒ!')
76
+
77
+ col1, col2, col3 = st.columns(3)
78
+
79
+ emoji_map = {
80
+ 'fire': '๐Ÿ”ฅ',
81
+ 'water': '๐Ÿ’ง',
82
+ 'wind': '๐Ÿ’จ',
83
+ 'earth': '๐ŸŒ',
84
+ 'light': 'โœจ',
85
+ 'dark': '๐ŸŒ™'
86
+ }
87
+
88
+ korean_map = {
89
+ 'fire': '๋ถˆ',
90
+ 'water': '๋ฌผ',
91
+ 'wind': '๋ฐ”๋žŒ',
92
+ 'earth': '๋Œ€์ง€',
93
+ 'light': '๋น›',
94
+ 'dark': '์–ด๋‘ '
95
+ }
96
+
97
+ # ๋‹จ์ผ ์—ด๋กœ ํ‘œ์‹œ
98
+ for type, count in results.items():
99
+ st.metric(
100
+ label=f"{emoji_map.get(type, '')} {korean_map.get(type, type)}",
101
+ value=f"{count}๊ฐœ"
102
+ )
103
+
104
+ # cols = [col1, col2, col3]
105
+ # counts_str = ''
106
+ # for idx, (type, count) in enumerate(results.items()):
107
+ # col = cols[idx % 3]
108
+ # with col:
109
+ # st.metric(
110
+ # label=f"{emoji_map.get(type, '')} {korean_map.get(type, type)}",
111
+ # value=f"{count}๊ฐœ"
112
+ # )
113
+ counts_str += f"{count}/"
114
+ st.markdown(f'{counts_str}')
115
+ except Exception as e:
116
+ st.error(f"๋ถ„์„ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}")
117
+ st.info("EasyOCR ๋ชจ๋ธ ๋กœ๋”ฉ์— ์‹คํŒจํ–ˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Streamlit Cloud์˜ ๋ฉ”๋ชจ๋ฆฌ ์ œํ•œ ๋•Œ๋ฌธ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.")
118
+
119
+
120
+ # Streamlit UI
121
+ st.set_page_config(page_title="๊ฒŒ์ž„ ์•„์ดํ…œ ์นด์šดํ„ฐ", page_icon="๐ŸŽฎ")
122
+
123
+ st.title('๐ŸŽฎ ๊ฒŒ์ž„ ์•„์ดํ…œ ์นด์šดํ„ฐ')
124
+ st.write('ํš๋“ํ•œ ์†์„ฑ ์•„์ดํ…œ ๊ฐœ์ˆ˜๋ฅผ ์ž๋™์œผ๋กœ ์„ธ์–ด๋“œ๋ฆฝ๋‹ˆ๋‹ค!')
125
+
126
+ tab1, tab2 = st.tabs(["๐Ÿ“ ํŒŒ์ผ ์—…๋กœ๋“œ", "๐Ÿ“‹ ๋ถ™์—ฌ๋„ฃ๊ธฐ"])
127
+
128
+ with tab1:
129
+ st.write('์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•˜์„ธ์š”')
130
+ uploaded_file = st.file_uploader("์Šคํฌ๋ฆฐ์ƒท์„ ์—…๋กœ๋“œํ•˜์„ธ์š”", type=['png', 'jpg', 'jpeg'])
131
+
132
+ if uploaded_file is not None:
133
+ file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8)
134
+ img = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
135
+ process_image(img)
136
+
137
+ with tab2:
138
+ st.write('์ด๋ฏธ์ง€๋ฅผ ๋ถ™์—ฌ๋„ฃ์œผ์„ธ์š”')
139
+ paste_result = pbutton(
140
+ label="๐Ÿ“‹ ์—ฌ๊ธฐ๋ฅผ ํด๋ฆญํ•˜๊ณ  Ctrl+V",
141
+ background_color="#FF4B4B",
142
+ hover_background_color="#FF6B6B",
143
+ )
144
+
145
+ if paste_result.image_data is not None:
146
+ pil_image = paste_result.image_data
147
+ # st.markdown(f'{type(pil_image)}')
148
+ img = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
149
+ process_image(img)
150
+
151
 
152
+ st.markdown('---')
153
+ st.caption('Made by โค๏ธsseong')