โ๐ ๋ณด๊ณ ๋ฐ๋ผํ ํฌ์คํ : Marcelo ์์ ์จ ๋ธ๋ก๊ทธ
๐ ์ค๋น๋ฌผ
โญ๏ธ ๋ชฉํ
ย openCV์ ๊ด๋ จ๋ ์คํ์์ค๋ค์ ํ์ฉํ์ฌ ๋ด ์ผ๊ตด ์ธ์ ํ์ธํ๊ธฐ
โ๏ธ openCV ๋ฑ ๊ด๋ จ ํจํค์ง๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์ค์น๋์๋๊ฐ
โ๏ธ ์ฝ๋๊ฐ ์ ์์ ์ผ๋ก ์๋ํ๋๊ฐ
โ๏ธ ๋ด ์ผ๊ตด์ ๋ผ์ฆ๋ฒ ๋ฆฌ๊ฐ ์์๋จน๋?!
์ฌ์ค ์ค๋น๋ฌผ๋ง ์์ผ๋ฉด ๋ ๊ฑฐ๋ผ ๋ณธ๋ค
์ง์ง์
๋ณดํต ๋ฌธ์ ๋ ํจํค์ง ์ค์น์์ ๋ฐ์ํ๋ค
๋ชจ๋ ๋ก๋์ ๊ดํ ๋ฌธ์ ๋ ์ต์๋จ ์๋ณธ ๊ธ์์ ์์ ํ๋ ๋ฐฉ๋ฒ์ ์ ์ํ์ง๋ง ํจํค์ง ์์กด์ฑ์ด๋ ๋ฒ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ๊ณจ์น์ํ๋ค
ํน์๋ ๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค๋ฉด
could not open moddep file '/lib/modules/4.19.75-v7l+/modules.dep.bin'
๐ ์ฌ๊ธฐ๋ฅผ ํตํด ํด๊ฒฐํ ์ ์๋ค
openCV์ Python์ ์ค์นํ๋ ๊ฒ์ ๋น๊ต์ ๊ฐ๋จํ์ง๋ง
haarcascade๋ฅผ ๋ฐ๋๋ค๊ณ ํ ๋ ์ ๋ง์ ๋ง ๋ด๋น๋ผ๋ฉด ํค๋งฌ ์ ์๋ค
์ฐธ๊ณ ๋ก ๋ ์์ฒญ ํค๋งธ๋ค
๐ haarcascade๋ ๊ฐ์ฒด ์ธ์๊ณผ ํ์ต์ ๊ดํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค
์ด๋ฅผ ํตํด ์ฌ๋์ ์ผ๊ตด์ด๋ ๋๋์ ์ ์ ๋ฑ์ openCV๋ก ์ธ์ํ ์ ์๊ฒ ๋๋ค
haarcascade๋ ์ง์ ๋ค์ด๋ก๋ ๋ฐ๋๊ฒ ํธํ๋ค
๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ ํ์ํ ํ์ผ๋ง ์์ ๊ณจ๋ผ์ธ ์ ์๊ธฐ ๋๋ฌธ์
ํ๊บผ๋ฒ์ ๋ฐ์๋๋๋ก ํ์
๐ $ git clone https://github.com/opencv/opencv.git
์ค์น๋๊ธธ ์ํ๋ ๋๋ ํฐ๋ฆฌ๋ฅผ ์์ฑํ ํ ์์ ๋ช
๋ น์ด๋ก ๋ค์ด๋ก๋๊ฐ ๊ฐ๋ฅํ๋ค
์ง์ ๊นํ๋ธ์์ ๋ค์ด๋ก๋ ํ๋ ๊ฒ๋ ๊ฐ๋ฅํ ๊ฒ์ผ๋ก ์๊ณ ์๋ค
๋ค์ด๋ก๋๋ ์ด๋ ค์ด ๊ฒ์ด ์๋๊ธฐ ๋๋ฌธ์ ๊ผญ ๊ผญ ๋ฏธ๋ฆฌ ์ค๋นํด๋์
์ค์น๊ฐ ์๋ฃ๋๋ค๋ฉด ๋ค์์ ์ฝ๋๋ฅผ ํ์ผ๋ก ์์ฑํ๋ค
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
cap.set(3,640) # set Width
cap.set(4,480) # set Height
while(True):
ret, frame = cap.read()
frame = cv2.flip(frame, -1) # Flip camera vertically
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame', frame)
cv2.imshow('gray', gray)
k = cv2.waitKey(30) & 0xff
if k == 27: # press 'ESC' to quit
break
cap.release()
cv2.destroyAllWindows()
์ถ์ฒ: Marcelo ์์ ์จ ๋ธ๋ก๊ทธ
์ด ์ฝ๋๋ฅผ ๐ python <ํ์ผ์ด๋ฆ>.py
๋ก ์คํํ๋ฉด
์ปฌ๋ฌ ํ๋ฉด๊ณผ ํ๋ฐฑ ํ๋ฉด์ด ๋์์ ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค
ํ๋ฉด์ด ๋์ค๊ฒ ๋ง๋ค์์ผ๋ ์ด์ ์ผ๊ตด์ ์ธ์ํ๊ฒ ๋ง๋ค์ด์ผ๊ฒ ๋ค
๐ก ์ผ๊ตด(๋๋ ๋ชจ๋ ๋ฌผ์ฒด)์ ๊ฐ์งํ๋ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์
Haar Cascade classifier ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ผ๊ณ ํ๋ค
์ผ๊ตด๋ฟ๋ง์ด ์๋๋ผ ์์ ์ด ์ํ๋ ๊ฐ์ฒด๋ฅผ ์ธ์ ์ํค๋ ค๋ฉด ํ๋ จ์ด ํ์ํ๋ฐ ์์ธํ ๋ด์ฉ์
๐์ฌ๊ธฐ์์ ๋ค๋ฃจ๊ณ ์๋ค
๋ค์์ ์ฝ๋๋ฅผ ํตํด ์ผ๊ตด์ ์ธ์ํ์ฌ ์ฌ๊ฐํ ๋ฐ์ค๋ก ์ก์์ฃผ๋์ง ํ์ธํ๋ค
์ฝ๋ ์ด๋ฐ์ faceCascade ๋ณ์์ ๊ฒฝ๋ก๋ ์์ ์ด ๋ง๋ ๋๋ ํฐ๋ฆฌ๋ฅผ ํ์ธํ๊ณ ์์ ํด์ค๋ค
โโ ์ด ์ฝ๋๊ฐ ์ ์ฅ๋๋ ๊ฒฝ๋ก์
haarcascade_frontalface_default.xml
ํ์ผ์ ๋ณต์ฌํ์ฌ ๋ฃ์ด์ค์ผ ํ๋ค
์ด ํ์ผ์ ๋ฏธ๋ฆฌ ๋ค์ด ๋ฐ์๋์ harrCascadeํด๋์์ ์ฐพ์ ์ ์๋ค
'''
Haar Cascade Face detection with OpenCV
Based on tutorial by pythonprogramming.net
Visit original post: https://pythonprogramming.net/haar-cascade-face-eye-detection-python-opencv-tutorial/
Adapted by Marcelo Rovai - MJRoBot.org @ 7Feb2018
'''
import numpy as np
import cv2
# multiple cascades: https://github.com/Itseez/opencv/tree/master/data/haarcascades
faceCascade = cv2.CascadeClassifier('Cascades/haarcascade_frontalface_default.xml')
cap = cv2.VideoCapture(0)
cap.set(3,640) # set Width
cap.set(4,480) # set Height
while True:
ret, img = cap.read()
img = cv2.flip(img, -1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.2,
minNeighbors=5
,
minSize=(20, 20)
)
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
cv2.imshow('video',img)
k = cv2.waitKey(30) & 0xff
if k == 27: # press 'ESC' to quit
break
cap.release()
cv2.destroyAllWindows()
์ถ์ฒ: Marcelo ์์ ์จ ๋ธ๋ก๊ทธ
์ด ์ฝ๋๋ฅผ ์คํํ๋๋ฐ
faceCascade = cv2.CascadeClassifier('Cascades/haarcascade_frontalface_default.xml')
๋ถ๋ถ์์ ์ค๋ฅ๊ฐ ๋๋ค๋ฉด haarcascade_frontalface_default.xml
ํ์ผ์ ๊ฒฝ๋ก๊ฐ ์๋ชป๋ ๊ฒ์ด๋ ํ์ธํด์ ๋ฐ๋ก ์ก๋๋ค
๋ง์ฐฌ๊ฐ์ง๋ก ์ฝ๋๋ฅผ ๐ python <ํ์ผ์ด๋ฆ>.py
๋ก ์คํํ๋ฉด
ํ๋์ ์ฌ๊ฐํ ์์ ์ผ๊ตด์ ์ก์์ค๋ค
์ฌ๋ ์ผ๊ตด ์ทจ๊ธ์ ๋นํด์ ๋คํ์ด๋ค
์ด์ ๋ด ์ผ๊ตด์ ๋ณด๋ฉด ํน์ ์ธ์ผ๋ก ์ธ์ํ ์ ์๋๋ก
๋ด ์ด๋ฆ์ ์
๋ ฅํ๊ณ ์ฌ์ง์ ์ฐ์ด์ ํ์ต์ํฌ ๊ฒ์ด๋ค
๋๋ ํฐ๋ฆฌ๊ฐ ๋ณต์กํด์ง ์ ์์ผ๋ ํ๋๋ฅผ ์๋ก ๋ง๋ ๋ค
ํฐ๋ฏธ๋์์๋ ํ์ผ๋งค๋์ ์์๋ ์๋ฌดํผ ์ํ๋ ๋๋ ํฐ๋ฆฌ๋ฅผ ์์ฑํ๋ค
๋๋ ์์ ํ Marcelo์์ ์จ๋ฅผ ๋ฐ๋ผํ๋ค
๐ mkdir FacialRecognitionProject
๊ทธ๋ฆฌ๊ณ ํ์ต์ํฌ ๋ด ์ผ๊ตด ์ฌ์ง์ ์ ์ฅํด๋ ํด๋๋ฅผ ํ์ํด๋๋ก ๋ง๋ ๋ค
๐ mkdir dataset
~/FacialRecognitionProject/dataset
์๋ ๊ฒ ๋ง๋ค์ด์ง ์ํ์ด๋ค
๋ค์์ ์ฝ๋๋
dataset์์ ๋ค์ ์์ ๋๋ ํฐ๋ฆฌ๋ก ์ฌ๋ผ๊ฐ์
~/FacialRecognitionProject ์ ์์ฑํ๋ค
โโ ๋ง์ฐฌ๊ฐ์ง๋ก
haarcascade_frontalface_default.xml
ํ์ผ์ ~/FacialRecognitionProject ์ ๋ฃ์ด์ฃผ์
๋ณต์ฌํ๋ ๊ฒ ํธํ ๊ฒ ๊ฐ๋ค
์ฌ๊ธฐ์๋ ๋ง์ฐฌ๊ฐ์ง๋ก faceCascade ๋ณ์์ ๊ฒฝ๋ก๋ฅผ ์์ ์ด ์์ฑํ ๊ฒฝ๋ก์ ๋ง๊ฒ ์ ์์ ํด์ค๋ค
import numpy as np
import cv2
faceCascade = cv2.CascadeClassifier('Cascades/haarcascade_frontalface_default.xml')
cap = cv2.VideoCapture(0)
cap.set(3,640) # set Width
cap.set(4,480) # set Height
while True:
ret, img = cap.read()
img = cv2.flip(img, -1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.2,
minNeighbors=5,
minSize=(20, 20)
)
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
cv2.imshow('video',img)
k = cv2.waitKey(30) & 0xff
if k == 27: # press 'ESC' to quit
break
cap.release()
cv2.destroyAllWindows()
์ถ์ฒ: Marcelo ์์ ์จ ๋ธ๋ก๊ทธ
์ด ์ฝ๋๋ฅผ ๐ python <ํ์ผ์ด๋ฆ>.py
๋ก ์คํํ๋ฉด
์ด๋ฐ ๋ฌธ๊ตฌ๊ฐ ๋์จ๋ค
user id๋ฅผ ์
๋ ฅํ๋ผ๋๋ฐ ์ฌ๊ธฐ์ ๋ฃ์ id๋ ์ซ์์ด๋ค
์ผ๊ตด๊ณผ ๋งค์นํ ์ด๋ฆ์ ๋ํ ๋ฐฐ์ด์ ๋ค์ ํ์ผ์์ ๋ณด๊ฒ ๋ ๊ฒ์ด๋ค
์ง๊ธ์ ์๊ธฐ ์ฝ๊ฒ 1๋ก ๋ฃ์ด์ ์คํํ๋ค
1์ ์ ๋ ฅํ๋ฉด
์บก์ณ๊ฐ ์์๋๋ ์ ์ ๋์ ์นด๋ฉ๋ผ๋ฅผ ์์ํ๊ณ ๊ธฐ๋ค๋ฆฌ๋ผ๋ ์๋ด๊ฐ ๋์จ๋ค
์ง์ ํด๋ณด๋ ๋ง์คํฌ๋ฅผ ์ด ์ํ์์๋ ์ผ๊ตด์ด ์ ์ธ์๋์ง ์๋๋ค
์๊ฒฝ๋ ์ธ์์ ์ํฅ์ ์ค ์ ์์ผ๋ ๋ค ๋ด๋ ค ๋๊ณ (?) ์นด๋ฉ๋ผ๋ฅผ ์ณ๋ค ๋ด์ผ ํ๋ค
์๋ฌดํผ ์ด ์์
์ด ๋ฌด์ฌํ ๋๋ฌ๋ค๋ฉด
์ด๋ฐ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค
user id๋ฅผ '1'๋ก ํ๊ธฐ ๋๋ฌธ์ 1.1, 1.2, 1.3 ~ ์์ผ๋ก ์์ฑ๋ ๊ฒ์ ๋ณผ ์๊ฐ ์๋ค
์ด ์ฌ์ง๋ค์ ํตํด ์ฝ๋๊ฐ ๋ด ์ผ๊ตด์ ํ์ตํ๊ณ ์์๋ณผ ์ ์๊ฒ ๋๋ค
ํ์ต ์์ฒด๋ ์ฝ๋๋ฅผ ํ ๋ฒ RUN ํด์ฃผ๋ ๊ฒ์ผ๋ก ๋๋๋ค
๊ทธ ์ ์ ํ์ต์ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ trainer ํด๋๋ฅผ ๋ง๋ ๋ค
๐ mkdir trainer
๊ทธ๋ฌ๊ณ ๋์ ๋ค์์ ์ฝ๋๋ฅผ ์์ฑํ๊ณ Run์ํฌ ๊ฒ์ธ๋ฐ
โโ ๋ง์ฐฌ๊ฐ์ง๋ก
haarcascade_frontalface_default.xml
ํ์ผ์ ~/FacialRecognitionProject ์ ๋ฃ์ด์ฃผ์
์ฝ๋ ๋ด์ ํ์ผ ๊ฒฝ๋ก๋ ๋ค์ ํ์ธํด๋ณผ ๊ฒ!
import cv2
import numpy as np
from PIL import Image
import os
# Path for face image database
path = 'dataset'
recognizer = cv2.face.LBPHFaceRecognizer_create()
detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml");
# function to get the images and label data
def getImagesAndLabels(path):
imagePaths = [os.path.join(path,f) for f in os.listdir(path)]
faceSamples=[]
ids = []
for imagePath in imagePaths:
PIL_img = Image.open(imagePath).convert('L') # convert it to grayscale
img_numpy = np.array(PIL_img,'uint8')
id = int(os.path.split(imagePath)[-1].split(".")[1])
faces = detector.detectMultiScale(img_numpy)
for (x,y,w,h) in faces:
faceSamples.append(img_numpy[y:y+h,x:x+w])
ids.append(id)
return faceSamples,ids
print ("\n [INFO] Training faces. It will take a few seconds. Wait ...")
faces,ids = getImagesAndLabels(path)
recognizer.train(faces, np.array(ids))
# Save the model into trainer/trainer.yml
recognizer.write('trainer/trainer.yml') # recognizer.save() worked on Mac, but not on Pi
# Print the numer of faces trained and end program
print("\n [INFO] {0} faces trained. Exiting Program".format(len(np.unique(ids))))
์ถ์ฒ: Marcelo ์์ ์จ ๋ธ๋ก๊ทธ
๋ง์ฝ PIL ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ค์น๋์ง ์์ ์ํ๋ผ ์ด ์ฝ๋์ ์ค๋ฅ๊ฐ ์๊ธด๋ค๋ฉด
๐ pip install pillow
๋ช ๋ ์ด๋ฅผ ํตํด ์ค์นํด์ฃผ๋๋ก ํ๋ค
์ฝ๋๊ฐ ๋ฌด๋ํ๊ฒ ์๋๋์๋ค๋ฉด trainer ํด๋์ ๋ญ๊ฐ๊ฐ ์๊ฒผ์ ๊ฒ์ด๋ค
๋์ถฉ ํ์ต๋ ๋ด์ฉ์ด ์ ์ฅ๋ ํ์ผ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋๊ฒ ๋ค
์ด์ ์ด๊ฑธ ํ ๋๋ก ํด์ ๋ด ์ผ๊ตด์ ์์๋ณด๋์ง ํ์ธํด์ผ ํ๋ค
ํ์ต๋ ๋ด์ฉ์ด ์ ์ฅ๋ ํ์ผ์ ๋ถ๋ฌ์์ ๊ทธ๊ฑธ ํ ๋๋ก ๋ด ์ผ๊ตด์ ์ธ์ํ๋ ๊ตฌ์กฐ๋ก ๋์๊ฐ๋ค
โก๏ธ ๊ณ์ํด์ ๋ฐ๋ณตํ๋ ๋ด์ฉ์ด์ง๋ง
haarcascade_frontalface_default.xml
์ด ๋์ ๊ฒฝ๋ก๋ฅผ ์ฃผ์ํ์
์๋์ ๋์ค๋ ์ฝ๋์ ์ด๋ฐ๋ถ ๋ณ์ ๋ถ๋ถ์ ๋ณด๋ฉด names๋ผ๋ ๋ฐฐ์ด์ด ๋ณด์ผ ๊ฒ์ด๋ค
๐งฉ 12) names = ['None', 'Marcelo', 'Paula', 'Ilza', 'Z', 'W']
์๊น์ ์ ์ฐ๋ฆฌ๋ id๋ฅผ '1'๋ก ์ค์ ํ์๋ค
๋ฐ๋ก ์ฌ๊ธฐ์ ์ฐ๊ธฐ ์ํจ์ด์๋ค
์ด ํ๋ก์ ํธ๋ฅผ ์งํํ๊ณ ๋ธ๋ก๊ทธ์ ์์ฑํ์ Marcelo์์ ์จ์ ์ด๋ฆ์ด
๋ฐฐ์ด์ 1๋ฒ ์ธ๋ฑ์ค์ ์ ์ฅ๋์ด ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค
๋๋ Marcelo์์ ์จ ๋๋ถ์ ์ด๋ฐ ์ฌ๋ฐ๋ ๊ฒฝํ์ ํ ์ ์๊ธด ํ์ง๋ง
๊ทธ๋ ๋ค๊ณ ๋ด๊ฐ Marcelo์์ ์จ๊ฐ ๋ ๊ฑด ์๋๊ธฐ ๋๋ฌธ์ user id ๋๋ ๋ฐฐ์ด์ ๋ด์ฉ์ ์์ ํด์ ๋ด ์ด๋ฆ์ ์ธ ๊ฑฐ์
import cv2
import numpy as np
import os
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('trainer/trainer.yml')
cascadePath = "haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(cascadePath);
font = cv2.FONT_HERSHEY_SIMPLEX
#iniciate id counter
id = 0
# names related to ids: example ==> Marcelo: id=1, etc
names = ['None', 'Marcelo', 'Paula', 'Ilza', 'Z', 'W']
# Initialize and start realtime video capture
cam = cv2.VideoCapture(0)
cam.set(3, 640) # set video widht
cam.set(4, 480) # set video height
# Define min window size to be recognized as a face
minW = 0.1*cam.get(3)
minH = 0.1*cam.get(4)
while True:
ret, img =cam.read()
img = cv2.flip(img, -1) # Flip vertically
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor = 1.2,
minNeighbors = 5,
minSize = (int(minW), int(minH)),
)
for(x,y,w,h) in faces:
cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
id, confidence = recognizer.predict(gray[y:y+h,x:x+w])
# Check if confidence is less them 100 ==> "0" is perfect match
if (confidence < 100):
id = names[id]
confidence = " {0}%".format(round(100 - confidence))
else:
id = "unknown"
confidence = " {0}%".format(round(100 - confidence))
cv2.putText(img, str(id), (x+5,y-5), font, 1, (255,255,255), 2)
cv2.putText(img, str(confidence), (x+5,y+h-5), font, 1, (255,255,0), 1)
cv2.imshow('camera',img)
k = cv2.waitKey(10) & 0xff # Press 'ESC' for exiting video
if k == 27:
break
# Do a bit of cleanup
print("\n [INFO] Exiting Program and cleanup stuff")
cam.release()
cv2.destroyAllWindows()
์ถ์ฒ: Marcelo ์์ ์จ ๋ธ๋ก๊ทธ
์ด๊ฑธ ๋๋ ค ๋ณด๋ฉด
๋ฎ์ ์์น์ง๋ง ๊ณ ๋ง๊ฒ๋ ์์์ค๋ค
์ ๋ฉด์ผ๋ก ์ดฌ์์ ๋ง์ด ํ๋๋ฐ ์๋ชจ์ต์ด ๋์์ ๊ทธ๋ฐ ๊ฒ์ผ ์๋ ์๊ณ
์ฒ์ dataset์ ๋ง๋ค ๋ ์ ๋ฉด์ด ์ ๋๋ก ์กํ์ง ์์์ ์๋ ์๊ฒ ๋ค
์๋ฌดํผ Marcelo์์ ์จ ๋์ ๋๋ ๋ด ์ผ๊ตด์ ์ธ์ํ๋ ์์คํ ์ ๊ตฌ์ฑํด๋ณผ ์ ์์๋ค
๊ฝค ์ฌ๋ฐ์๋ค
๋ผ์ฆ๋ฒ ๋ฆฌ ํ์ด์ ์ฑ๋ฅ์ด ์กฐ๊ธ ๋ ์ข์๋ค๋ฉด
์ฌ๋ฌ ์ธ์ ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉํด ๋ณผ ์ ์์๋๋ฐ ์ข ์์ฝ๋ค
์๋ฌดํผ Marcelo์์ ์จ์๊ฒ ๊ฒฝ์๋ฅผ ํํ๋ฉฐ ์ค์ต ๋์ด๋ค
๋