Skip to content

Commit

Permalink
feat(server): add utility server implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
AmitMY committed Jul 2, 2024
1 parent b19d415 commit 6f17a4e
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 3 deletions.
46 changes: 43 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ signwriting_to_image(fsw)

![AS10011S10019S2e704S2e748M525x535S2e748483x510S10011501x466S20544510x500S10019476x475](signwriting/visualizer/test_assets/AS10011S10019S2e704S2e748M525x535S2e748483x510S10011501x466S20544510x500S10019476x475.png)

To use the visualizer with the server, you can hit:
https://sign.mt/api/signwriting/visualizer?fsw=M525x535S2e748483x510S10011501x466S2e704510x500S10019476x475

### `signwriting.utils`

This module includes general utilities that were not covered in the other modules.
Expand All @@ -95,14 +98,51 @@ This module includes general utilities that were not covered in the other module
This is useful for example for fingerspelling words out of individual character signs.

```python
from signwriting.utils.join_signs import join_signs
from signwriting.utils.join_signs import join_signs_vertical

char_a = 'M507x507S1f720487x492'
char_b = 'M507x507S14720493x485'
result_sign = join_signs(char_a, char_b)
# M500x500S1f720487x493S14720493x508
result_sign = join_signs_vertical(char_a, char_b)
# M510x518S1f720490x481S14720496x496
```


### `signwriting.fingerspelling`

This module is used to generate spelling data from a list of characters.

```python
from signwriting.fingerspelling.fingerspelling import spell

word = "Hello" # any string of characters
language = "en-us-ase-asl" # long language code, as defined in the fingerspelling README
spell(word, language)
# M515x563S11502477x437S14a20492x457S1dc20484x477S1dc20484x512S17620492x547
```

To use the fingerspelling with the server, you can hit:
https://sign.mt/api/signwriting/fingerspelling?text=hello&signed_language=ase

### `signwriting.mouthing`

This module is used to generate SpeechWriting from spoken words.

```python
from signwriting.mouthing.mouthing import mouth

word = "Hello" # any string of characters, preferably valid words
language = "eng-Latn" # supported languages under "Language Support" at https://pypi.org/project/epitran/
mouth(word, language)
# M557x518S34700443x482S35c00469x482S34400495x482S34d00521x482
```

Note: Installing English support for `epitran` requires extra steps,
see "Install flite" at [mouthing/README.md](signwriting/mouthing/README.md).

To use the mouthing with the server, you can hit:
https://sign.mt/api/signwriting/mouthing?text=hello&spoken_language=eng-Latn


## Cite

```bibtex
Expand Down
10 changes: 10 additions & 0 deletions examples/spell_and_mouth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from signwriting.fingerspelling.fingerspelling import spell
from signwriting.mouthing.mouthing import mouth
from signwriting.utils.join_signs import join_signs_vertical

text = "Hello SignWriting List"
for word in text.split(" "):
mouthing = mouth(word, language="eng-Latn")
spelling = spell(word, language="en-us-ase-asl", vertical=False)
sign = join_signs_vertical(mouthing, spelling, spacing=5)
print(sign)
19 changes: 19 additions & 0 deletions signwriting/fingerspelling/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from flask_restful import Resource, reqparse

from signwriting.fingerspelling.fingerspelling import spell, get_chars_by

parser = reqparse.RequestParser()
parser.add_argument('text', type=str, required=True, help='Text to fingerspell')
parser.add_argument('signed_language', type=str, required=True, help='Signed language ISO-3 code')


class Fingerspelling(Resource):
def get(self):
args = parser.parse_args()

try:
chars = get_chars_by(value=args["signed_language"], category="SIGNED")
except ValueError as e:
return {"message": str(e)}, 400

return {"fsw": spell(args["text"], chars=chars)}
15 changes: 15 additions & 0 deletions signwriting/mouthing/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from flask_restful import Resource, reqparse

from signwriting.mouthing.mouthing import mouth

parser = reqparse.RequestParser()
parser.add_argument('text', type=str, required=True, help='Text to mouth')
parser.add_argument('spoken_language', type=str, required=True,
help='Spoken Language code. See "Language Support" at https://pypi.org/project/epitran/')


class Mouthing(Resource):
def get(self):
args = parser.parse_args()

return {"fsw": mouth(args["text"], language=args["spoken_language"])}
16 changes: 16 additions & 0 deletions signwriting/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from flask import Flask
from flask_restful import Api

from signwriting.fingerspelling.server import Fingerspelling
from signwriting.mouthing.server import Mouthing
from signwriting.visualizer.server import Visualizer

app = Flask(__name__)
api = Api(app)

api.add_resource(Visualizer, '/visualizer')
api.add_resource(Fingerspelling, '/fingerspelling')
api.add_resource(Mouthing, '/mouthing')

if __name__ == "__main__":
app.run()
45 changes: 45 additions & 0 deletions signwriting/visualizer/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from io import BytesIO

from flask import send_file
from flask_restful import Resource, reqparse

from signwriting.formats.swu_to_fsw import swu2fsw
from signwriting.visualizer.visualize import RGBA, signwriting_to_image


def hex_color_to_rgba(hex_color: str) -> RGBA:
r = int(hex_color[0:2], 16)
g = int(hex_color[2:4], 16)
b = int(hex_color[4:6], 16)
a = int(hex_color[6:8], 16) if len(hex_color) > 6 else 255
return r, g, b, a


def send_pil_image(pil_img):
img_io = BytesIO()
pil_img.save(img_io, 'PNG')
img_io.seek(0)
return send_file(img_io, mimetype='image/png')


parser = reqparse.RequestParser()
parser.add_argument('fsw', type=str, required=False, help='FSW String (Must be provided if swu is not provided)')
parser.add_argument('swu', type=str, required=False, help='SWU String (Must be provided if fsw is not provided)')
parser.add_argument('line', type=str, default='000000ff', help='Line color in hex format')
parser.add_argument('fill', type=str, default='ffffffff', help='Fill color in hex format')


class Visualizer(Resource):
def get(self):
args = parser.parse_args()
fsw = args.get("fsw")
swu = args.get("swu")
if fsw is None and swu is None:
return {"message": "No fsw or swu provided"}, 400

line_color = hex_color_to_rgba(args["line"])
fill_color = hex_color_to_rgba(args["fill"])

sw_string = fsw if fsw is not None else swu2fsw(swu)
image = signwriting_to_image(fsw=sw_string, line_color=line_color, fill_color=fill_color)
return send_pil_image(image)
1 change: 1 addition & 0 deletions signwriting/visualizer/visualize.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def get_font(font_name: str) -> ImageFont.FreeTypeFont:
return ImageFont.truetype(str(font_path), 30)


@lru_cache(maxsize=None)
def get_symbol_size(symbol: str):
font = get_font('SuttonSignWritingLine')
line_id = symbol_line(key2id(symbol))
Expand Down

0 comments on commit 6f17a4e

Please sign in to comment.