NeerajNotfound commited on
Commit
e47c691
·
verified ·
1 Parent(s): a8f37ad

Upload 88 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +3 -0
  2. .streamlit/config.toml +3 -0
  3. DEPLOY.md +48 -0
  4. README.md +100 -19
  5. app.py +161 -0
  6. models/easyocr/craft_mlt_25k.pth +3 -0
  7. models/easyocr/english_g2.pth +3 -0
  8. outputs/MyHandwriting.ttf +0 -0
  9. outputs/SentenceFont.ttf +0 -0
  10. outputs/debug/char_a_7_1.png +0 -0
  11. outputs/debug/char_b_2_0.png +0 -0
  12. outputs/debug/char_c_1_3.png +0 -0
  13. outputs/debug/char_d_8_0.png +0 -0
  14. outputs/debug/char_e_0_2.png +0 -0
  15. outputs/debug/char_e_5_2.png +0 -0
  16. outputs/debug/char_e_6_2.png +0 -0
  17. outputs/debug/char_f_3_0.png +0 -0
  18. outputs/debug/char_g_8_2.png +0 -0
  19. outputs/debug/char_h_0_1.png +0 -0
  20. outputs/debug/char_h_6_1.png +0 -0
  21. outputs/debug/char_i_1_2.png +0 -0
  22. outputs/debug/char_j_4_0.png +0 -0
  23. outputs/debug/char_k_1_4.png +0 -0
  24. outputs/debug/char_l_7_0.png +0 -0
  25. outputs/debug/char_m_4_2.png +0 -0
  26. outputs/debug/char_n_2_4.png +0 -0
  27. outputs/debug/char_o_2_2.png +0 -0
  28. outputs/debug/char_o_3_1.png +0 -0
  29. outputs/debug/char_o_5_0.png +0 -0
  30. outputs/debug/char_o_8_1.png +0 -0
  31. outputs/debug/char_p_4_3.png +0 -0
  32. outputs/debug/char_q_1_0.png +0 -0
  33. outputs/debug/char_r_2_1.png +0 -0
  34. outputs/debug/char_r_5_3.png +0 -0
  35. outputs/debug/char_s_4_4.png +0 -0
  36. outputs/debug/char_t_0_0.png +0 -0
  37. outputs/debug/char_t_6_0.png +0 -0
  38. outputs/debug/char_u_1_1.png +0 -0
  39. outputs/debug/char_u_4_1.png +0 -0
  40. outputs/debug/char_v_5_1.png +0 -0
  41. outputs/debug/char_w_2_3.png +0 -0
  42. outputs/debug/char_x_3_2.png +0 -0
  43. outputs/debug/char_y_7_4.png +0 -0
  44. outputs/debug/char_z_7_3.png +0 -0
  45. outputs/debug/word_0.png +0 -0
  46. outputs/debug/word_1.png +0 -0
  47. outputs/debug/word_2.png +0 -0
  48. outputs/debug/word_3.png +0 -0
  49. outputs/debug/word_4.png +0 -0
  50. outputs/debug/word_5.png +0 -0
.gitattributes CHANGED
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ outputs/proper_input_template.jpg filter=lfs diff=lfs merge=lfs -text
37
+ temp_grid.jpg filter=lfs diff=lfs merge=lfs -text
38
+ ui/logo.png filter=lfs diff=lfs merge=lfs -text
.streamlit/config.toml ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ [server]
2
+ fileWatcherType = "none"
3
+ headless = true
DEPLOY.md ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # How to Deploy Type.ai to Hugging Face Spaces
2
+
3
+ This guide will help you deploy your handwriting font generator for free on Hugging Face Spaces.
4
+
5
+ ## Prerequisites
6
+ - A [Hugging Face Account](https://huggingface.co/join) (Free)
7
+
8
+ ## Step-by-Step Deployment
9
+
10
+ ### 1. Create a New Space
11
+ 1. Go to [huggingface.co/spaces](https://huggingface.co/spaces).
12
+ 2. Click **"Create new Space"**.
13
+ 3. **Space Name**: Enter `type-ai` (or similar).
14
+ 4. **License**: `MIT` (optional).
15
+ 5. **SDK**: Select **Streamlit**.
16
+ 6. **Hardware**: Keep the default **CPU Basic (Free)**.
17
+ > *Note: This builds slowly but works. If it fails, you can request a restart.*
18
+ > *For faster font generation, T4 GPU (small cost) is better, but CPU works for free.*
19
+ 7. Click **"Create Space"**.
20
+
21
+ ### 2. Upload Your Code
22
+ You will see a page with instructions. We will upload files via the web interface (easiest method).
23
+
24
+ 1. On your Space page, click the **"Files"** tab.
25
+ 2. Click **"Add file"** > **"Upload files"**.
26
+ 3. Drag and drop **ALL** the files from your `Type.ai` folder into the upload area.
27
+ - **Crucial Files**:
28
+ - `app.py`
29
+ - `requirements.txt` (I just updated this for you)
30
+ - `packages.txt` (I just created this for you - installs Tesseract)
31
+ - `src/` folder (drag the whole folder)
32
+ - `models/` folder (if you have local models, otherwise the code downloads them)
33
+ - `ui/` folder
34
+ 4. In the "Commit message" box, type "Initial deploy".
35
+ 5. Click **"Commit changes to main"**.
36
+
37
+ ### 3. Watch it Build
38
+ 1. Click the **"App"** tab.
39
+ 2. You will see "Building".
40
+ 3. Hugging Face will automatically:
41
+ - Install Python libraries from `requirements.txt`.
42
+ - Install Tesseract OCR from `packages.txt`.
43
+ 4. This process may take **5-10 minutes** the first time.
44
+
45
+ ### Troubleshooting
46
+ - **"Runtime Error"**: Check the **"Logs"** tab.
47
+ - **Tesseract not found**: Ensure `packages.txt` exists in the root directory.
48
+ - **Memory Error**: The free tier has 16GB RAM, which is usually enough. If it crashes loading the model, we can optimize the code to load lighter models.
README.md CHANGED
@@ -1,19 +1,100 @@
1
- ---
2
- title: TypeAI
3
- emoji: 🚀
4
- colorFrom: red
5
- colorTo: red
6
- sdk: docker
7
- app_port: 8501
8
- tags:
9
- - streamlit
10
- pinned: false
11
- short_description: Streamlit template space
12
- ---
13
-
14
- # Welcome to Streamlit!
15
-
16
- Edit `/src/streamlit_app.py` to customize this app to your heart's desire. :heart:
17
-
18
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
19
- forums](https://discuss.streamlit.io).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Type AI
3
+ emoji: ✒️
4
+ colorFrom: blue
5
+ colorTo: purple
6
+ sdk: streamlit
7
+ sdk_version: 1.25.0
8
+ python_version: "3.10"
9
+ app_file: app.py
10
+ pinned: false
11
+ ---
12
+
13
+ # Type.ai - AI Handwriting to Font Generator
14
+
15
+ Convert your handwriting into a custom TrueType font file using AI-powered character detection.
16
+
17
+ ## Features
18
+
19
+ - **AI Character Detection**: Uses advanced contour analysis and OCR to extract characters
20
+ - **Style Analysis**: Captures stroke width, slant, and roughness of your handwriting
21
+ - **Vector Conversion**: Converts bitmap characters to smooth vector paths
22
+ - **Font Generation**: Creates installable TTF font files
23
+ - **Web UI**: Modern drag-and-drop interface
24
+ - **REST API**: Integrate into your own applications
25
+
26
+ ## Quick Start
27
+
28
+ ### 1. Install Dependencies
29
+
30
+ ```bash
31
+ cd Type.ai
32
+ pip install -r requirements.txt
33
+ ```
34
+
35
+ ### 2. Command Line Usage
36
+
37
+ ```bash
38
+ # Basic usage
39
+ python main.py handwriting.jpg --output MyFont.ttf --name "MyHandwriting"
40
+
41
+ # With debug output
42
+ python main.py sample.png -o CustomFont.ttf -n "Custom Font" --debug
43
+ ```
44
+
45
+ ### 3. Web Interface
46
+
47
+ ```bash
48
+ # Start the server
49
+ python server.py
50
+
51
+ # Open in browser
52
+ # http://localhost:8000/ui/
53
+ ```
54
+
55
+ ## Tips for Best Results
56
+
57
+ 1. **Write clearly** with consistent size
58
+ 2. **Include all letters** A-Z (uppercase and/or lowercase)
59
+ 3. **Use dark ink** on white paper
60
+ 4. **Good lighting** - avoid shadows
61
+ 5. **High resolution** scan or photo
62
+
63
+ ## Project Structure
64
+
65
+ ```
66
+ Type.ai/
67
+ ├── src/
68
+ │ ├── preprocessing.py # Image enhancement
69
+ │ ├── segmentation.py # Character detection
70
+ │ ├── style_extractor.py # Style analysis
71
+ │ ├── vectorizer.py # Bitmap to vector
72
+ │ ├── font_generator.py # TTF creation
73
+ │ └── pipeline.py # Main orchestrator
74
+ ├── ui/
75
+ │ └── index.html # Web interface
76
+ ├── main.py # CLI
77
+ ├── server.py # FastAPI server
78
+ └── requirements.txt # Dependencies
79
+ ```
80
+
81
+ ## API Endpoints
82
+
83
+ | Endpoint | Method | Description |
84
+ |----------|--------|-------------|
85
+ | `/api/upload` | POST | Upload handwriting image |
86
+ | `/api/status/{job_id}` | GET | Check processing status |
87
+ | `/api/download/{job_id}` | GET | Download generated font |
88
+ | `/api/preview/{job_id}` | GET | Get segmentation preview |
89
+
90
+ ## Requirements
91
+
92
+ - Python 3.8+
93
+ - PyTorch 1.9+
94
+ - OpenCV
95
+ - fonttools
96
+ - Tesseract OCR (optional, for character recognition)
97
+
98
+ ## License
99
+
100
+ MIT
app.py ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Type.ai - Web Interface
3
+ -----------------------
4
+ A clean UI to generate handwriting fonts.
5
+ Now supports Phase 1 (Grid) and Phase 2 (Sentence).
6
+ """
7
+ import streamlit as st
8
+ import os
9
+ import cv2
10
+ import numpy as np
11
+ import sys
12
+ from pathlib import Path
13
+
14
+ # Fix imports
15
+ sys.path.insert(0, str(Path(__file__).parent / 'src'))
16
+ from process_grid import process_grid_final
17
+ from process_sentence import process_sentence
18
+
19
+ def main():
20
+ # Use logo as favicon/page icon
21
+ logo_path = "ui/logo.png"
22
+ st.set_page_config(
23
+ page_title="Type.ai",
24
+ page_icon=logo_path if os.path.exists(logo_path) else "✒️",
25
+ layout="centered"
26
+ )
27
+
28
+ # --- LOGO & HEADER ---
29
+ logo_path = "ui/logo.png"
30
+ if os.path.exists(logo_path):
31
+ st.image(logo_path, width=200)
32
+ else:
33
+ st.title("✒️ Type.ai")
34
+
35
+ st.header("Turn your handwriting into a font.")
36
+
37
+ tab1, tab2 = st.tabs(["📏 Grid Mode (Standard)", "📝 Sentence Mode (Experimental)"])
38
+
39
+ # --- TAB 1: GRID MODE ---
40
+ with tab1:
41
+ st.subheader("Method 1: The Precision Grid")
42
+ st.markdown("Use this for 100% accuracy using the template.")
43
+
44
+ col1, col2 = st.columns([1, 2])
45
+ template_path = "outputs/proper_input_template.jpg"
46
+
47
+ # Ensure template exists
48
+ if not os.path.exists(template_path):
49
+ st.warning("Template not found. Please run cleanup or generate it.")
50
+
51
+ with col1:
52
+ if os.path.exists(template_path):
53
+ st.image(template_path, caption="Grid Template", width=150)
54
+
55
+ with col2:
56
+ st.write("1. Download blank template.\n2. Fill with **Blue Pen**.\n3. Upload.")
57
+ if os.path.exists(template_path):
58
+ with open(template_path, "rb") as f:
59
+ st.download_button(
60
+ label="📥 Download Blank Template",
61
+ data=f,
62
+ file_name="TypeAI_Template.jpg",
63
+ mime="image/jpeg"
64
+ )
65
+
66
+ uploaded_grid = st.file_uploader("Upload Grid Scan", type=["jpg", "png", "jpeg"], key="grid_up")
67
+
68
+ if uploaded_grid is not None:
69
+ st.image(uploaded_grid, caption="Grid Upload", width=300)
70
+
71
+ font_name = st.text_input("Name your font:", value="MyHandwriting", key="grid_font_name")
72
+
73
+ if st.button("✨ Generate Grid Font"):
74
+ with st.spinner("Processing Grid..."):
75
+ try:
76
+ temp_path = "temp_grid.jpg"
77
+ with open(temp_path, "wb") as f:
78
+ f.write(uploaded_grid.getbuffer())
79
+
80
+ # Clean filename
81
+ safe_name = "".join(x for x in font_name if x.isalnum() or x in " -_")
82
+ if not safe_name: safe_name = "MyHandwriting"
83
+
84
+ output_filename = f"{safe_name.replace(' ', '_')}.ttf"
85
+ output_path = os.path.join("outputs", output_filename)
86
+
87
+ process_grid_final(temp_path, output_path, font_family_name=font_name)
88
+
89
+ st.success(f"Font '{font_name}' Generated!")
90
+
91
+ with open(output_path, "rb") as f:
92
+ st.download_button(f"Download {output_filename}", f, output_filename)
93
+ except Exception as e:
94
+ st.error(f"Error: {e}")
95
+
96
+ # --- TAB 2: SENTENCE MODE ---
97
+ with tab2:
98
+ st.subheader("Method 2: Natural Sentence (Phase 2)")
99
+ st.markdown("Upload a photo of any handwritten sentence to detect letters automatically.")
100
+
101
+ st.info("ℹ️ **First Run Note:** This mode uses AI models (TrOCR) which will download on the first run. Please be patient.")
102
+
103
+ try:
104
+ import torch
105
+ if torch.cuda.is_available():
106
+ gpu_name = torch.cuda.get_device_name(0)
107
+ st.success(f"🚀 Acceleration Enabled: Using {gpu_name}")
108
+ else:
109
+ st.warning("⚠️ No GPU Detected. Running on CPU (this might be slow).")
110
+ except ImportError:
111
+ pass
112
+
113
+ uploaded_sent = st.file_uploader("Upload Sentence Image", type=["jpg", "png", "jpeg"], key="sent_up")
114
+
115
+ if uploaded_sent is not None:
116
+ st.image(uploaded_sent, caption="Sentence Upload", width=300)
117
+ if st.button("🧠 Analyze & Generate"):
118
+ with st.spinner("Analyzing handwriting (Segmentation + OCR)..."):
119
+ try:
120
+ temp_path = "temp_sentence.jpg"
121
+ with open(temp_path, "wb") as f:
122
+ f.write(uploaded_sent.getbuffer())
123
+
124
+ output_path = "outputs/SentenceFont.ttf"
125
+ result = process_sentence(temp_path, output_path)
126
+
127
+ if result and result[0] and os.path.exists(result[0]):
128
+ font_path, text_content = result
129
+ st.success("Sentence Font Generated!")
130
+
131
+ # Generate Preview
132
+ if text_content:
133
+ st.subheader("Preview: Your Text in Your Font")
134
+ from font_renderer import render_font_preview
135
+ preview_path = "outputs/preview.png"
136
+ render_font_preview(font_path, text_content, preview_path)
137
+ if os.path.exists(preview_path):
138
+ st.image(preview_path, caption="Generated Preview", use_container_width=True)
139
+ else:
140
+ st.warning("Could not generate preview image.")
141
+ else:
142
+ st.warning("Font generated, but no text content reconstructed for preview.")
143
+
144
+ st.balloons()
145
+ with open(output_path, "rb") as f:
146
+ st.download_button("Download SentenceFont.ttf", f, "SentenceFont.ttf")
147
+
148
+ # Debug View
149
+ if os.path.exists("outputs/debug_alphabet.png"):
150
+ with st.expander("👁️ Debug: what the AI saw"):
151
+ st.image("outputs/debug_alphabet.png", caption="Detected Characters")
152
+ else:
153
+ st.warning("No font generated. Maybe no characters were confidently detected?")
154
+
155
+ except Exception as e:
156
+ st.error(f"Error: {e}")
157
+ import traceback
158
+ st.text(traceback.format_exc()) # Debug info
159
+
160
+ if __name__ == "__main__":
161
+ main()
models/easyocr/craft_mlt_25k.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4a5efbfb48b4081100544e75e1e2b57f8de3d84f213004b14b85fd4b3748db17
3
+ size 83152330
models/easyocr/english_g2.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e2272681d9d67a04e2dff396b6e95077bc19001f8f6d3593c307b9852e1c29e8
3
+ size 15143997
outputs/MyHandwriting.ttf ADDED
Binary file (5.3 kB). View file
 
outputs/SentenceFont.ttf ADDED
Binary file (4.83 kB). View file
 
outputs/debug/char_a_7_1.png ADDED
outputs/debug/char_b_2_0.png ADDED
outputs/debug/char_c_1_3.png ADDED
outputs/debug/char_d_8_0.png ADDED
outputs/debug/char_e_0_2.png ADDED
outputs/debug/char_e_5_2.png ADDED
outputs/debug/char_e_6_2.png ADDED
outputs/debug/char_f_3_0.png ADDED
outputs/debug/char_g_8_2.png ADDED
outputs/debug/char_h_0_1.png ADDED
outputs/debug/char_h_6_1.png ADDED
outputs/debug/char_i_1_2.png ADDED
outputs/debug/char_j_4_0.png ADDED
outputs/debug/char_k_1_4.png ADDED
outputs/debug/char_l_7_0.png ADDED
outputs/debug/char_m_4_2.png ADDED
outputs/debug/char_n_2_4.png ADDED
outputs/debug/char_o_2_2.png ADDED
outputs/debug/char_o_3_1.png ADDED
outputs/debug/char_o_5_0.png ADDED
outputs/debug/char_o_8_1.png ADDED
outputs/debug/char_p_4_3.png ADDED
outputs/debug/char_q_1_0.png ADDED
outputs/debug/char_r_2_1.png ADDED
outputs/debug/char_r_5_3.png ADDED
outputs/debug/char_s_4_4.png ADDED
outputs/debug/char_t_0_0.png ADDED
outputs/debug/char_t_6_0.png ADDED
outputs/debug/char_u_1_1.png ADDED
outputs/debug/char_u_4_1.png ADDED
outputs/debug/char_v_5_1.png ADDED
outputs/debug/char_w_2_3.png ADDED
outputs/debug/char_x_3_2.png ADDED
outputs/debug/char_y_7_4.png ADDED
outputs/debug/char_z_7_3.png ADDED
outputs/debug/word_0.png ADDED
outputs/debug/word_1.png ADDED
outputs/debug/word_2.png ADDED
outputs/debug/word_3.png ADDED
outputs/debug/word_4.png ADDED
outputs/debug/word_5.png ADDED