kai-sheng commited on
Commit
a426d06
·
verified ·
1 Parent(s): c9ec3e2

first upload image caption generator

Browse files
Files changed (3) hide show
  1. Dockerfile +11 -0
  2. main.py +93 -0
  3. requirements.txt +6 -0
Dockerfile ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9
2
+
3
+ WORKDIR /code
4
+
5
+ COPY ./requirements.txt /code/requirements.txt
6
+
7
+ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
8
+
9
+ COPY . .
10
+
11
+ CMD ["uvicorn", "-b", "0.0.0.0:7860", "main:app", "--host"]
main.py ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import io
3
+ from flask import Flask, request, jsonify
4
+ import base64
5
+ import numpy as np
6
+ from pickle import load
7
+ from PIL import Image
8
+ from keras.applications.xception import Xception #to get pre-trained model Xception
9
+ from keras.models import load_model
10
+ from keras.preprocessing.sequence import pad_sequences
11
+
12
+ os.environ["TF_ENABLE_ONEDNN_OPTS"] = "0"
13
+
14
+ app = Flask(__name__)
15
+
16
+ # MAX_LENGTH = 34
17
+ MAX_LENGTH = 38
18
+
19
+ def extract_features(image_data, model):
20
+ try:
21
+ image = Image.open(io.BytesIO(image_data))
22
+ except Exception as e:
23
+ print("ERROR: Can't open image! Ensure that image data is correct and in the expected format")
24
+ print(str(e))
25
+ return None
26
+
27
+ image = image.resize((299,299))
28
+ image = np.array(image)
29
+
30
+ # for 4 channels images, we need to convert them into 3 channels
31
+ if image.shape[2] == 4:
32
+ image = image[..., :3]
33
+
34
+ image = np.expand_dims(image, axis=0)
35
+ image = image/127.5
36
+ image = image - 1.0
37
+ feature = model.predict(image)
38
+
39
+ return feature
40
+
41
+
42
+ def word_for_id(integer, tokenizer):
43
+ for word, index in tokenizer.word_index.items():
44
+ if index == integer:
45
+ return word
46
+ return None
47
+
48
+
49
+ def generate_desc(model, tokenizer, photo, max_length):
50
+ in_text = 'start'
51
+ for i in range(max_length):
52
+ sequence = tokenizer.texts_to_sequences([in_text])[0]
53
+ sequence = pad_sequences([sequence], maxlen=max_length)
54
+ pred = model.predict([photo,sequence], verbose=0)
55
+ pred = np.argmax(pred)
56
+ word = word_for_id(pred, tokenizer)
57
+ if word is None or word == 'end':
58
+ break
59
+ in_text += ' ' + word
60
+ return in_text.replace('start ', '')
61
+
62
+
63
+ # API endpoint to receive image and generate caption
64
+ @app.route('/api', methods=['POST'])
65
+ def generate_caption():
66
+ try:
67
+ base64_image_data = request.form['image']
68
+ # return jsonify({'caption': base64_image_data}), 200
69
+ # Replace spaces with "+" characters to handle cases where "+" characters are missing
70
+ # base64_image_data = base64_image_data.replace(" ", "+")
71
+
72
+ # Decode the Base64 string into binary image data
73
+ image_data = base64.b64decode(base64_image_data)
74
+
75
+ tokenizer = load(open("tokenizer.p","rb"))
76
+ # model = load_model('model_9.h5')
77
+ model = load_model('models/model_9.keras')
78
+
79
+ xception_model = Xception(include_top=False, pooling="avg")
80
+ photo = extract_features(image_data, xception_model)
81
+
82
+ if photo is None:
83
+ return jsonify({'error': 'Failed to extract features from the image'}), 400
84
+
85
+ caption = generate_desc(model, tokenizer, photo, MAX_LENGTH)
86
+
87
+ # Return the generated caption
88
+ return jsonify({'caption': caption}), 200
89
+ except Exception as e:
90
+ return jsonify({'error': str(e)}), 500
91
+
92
+ if __name__ == '__main__':
93
+ app.run(host='0.0.0.0')
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ uvicorn
2
+ Flask==2.2.5
3
+ Pillow==9.4.0
4
+ numpy==1.25.2
5
+ keras==3.0
6
+ tensorflow==2.16.1