From 764227574d5d0fcc7e045464a344f3d546d490e6 Mon Sep 17 00:00:00 2001 From: Toby Cm Date: Sun, 12 May 2024 12:47:24 -0700 Subject: [PATCH 1/3] refactor: :recycle: Fix sql injection, restructure project files, clean database and refactor code --- README.md | 171 +++++++++--------- engine/Dockerfile | 2 +- engine/api/database.sqlite | Bin 16384 -> 16384 bytes engine/api/main.py | 11 +- engine/api/routers/engine.py | 252 +++++++++++++++------------ engine/api/utils.py | 8 + engine/{api => model}/model.p | Bin engine/train/create_dataset.py | 29 ++- engine/train/inference_classifier.py | 82 ++++----- engine/train/model.p | Bin 79420 -> 0 bytes engine/train/train_classifier.py | 21 ++- example/Python/nomodel.py | 57 +++--- mypy.ini | 4 + 13 files changed, 346 insertions(+), 291 deletions(-) create mode 100644 engine/api/utils.py rename engine/{api => model}/model.p (100%) delete mode 100644 engine/train/model.p create mode 100644 mypy.ini diff --git a/README.md b/README.md index efe3d37..c166b30 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ +--- +runme: + id: 01HXQ4NN4MHTJTRY3Q2ZWHP2A7 + version: v3 +--- + # Atlantis engine ![1715102710368](example/docs/image/Atlantis.png) @@ -43,8 +49,9 @@ Giao diện chương trình là gì? Giao diện chương trình – Application #### Dưới đây là hướng dẫn train model cơ bản -```python -# collect_imgs.py +```python {"id":"01HXQ4NN4K1WC0X7KXQHW3331T"} +# engine/train/collect_imgs.py + import os import cv2 DATA_DIR = './data' @@ -74,16 +81,17 @@ for j in range(number_of_classes): counter += 1 cap.release() cv2.destroyAllWindows() + ``` -```python -#create_dataset.py +```python {"id":"01HXQ4NN4K1WC0X7KXQJAGAZM4"} +# engine/train/create_dataset.py + import os import pickle -import mediapipe as mp import cv2 -import matplotlib.pyplot as plt +import mediapipe as mp mp_hands = mp.solutions.hands mp_drawing = mp.solutions.drawing_utils @@ -98,8 +106,9 @@ labels = [] for dir_ in os.listdir(DATA_DIR): for img_path in os.listdir(os.path.join(DATA_DIR, dir_)): data_aux = [] - x_ = [] - y_ = [] + + xs = [] + ys = [] img = cv2.imread(os.path.join(DATA_DIR, dir_, img_path)) img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) @@ -107,65 +116,71 @@ for dir_ in os.listdir(DATA_DIR): results = hands.process(img_rgb) if results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: - for i in range(len(hand_landmarks.landmark)): - x = hand_landmarks.landmark[i].x - y = hand_landmarks.landmark[i].y - - x_.append(x) - y_.append(y) + for _ in range(len(hand_landmarks.landmark)): + xs.append(hand_landmarks.landmark[0].x) + ys.append(hand_landmarks.landmark[0].y) - for i in range(len(hand_landmarks.landmark)): - x = hand_landmarks.landmark[i].x - y = hand_landmarks.landmark[i].y - data_aux.append(x - min(x_)) - data_aux.append(y - min(y_)) + for _ in range(len(hand_landmarks.landmark)): + data_aux.append(hand_landmarks.landmark[0].x - min(xs)) + data_aux.append(hand_landmarks.landmark[0].y - min(ys)) data.append(data_aux) labels.append(dir_) -f = open('data.pickle', 'wb') -pickle.dump({'data': data, 'labels': labels}, f) -f.close() +with open('data.pickle', 'wb') as f: + pickle.dump({'data': data, 'labels': labels}, f) + ``` -```python -#train_classifier.py +```python {"id":"01HXQ4NN4K1WC0X7KXQNK2D04E"} +# engine/train/train_classifier.py + import pickle +from os import remove +import numpy as np from sklearn.ensemble import RandomForestClassifier -from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score -import numpy as np -from os import remove +from sklearn.model_selection import train_test_split + data_dict = pickle.load(open('./data.pickle', 'rb')) + data = np.asarray(data_dict['data']) labels = np.asarray(data_dict['labels']) -x_train, x_test, y_train, y_test = train_test_split(data, labels, test_size=0.2, shuffle=True, stratify=labels, random_state=42) + +x_train, x_test, y_train, y_test = train_test_split(data, + labels, + test_size=0.2, + shuffle=True, + stratify=labels, + random_state=42) + model = RandomForestClassifier() + model.fit(x_train, y_train) y_predict = model.predict(x_test) + score = accuracy_score(y_predict, y_test) -print('{}% of samples were classified correctly !'.format(score * 100)) +print(f'{score * 100}% of samples were classified correctly !') -f = open('model.p', 'wb') -pickle.dump({'model': model}, f) -f.close() +with open('../model/model.p', 'wb') as f: + pickle.dump({'model': model}, f) remove('./data.pickle') ``` -```python -#inference_classifier.py +```python {"id":"01HXQ4NN4K1WC0X7KXQP0PVHJE"} +# engine/train/inference_classifier.py + import pickle import cv2 import mediapipe as mp import numpy as np -import time -model_dict = pickle.load(open('./model.p', 'rb')) +model_dict = pickle.load(open('../model/model.p', 'rb')) model = model_dict['model'] cap = cv2.VideoCapture(0) @@ -174,18 +189,17 @@ mp_hands = mp.solutions.hands mp_drawing = mp.solutions.drawing_utils mp_drawing_styles = mp.solutions.drawing_styles -OUTPUT = [] +output: list[str] = [] hands = mp_hands.Hands(static_image_mode=True, min_detection_confidence=0.3) -labels_dict = {0:'ok',1:'xin chao',2:'tam biet'} -CHECK_FRAME = 0 +labels_dict = {0: 'ok', 1: 'xin chao', 2: 'tam biet'} +detected = False predicted_character = '' while True: - data_aux = [] - x_ = [] - y_ = [] + xs = [] + ys = [] ret, frame = cap.read() H, W, _ = frame.shape @@ -193,70 +207,64 @@ while True: frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results = hands.process(frame_rgb) - - if results.multi_hand_landmarks: - CHECK_FRAME+=1 + if results.multi_hand_landmarks: + detected = True - if CHECK_FRAME == 1: - CHECK_FRAME = 0 + if not detected: + continue - for hand_landmarks in results.multi_hand_landmarks: - mp_drawing.draw_landmarks( - frame, - hand_landmarks, - mp_hands.HAND_CONNECTIONS, - mp_drawing_styles.get_default_hand_landmarks_style(), - mp_drawing_styles.get_default_hand_connections_style()) + detected = False - for hand_landmarks in results.multi_hand_landmarks: - for i in range(len(hand_landmarks.landmark)): - x = hand_landmarks.landmark[i].x - y = hand_landmarks.landmark[i].y + for hand_landmarks in results.multi_hand_landmarks: + mp_drawing.draw_landmarks( + frame, hand_landmarks, mp_hands.HAND_CONNECTIONS, + mp_drawing_styles.get_default_hand_landmarks_style(), + mp_drawing_styles.get_default_hand_connections_style()) - x_.append(x) - y_.append(y) + for hand_landmarks in results.multi_hand_landmarks: + for _ in range(len(hand_landmarks.landmark)): + xs.append(hand_landmarks.landmark[0].x) + ys.append(hand_landmarks.landmark[0].y) - for i in range(len(hand_landmarks.landmark)): - x = hand_landmarks.landmark[i].x - y = hand_landmarks.landmark[i].y - data_aux.append(x - min(x_)) - data_aux.append(y - min(y_)) + for _ in range(len(hand_landmarks.landmark)): + data_aux.append(hand_landmarks.landmark[0].x - min(xs)) + data_aux.append(hand_landmarks.landmark[0].y - min(ys)) - x1 = int(min(x_) * W) - 10 - y1 = int(min(y_) * H) - 10 + x1 = int(min(xs) * W) - 10 + y1 = int(min(ys) * H) - 10 - x2 = int(max(x_) * W) - 10 - y2 = int(max(y_) * H) - 10 + x2 = int(max(xs) * W) - 10 + y2 = int(max(ys) * H) - 10 - prediction = model.predict([np.asarray(data_aux)]) + prediction = model.predict([np.asarray(data_aux)]) - print(prediction) + print(prediction) - predicted_character = labels_dict[int(prediction[0])] + predicted_character = labels_dict[int(prediction[0])] - cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 0), 4) - cv2.putText(frame, predicted_character , (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 1.3, (0, 0, 0), 3, - cv2.LINE_AA) + cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 0), 4) + cv2.putText(frame, predicted_character, (x1, y1 - 10), + cv2.FONT_HERSHEY_SIMPLEX, 1.3, (0, 0, 0), 3, cv2.LINE_AA) if predicted_character != '': - if len(OUTPUT) == 0 or OUTPUT[-1] != predicted_character: - OUTPUT.append(predicted_character) - + if len(output) == 0 or output[-1] != predicted_character: + output.append(predicted_character) cv2.imshow('frame', frame) - if cv2.waitKey(25)==ord('q'): + if cv2.waitKey(25) == ord('q'): break -print(OUTPUT) +print(output) cap.release() cv2.destroyAllWindows() + ``` ## Giấy phép -``` +```md {"id":"01HXQ4NN4MHTJTRY3Q2WSHGVHA"} MIT License Copyright (c) 2024 iotran207 @@ -279,6 +287,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ``` Phần cuối xin cảm ơn team MEDIAPIPE của google vì đã phát triển một framework thật tuyệt vời và [computervisioneng](https://github.com/computervisioneng) đã tạo nên một repo thật tuyệt vời để học hỏi. diff --git a/engine/Dockerfile b/engine/Dockerfile index 6448609..c3547a7 100644 --- a/engine/Dockerfile +++ b/engine/Dockerfile @@ -10,6 +10,6 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt COPY ./api /code/api -COPY ./train/model.p /code/api/model.p +COPY ./model/model.p /code/model/model.p CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8345"] \ No newline at end of file diff --git a/engine/api/database.sqlite b/engine/api/database.sqlite index 9e006f3779159df3db01a23ff9fdd8695d5fbebb..7aec99cf354146b01dfaa25c2bcfa4890c14eadd 100644 GIT binary patch delta 89 zcmZo@U~Fh$oFL7}HBrWym5V_y?Zw8F1^he=0t^iNU-+-^FXu1aEU1vmKe<%CA0qml k{~Z54{+B?}z5J8U>YGDE|M1V{Kg9nWDB8 bool: + return not not DATABASE_CURSOR.execute( + "SELECT * FROM DATA_USER WHERE token = ?", (token, )).fetchone() + + +async def handleVideo(video_path: str) -> dict[str, list[str] | str]: + video_capture = VideoCapture(video_path) predicted_character = '' - OUTPUT = [] - CHECK_FRAME = 0 + output: list[str] = [] + detected = True + try: while True: - data_aux = [] - x_ = [] - y_ = [] + data_aux: list[int] = [] + xs: list[int] = [] + ys: list[int] = [] ret, frame = video_capture.read() if not ret: break @@ -59,103 +58,142 @@ async def HandleVideo(VIDEO_PATH: str): frame_rgb = cvtColor(frame, COLOR_BGR2RGB) results = hands.process(frame_rgb) if results.multi_hand_landmarks: - CHECK_FRAME+=1 - if CHECK_FRAME == 1: - CHECK_FRAME = 0 - for hand_landmarks in results.multi_hand_landmarks: - for i in range(len(hand_landmarks.landmark)): - x = hand_landmarks.landmark[0].x - y = hand_landmarks.landmark[0].y - x_.append(x) - y_.append(y) - - for i in range(len(hand_landmarks.landmark)): - x = hand_landmarks.landmark[0].x - y = hand_landmarks.landmark[0].y - data_aux.append(x - min(x_)) - data_aux.append(y - min(y_)) - - x1 = int(min(x_) * W) - 10 - y1 = int(min(y_) * H) - 10 - x2 = int(max(x_) * W) - 10 - y2 = int(max(y_) * H) - 10 - - prediction = model.predict([np.asarray(data_aux)]) - predicted_character = labels_dict[int(prediction[0])] - if OUTPUT == []: - OUTPUT.append(predicted_character) - print(predicted_character) - else: - if OUTPUT[-1] != predicted_character: - OUTPUT.append(predicted_character) - print(predicted_character) - - return {"data": OUTPUT} + detected = True + + if not detected: + continue + + detected = False + for hand_landmarks in results.multi_hand_landmarks: + for _ in range(len(hand_landmarks.landmark)): + xs.append(hand_landmarks.landmark[0].x) + ys.append(hand_landmarks.landmark[0].y) + + for _ in range(len(hand_landmarks.landmark)): + data_aux.append(hand_landmarks.landmark[0].x - min(xs)) + data_aux.append(hand_landmarks.landmark[0].y - min(ys)) + + # unused variables + # x1 = int(min(x_) * W) - 10 + # y1 = int(min(y_) * H) - 10 + # x2 = int(max(x_) * W) - 10 + # y2 = int(max(y_) * H) - 10 + + prediction = model.predict([np.asarray(data_aux)]) + predicted_character = labels_dict[int(prediction[0])] + if output == []: + output.append(predicted_character) + print(predicted_character) + continue + if output[-1] != predicted_character: + output.append(predicted_character) + print(predicted_character) + + return {"data": output} except Exception as e: return {"error": str(e)} + @router.post("/video") -async def UploadVideo(file: UploadFile = UploadFile,token: str = None): - if not DATABASE_CURSOR.execute(f"SELECT * FROM DATA_USER WHERE token = '{token}'").fetchone(): +async def uploadVideo(file: UploadFile | None = None, + token: str | None = None): + if file is None: + return {"error": "No file provided."} + if token is None: + return {"error": "No token provided."} + + if not DATABASE_CURSOR.execute("SELECT * FROM DATA_USER WHERE token = ?", + (token, )).fetchone(): return {"error": "Invalid token."} - else: - TimeNow = time() - with open(f"data/temp/{TimeNow}.mp4", "wb") as buffer: - buffer.write(file.file.read()) - return await HandleVideo(f"data/temp/{TimeNow}.mp4") + timestamp = time() + with open(f"data/temp/{timestamp}.mp4", "wb") as buffer: + buffer.write(file.file.read()) + + return await handleVideo(f"data/temp/{timestamp}.mp4") -def GenToken(): - return ''.join(SystemRandom().choice(ascii_uppercase + digits) for _ in range(32)) @router.post("/regentoken") -async def GetToken(data: GetTokenModel): - token = GenToken() - while DATABASE_CURSOR.execute(f"SELECT * FROM DATA_USER WHERE token = '{token}'").fetchone(): - token = GenToken() - DATABASE_CURSOR.execute(f"UPDATE DATA_USER SET token = '{token}' WHERE username = '{data.username}' AND password = '{data.password}'") +async def getToken(user: User): + token = randomString(32) + + while DATABASE_CURSOR.execute("SELECT * FROM DATA_USER WHERE token = ?", + (token, )).fetchone(): + token = randomString(32) + + DATABASE_CURSOR.execute( + "UPDATE DATA_USER SET token = ? WHERE username = ? AND password = ?", + (token, user.username, user.password)) DATABASE.commit() - - DATABASE_CURSOR.execute(f"SELECT * FROM DATA_USER WHERE username = '{data.username}' AND password = '{data.password}'") + + DATABASE_CURSOR.execute( + "SELECT * FROM DATA_USER WHERE username = ? AND password = ?", + (user.username, user.password)) + result = DATABASE_CURSOR.fetchone() - if result: - return {"token": result[2]} - else: - return {"error": "Invalid username or password, you can go to /register to create a new account."} + if not result: + return { + "error": + "Invalid username or password, you can go to /register to create a new account." + } + + return {"token": result[2]} + @router.post("/register") -async def Register(username: str, password: str): +async def register(username: str, password: str): try: - DATABASE_CURSOR.execute(f"SELECT * FROM DATA_USER WHERE username = '{username}'") - result = DATABASE_CURSOR.fetchone() - if result: + DATABASE_CURSOR.execute("SELECT * FROM DATA_USER WHERE username = ?", + (username, )) + if DATABASE_CURSOR.fetchone(): # If the username already exists return {"error": "Username already exists."} - else: - token = GenToken() - while DATABASE_CURSOR.execute(f"SELECT * FROM DATA_USER WHERE token = '{token}'").fetchone(): - token = GenToken() - DATABASE_CURSOR.execute(f"INSERT INTO DATA_USER (username, password,token) VALUES ('{username}', '{password}', '{token}')") - DATABASE.commit() - return {"token": f"{token}"} + + token = randomString(32) + while DATABASE_CURSOR.execute( + "SELECT * FROM DATA_USER WHERE token = ?", + (token, )).fetchone(): + # If the token already exists + token = randomString(32) + + DATABASE_CURSOR.execute( + "INSERT INTO DATA_USER (username, password, token) VALUES (?, ?, ?)", + (username, password, token)) + + DATABASE.commit() + + return {"token": token} except Exception as e: - return {"error": str(e)} - + return JSONResponse(status_code=500, content={"error": str(e)}) + + @router.post("/upload") -async def UploadFile(file: UploadFile = UploadFile,token: str = None): - if VerifyUserToken(token)==False: +async def uploadFile(file: UploadFile | None = None, token: str | None = None): + if file is None: + return {"error": "No file provided."} + if token is None: + return {"error": "No token provided."} + + if verifyUserToken(token) == False: return {"error": "Invalid token."} - else: - USERNAME = DATABASE_CURSOR.execute(f"SELECT * FROM DATA_USER WHERE token = '{token}'").fetchone()[0] - if not path_exists(f"data/user/{USERNAME}"): - mkdir(f"data/user/{USERNAME}") - - with open(f"data/user/{USERNAME}/{file.filename}", "wb") as buffer: - buffer.write(file.file.read()) - return {"status": "success", "filename": file.filename, "username": USERNAME,"time_upload": time(),"size": file.file.seek(0,2)} - + + username = DATABASE_CURSOR.execute( + "SELECT * FROM DATA_USER WHERE token = ?", (token, )).fetchone()[0] + + if not path_exists(f"data/user/{username}"): + mkdir(f"data/user/{username}") + + with open(f"data/user/{username}/{file.filename}", "wb") as buffer: + buffer.write(file.file.read()) + + return { + "status": "success", + "filename": file.filename, + "username": username, + "time_upload": time(), + "size": file.file.seek(0, 2) + } + + @router.post("/customtrain") -async def train(token:str): - return {"status":"will be updated soon."} - - - +async def train(token: str): + return {"status": "will be updated soon."} diff --git a/engine/api/utils.py b/engine/api/utils.py new file mode 100644 index 0000000..51a09d5 --- /dev/null +++ b/engine/api/utils.py @@ -0,0 +1,8 @@ +import random +import string + + +def randomString(length): + return ''.join( + random.choice(string.ascii_letters + string.digits) + for i in range(length)) diff --git a/engine/api/model.p b/engine/model/model.p similarity index 100% rename from engine/api/model.p rename to engine/model/model.p diff --git a/engine/train/create_dataset.py b/engine/train/create_dataset.py index 5e113d0..3141bdf 100644 --- a/engine/train/create_dataset.py +++ b/engine/train/create_dataset.py @@ -1,9 +1,8 @@ import os import pickle -import mediapipe as mp import cv2 -import matplotlib.pyplot as plt +import mediapipe as mp mp_hands = mp.solutions.hands mp_drawing = mp.solutions.drawing_utils @@ -19,8 +18,8 @@ for img_path in os.listdir(os.path.join(DATA_DIR, dir_)): data_aux = [] - x_ = [] - y_ = [] + xs = [] + ys = [] img = cv2.imread(os.path.join(DATA_DIR, dir_, img_path)) img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) @@ -28,22 +27,16 @@ results = hands.process(img_rgb) if results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: - for i in range(len(hand_landmarks.landmark)): - x = hand_landmarks.landmark[i].x - y = hand_landmarks.landmark[i].y - - x_.append(x) - y_.append(y) + for _ in range(len(hand_landmarks.landmark)): + xs.append(hand_landmarks.landmark[0].x) + ys.append(hand_landmarks.landmark[0].y) - for i in range(len(hand_landmarks.landmark)): - x = hand_landmarks.landmark[i].x - y = hand_landmarks.landmark[i].y - data_aux.append(x - min(x_)) - data_aux.append(y - min(y_)) + for _ in range(len(hand_landmarks.landmark)): + data_aux.append(hand_landmarks.landmark[0].x - min(xs)) + data_aux.append(hand_landmarks.landmark[0].y - min(ys)) data.append(data_aux) labels.append(dir_) -f = open('data.pickle', 'wb') -pickle.dump({'data': data, 'labels': labels}, f) -f.close() +with open('data.pickle', 'wb') as f: + pickle.dump({'data': data, 'labels': labels}, f) diff --git a/engine/train/inference_classifier.py b/engine/train/inference_classifier.py index 8ec4ae3..236bf0b 100644 --- a/engine/train/inference_classifier.py +++ b/engine/train/inference_classifier.py @@ -3,9 +3,8 @@ import cv2 import mediapipe as mp import numpy as np -import time -model_dict = pickle.load(open('./model.p', 'rb')) +model_dict = pickle.load(open('../model/model.p', 'rb')) model = model_dict['model'] cap = cv2.VideoCapture(0) @@ -14,17 +13,17 @@ mp_drawing = mp.solutions.drawing_utils mp_drawing_styles = mp.solutions.drawing_styles -OUTPUT = [] +output: list[str] = [] hands = mp_hands.Hands(static_image_mode=True, min_detection_confidence=0.3) -labels_dict = {0:'ok',1:'xin chao',2:'tam biet'} -CHECK_FRAME = 0 +labels_dict = {0: 'ok', 1: 'xin chao', 2: 'tam biet'} +detected = False predicted_character = '' while True: data_aux = [] - x_ = [] - y_ = [] + xs = [] + ys = [] ret, frame = cap.read() H, W, _ = frame.shape @@ -32,62 +31,55 @@ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results = hands.process(frame_rgb) - - if results.multi_hand_landmarks: - CHECK_FRAME+=1 + if results.multi_hand_landmarks: + detected = True - if CHECK_FRAME == 1: - CHECK_FRAME = 0 + if not detected: + continue - for hand_landmarks in results.multi_hand_landmarks: - mp_drawing.draw_landmarks( - frame, - hand_landmarks, - mp_hands.HAND_CONNECTIONS, - mp_drawing_styles.get_default_hand_landmarks_style(), - mp_drawing_styles.get_default_hand_connections_style()) + detected = False - for hand_landmarks in results.multi_hand_landmarks: - for i in range(len(hand_landmarks.landmark)): - x = hand_landmarks.landmark[i].x - y = hand_landmarks.landmark[i].y + for hand_landmarks in results.multi_hand_landmarks: + mp_drawing.draw_landmarks( + frame, hand_landmarks, mp_hands.HAND_CONNECTIONS, + mp_drawing_styles.get_default_hand_landmarks_style(), + mp_drawing_styles.get_default_hand_connections_style()) - x_.append(x) - y_.append(y) + for hand_landmarks in results.multi_hand_landmarks: + for _ in range(len(hand_landmarks.landmark)): + xs.append(hand_landmarks.landmark[0].x) + ys.append(hand_landmarks.landmark[0].y) - for i in range(len(hand_landmarks.landmark)): - x = hand_landmarks.landmark[i].x - y = hand_landmarks.landmark[i].y - data_aux.append(x - min(x_)) - data_aux.append(y - min(y_)) + for _ in range(len(hand_landmarks.landmark)): + data_aux.append(hand_landmarks.landmark[0].x - min(xs)) + data_aux.append(hand_landmarks.landmark[0].y - min(ys)) - x1 = int(min(x_) * W) - 10 - y1 = int(min(y_) * H) - 10 + x1 = int(min(xs) * W) - 10 + y1 = int(min(ys) * H) - 10 - x2 = int(max(x_) * W) - 10 - y2 = int(max(y_) * H) - 10 + x2 = int(max(xs) * W) - 10 + y2 = int(max(ys) * H) - 10 - prediction = model.predict([np.asarray(data_aux)]) + prediction = model.predict([np.asarray(data_aux)]) - print(prediction) + print(prediction) - predicted_character = labels_dict[int(prediction[0])] + predicted_character = labels_dict[int(prediction[0])] - cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 0), 4) - cv2.putText(frame, predicted_character , (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 1.3, (0, 0, 0), 3, - cv2.LINE_AA) + cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 0), 4) + cv2.putText(frame, predicted_character, (x1, y1 - 10), + cv2.FONT_HERSHEY_SIMPLEX, 1.3, (0, 0, 0), 3, cv2.LINE_AA) if predicted_character != '': - if len(OUTPUT) == 0 or OUTPUT[-1] != predicted_character: - OUTPUT.append(predicted_character) - + if len(output) == 0 or output[-1] != predicted_character: + output.append(predicted_character) cv2.imshow('frame', frame) - if cv2.waitKey(25)==ord('q'): + if cv2.waitKey(25) == ord('q'): break -print(OUTPUT) +print(output) cap.release() cv2.destroyAllWindows() diff --git a/engine/train/model.p b/engine/train/model.p deleted file mode 100644 index dabb960a8c6e15403f170e2fc038bbe5c088f662..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79420 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 Td1?DR*psw|TBF>A?AHGebK+zG diff --git a/engine/train/train_classifier.py b/engine/train/train_classifier.py index a5d311b..7b6779b 100644 --- a/engine/train/train_classifier.py +++ b/engine/train/train_classifier.py @@ -1,18 +1,22 @@ import pickle +from os import remove +import numpy as np from sklearn.ensemble import RandomForestClassifier -from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score -import numpy as np -from os import remove - +from sklearn.model_selection import train_test_split data_dict = pickle.load(open('./data.pickle', 'rb')) data = np.asarray(data_dict['data']) labels = np.asarray(data_dict['labels']) -x_train, x_test, y_train, y_test = train_test_split(data, labels, test_size=0.2, shuffle=True, stratify=labels, random_state=42) +x_train, x_test, y_train, y_test = train_test_split(data, + labels, + test_size=0.2, + shuffle=True, + stratify=labels, + random_state=42) model = RandomForestClassifier() @@ -22,10 +26,9 @@ score = accuracy_score(y_predict, y_test) -print('{}% of samples were classified correctly !'.format(score * 100)) +print(f'{score * 100}% of samples were classified correctly !') -f = open('model.p', 'wb') -pickle.dump({'model': model}, f) -f.close() +with open('../model/model.p', 'wb') as f: + pickle.dump({'model': model}, f) remove('./data.pickle') diff --git a/example/Python/nomodel.py b/example/Python/nomodel.py index e17f867..0799bad 100644 --- a/example/Python/nomodel.py +++ b/example/Python/nomodel.py @@ -1,45 +1,57 @@ import cv2 -import numpy as np -import os -from matplotlib import pyplot as plt import mediapipe as mp -mp_hands = mp.solutions.holistic +mp_hands = mp.solutions.holistic mp_drawing = mp.solutions.drawing_utils cap = cv2.VideoCapture(0) + def mediapipe_detection(image, model): - image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) - image.flags.writeable = False - results = model.process(image) - image.flags.writeable = True - image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) + image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) + image.flags.writeable = False + results = model.process(image) + image.flags.writeable = True + image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) return image, results + def draw_landmarks(image, results): - mp_drawing.draw_landmarks(image, results.left_hand_landmarks, mp_hands.HAND_CONNECTIONS) - mp_drawing.draw_landmarks(image, results.right_hand_landmarks, mp_hands.HAND_CONNECTIONS) + mp_drawing.draw_landmarks(image, results.left_hand_landmarks, + mp_hands.HAND_CONNECTIONS) + mp_drawing.draw_landmarks(image, results.right_hand_landmarks, + mp_hands.HAND_CONNECTIONS) + def draw_styled_landmarks(image, results): - mp_drawing.draw_landmarks(image, results.left_hand_landmarks, mp_hands.HAND_CONNECTIONS, - mp_drawing.DrawingSpec(color=(121,22,76), thickness=2, circle_radius=4), - mp_drawing.DrawingSpec(color=(121,44,250), thickness=2, circle_radius=2) - ) - mp_drawing.draw_landmarks(image, results.right_hand_landmarks, mp_hands.HAND_CONNECTIONS, - mp_drawing.DrawingSpec(color=(245,117,66), thickness=2, circle_radius=4), - mp_drawing.DrawingSpec(color=(245,66,230), thickness=2, circle_radius=2) - ) - + mp_drawing.draw_landmarks( + image, results.left_hand_landmarks, mp_hands.HAND_CONNECTIONS, + mp_drawing.DrawingSpec(color=(121, 22, 76), + thickness=2, + circle_radius=4), + mp_drawing.DrawingSpec(color=(121, 44, 250), + thickness=2, + circle_radius=2)) + mp_drawing.draw_landmarks( + image, results.right_hand_landmarks, mp_hands.HAND_CONNECTIONS, + mp_drawing.DrawingSpec(color=(245, 117, 66), + thickness=2, + circle_radius=4), + mp_drawing.DrawingSpec(color=(245, 66, 230), + thickness=2, + circle_radius=2)) + + cap = cv2.VideoCapture(0) -with mp_hands.Holistic(min_detection_confidence=0.5, min_tracking_confidence=0.5) as holistic: +with mp_hands.Holistic(min_detection_confidence=0.5, + min_tracking_confidence=0.5) as holistic: while cap.isOpened(): ret, frame = cap.read() image, results = mediapipe_detection(frame, holistic) print(results) - + draw_styled_landmarks(image, results) cv2.imshow('OpenCV Feed', image) @@ -48,4 +60,3 @@ def draw_styled_landmarks(image, results): break cap.release() cv2.destroyAllWindows() - diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000..8a94273 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,4 @@ +# Global options: + +[mypy] +disable_error_code = import \ No newline at end of file From d0a2ca660b879605798e76974feeeb886dc9066a Mon Sep 17 00:00:00 2001 From: Toby Cm Date: Sun, 12 May 2024 12:50:01 -0700 Subject: [PATCH 2/3] chore: :lipstick: clean readme --- README.md | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index c166b30..e6189f0 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,13 @@ ---- -runme: - id: 01HXQ4NN4MHTJTRY3Q2ZWHP2A7 - version: v3 ---- - # Atlantis engine ![1715102710368](example/docs/image/Atlantis.png) ## Thành quả phát triển -* [X] Thiết kế API -* [X] Công khai toàn bộ mã nguồn -* [X] Tạo các code mẫu để áp dụng -* [ ] đang cập nhật tiếp... +- [x] Thiết kế API +- [x] Công khai toàn bộ mã nguồn +- [x] Tạo các code mẫu để áp dụng +- [ ] đang cập nhật tiếp... ## Thử nghiệm @@ -31,15 +25,15 @@ Giao tiếp có vai trò vô cùng quan trọng đối với mỗi chúng ta, n ### Công nghệ sử dụng -* **Thị giác máy tính** +- **Thị giác máy tính** Thị giác máy tính là gì? Thị giác máy tính là một công nghệ mà máy sử dụng để tự động nhận biết và mô tả hình ảnh một cách chính xác và hiệu quả. Ngày nay, các hệ thống máy tính có quyền truy cập vào khối lượng lớn hình ảnh và dữ liệu video bắt nguồn từ hoặc được tạo bằng điện thoại thông minh, camera giao thông, hệ thống bảo mật và các thiết bị khác. Ứng dụng thị giác máy tính sử dụng trí tuệ nhân tạo và máy học (AI/ML) để xử lý những dữ liệu này một cách chính xác nhằm xác định đối tượng và nhận diện khuôn mặt, cũng như phân loại, đề xuất, giám sát và phát hiện. -* **Máy học** +- **Máy học** Máy học (machine learning) là một lĩnh vực của trí tuệ nhân tạo (AI) mà trong đó máy tính được lập trình để tự động học và cải thiện từ dữ liệu mà nó nhận được. Thay vì chỉ dựa trên các quy tắc cụ thể được lập trình trước, máy học cho phép máy tính "học" thông qua việc phân tích dữ liệu và tìm ra các mẫu, xu hướng hoặc quy luật ẩn trong dữ liệu mà không cần được lập trình trực tiếp. -* **Giao diện chương trình ứng dụng** +- **Giao diện chương trình ứng dụng** Giao diện chương trình là gì? Giao diện chương trình – Application Programming Interface viết tắt là API là một trung gian phần mềm cho phép hai ứng dụng giao tiếp với nhau, có thể sử dụng cho web-based system, operating system, database system, computer hardware, hoặc software library. @@ -49,7 +43,7 @@ Giao diện chương trình là gì? Giao diện chương trình – Application #### Dưới đây là hướng dẫn train model cơ bản -```python {"id":"01HXQ4NN4K1WC0X7KXQHW3331T"} +```python # engine/train/collect_imgs.py import os @@ -84,7 +78,7 @@ cv2.destroyAllWindows() ``` -```python {"id":"01HXQ4NN4K1WC0X7KXQJAGAZM4"} +```python # engine/train/create_dataset.py import os @@ -132,7 +126,7 @@ with open('data.pickle', 'wb') as f: ``` -```python {"id":"01HXQ4NN4K1WC0X7KXQNK2D04E"} +```python # engine/train/train_classifier.py import pickle @@ -171,7 +165,7 @@ with open('../model/model.p', 'wb') as f: remove('./data.pickle') ``` -```python {"id":"01HXQ4NN4K1WC0X7KXQP0PVHJE"} +```python # engine/train/inference_classifier.py import pickle @@ -264,7 +258,7 @@ cv2.destroyAllWindows() ## Giấy phép -```md {"id":"01HXQ4NN4MHTJTRY3Q2WSHGVHA"} +``` MIT License Copyright (c) 2024 iotran207 @@ -284,7 +278,7 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 94cad0a56b5d92c480ffaee724da4c40d38e97ce Mon Sep 17 00:00:00 2001 From: Toby Cm Date: Sun, 12 May 2024 17:04:44 -0700 Subject: [PATCH 3/3] refactor: :recycle: use context managers to auto close file handle --- README.md | 26 +++++++++++++++++++------- engine/api/routers/engine.py | 3 ++- engine/train/inference_classifier.py | 3 ++- engine/train/train_classifier.py | 3 ++- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index e6189f0..a611719 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ +--- +runme: + id: 01HXQM38H0ZX9BSHH89DJJB5PA + version: v3 +--- + # Atlantis engine ![1715102710368](example/docs/image/Atlantis.png) @@ -43,7 +49,7 @@ Giao diện chương trình là gì? Giao diện chương trình – Application #### Dưới đây là hướng dẫn train model cơ bản -```python +```python {"id":"01HXQM38GYX73YFXXRSQ2KJSEJ"} # engine/train/collect_imgs.py import os @@ -76,9 +82,10 @@ for j in range(number_of_classes): cap.release() cv2.destroyAllWindows() + ``` -```python +```python {"id":"01HXQM38GYX73YFXXRSQXQ5PWM"} # engine/train/create_dataset.py import os @@ -124,9 +131,10 @@ for dir_ in os.listdir(DATA_DIR): with open('data.pickle', 'wb') as f: pickle.dump({'data': data, 'labels': labels}, f) + ``` -```python +```python {"id":"01HXQM38GYX73YFXXRSR0G097A"} # engine/train/train_classifier.py import pickle @@ -137,7 +145,8 @@ from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score from sklearn.model_selection import train_test_split -data_dict = pickle.load(open('./data.pickle', 'rb')) +with open('./data.pickle', 'rb') as f: + data_dict = pickle.load(f) data = np.asarray(data_dict['data']) labels = np.asarray(data_dict['labels']) @@ -163,9 +172,10 @@ with open('../model/model.p', 'wb') as f: pickle.dump({'model': model}, f) remove('./data.pickle') + ``` -```python +```python {"id":"01HXQM38GYX73YFXXRSRYS7KBR"} # engine/train/inference_classifier.py import pickle @@ -174,7 +184,8 @@ import cv2 import mediapipe as mp import numpy as np -model_dict = pickle.load(open('../model/model.p', 'rb')) +with open('../model/model.p', 'rb') as f: + model_dict = pickle.load(f) model = model_dict['model'] cap = cv2.VideoCapture(0) @@ -258,7 +269,7 @@ cv2.destroyAllWindows() ## Giấy phép -``` +```md {"id":"01HXQM38GZ1HBF5NNQ999QT1D4"} MIT License Copyright (c) 2024 iotran207 @@ -282,6 +293,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ``` Phần cuối xin cảm ơn team MEDIAPIPE của google vì đã phát triển một framework thật tuyệt vời và [computervisioneng](https://github.com/computervisioneng) đã tạo nên một repo thật tuyệt vời để học hỏi. diff --git a/engine/api/routers/engine.py b/engine/api/routers/engine.py index d46ba79..868a637 100644 --- a/engine/api/routers/engine.py +++ b/engine/api/routers/engine.py @@ -22,7 +22,8 @@ mp_drawing_styles = mp.solutions.drawing_styles hands = mp_hands.Hands(static_image_mode=True, min_detection_confidence=0.3) -model_dict = pickle_load(open('../model/model.p', 'rb')) +with open('../model/model.p', 'rb') as f: + model_dict = pickle_load(f) model = model_dict['model'] labels_dict = {0: 'hi', 1: 'toi la', 2: 'hoang lan'} diff --git a/engine/train/inference_classifier.py b/engine/train/inference_classifier.py index 236bf0b..f94f5af 100644 --- a/engine/train/inference_classifier.py +++ b/engine/train/inference_classifier.py @@ -4,7 +4,8 @@ import mediapipe as mp import numpy as np -model_dict = pickle.load(open('../model/model.p', 'rb')) +with open('../model/model.p', 'rb') as f: + model_dict = pickle.load(f) model = model_dict['model'] cap = cv2.VideoCapture(0) diff --git a/engine/train/train_classifier.py b/engine/train/train_classifier.py index 7b6779b..2f384ac 100644 --- a/engine/train/train_classifier.py +++ b/engine/train/train_classifier.py @@ -6,7 +6,8 @@ from sklearn.metrics import accuracy_score from sklearn.model_selection import train_test_split -data_dict = pickle.load(open('./data.pickle', 'rb')) +with open('./data.pickle', 'rb') as f: + data_dict = pickle.load(f) data = np.asarray(data_dict['data']) labels = np.asarray(data_dict['labels'])