22.10.13(목) Today I Learned

정형빈·2022년 10월 13일
0

TIL

목록 보기
27/71

10/13 오늘의 시간표

09:00 ~ 10:00 [테스트] 쪽지시험
10:00 ~ 11:00 [원격] 실전 머신러닝 적용
11:00 ~ 12:00 [원격] 실전 머신러닝 적용
12:00 ~ 13:00 [원격] 실전 머신러닝 적용
13:00 ~ 14:00 점심식사
14:00 ~ 15:00 [원격] 실전 머신러닝 적용
15:00 ~ 16:00 [원격] 실전 머신러닝 적용
16:00 ~ 17:00 [원격] 실전 머신러닝 적용
17:00 ~ 18:00 [원격] 실전 머신러닝 적용
18:00 ~ 19:00 저녁식사
19:00 ~ 20:00 [원격] 실전 머신러닝 적용
20:00 ~ 21:00 [원격] 실전 머신러닝 적용

오늘도 어제와 마찬가지로 실전 머신러닝 적용 원격강의날이었지만 오전에 쪽지시험이 있다는 것이 달랐다.

쪽지시험

- opencv 활용

  1. 위 이미지를 다운받아 저장하세요
  2. opencv 로 이미지를 읽고 이미지의 가로, 세로가 각 몇 pixel 인지 구하세요
    1. (세로, 가로)
  3. 이미지에서 사람을 찾아 하얀색으로 네모를 그려서 result1.png 로 저장하세요
  4. 이미지에서 사람들을 잘라 people1.png, people2.png… 로 저장하세요
  5. 코드와 이미지를 git에 업로드하고 해당 repository를 공유해주세요

어제 특강에서 알려주신 opencv와 torch의 사물인식 기능을 활용하는 문제였다.
어제 특강을 통해 필요한 패키지 파일들은 미리 다 받아놓았기 때문에 바로 진행하면 되는 문제였는데 이미지 파일 경로설정에서 오류가 발생해 시간을 많이 잡아먹고 시작했다. 다행히 이미지 파일의 이름에 내가 특수문자를 넣었기 때문에 발생한 오류임을 알게되었고 즉시 수정하여 다음으로 넘어갈 수 있었다.

import torch
import cv2

model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
imgs = ['10.13test\photo.jpg']

results = model(imgs)

tmp_img = cv2.imread("10.13test\photo.jpg")

문제를 풀 수 있도록 다음과 같이 기본세팅을 해 두고 본격적으로 작업에 들어갔다.

가로, 세로가 몇 px인지 구하기 위한 방법으로는 여러가지가 있지만 나는 .shape 함수를 활용하였다. .shape 함수는 해당 도형의 높이(세로),넓이(가로),채널 값을 구하는 함수인데 여기에서 나는 채널 값은 필요없고 세로, 가로의 값만 구하면 되기 때문에 인덱스 설정을 통해 앞의 두 값만 가져왔다.

print('세로:', tmp_img.shape[0], 'px', '가로:', tmp_img.shape[1], 'px')

다음으로 해야 할 것은 이미지에서 사람을 찾아 하얀색 네모로 표시하는 것인데 이것은 어제 특강에서 배운 사물인식 기능을 활용하였다.

cv2.rectangle(tmp_img, (int(results.xyxy[0][0][0].item()), int(results.xyxy[0][0][1].item())), (int(results.xyxy[0][0][2].item()), int(results.xyxy[0][0][3].item())), (255,255,255))
cv2.rectangle(tmp_img, (int(results.xyxy[0][1][0].item()), int(results.xyxy[0][1][1].item())), (int(results.xyxy[0][1][2].item()), int(results.xyxy[0][1][3].item())), (255,255,255))
cv2.rectangle(tmp_img, (int(results.xyxy[0][2][0].item()), int(results.xyxy[0][2][1].item())), (int(results.xyxy[0][2][2].item()), int(results.xyxy[0][2][3].item())), (255,255,255))
cv2.rectangle(tmp_img, (int(results.xyxy[0][3][0].item()), int(results.xyxy[0][3][1].item())), (int(results.xyxy[0][3][2].item()), int(results.xyxy[0][3][3].item())), (255,255,255))
cv2.rectangle(tmp_img, (int(results.xyxy[0][4][0].item()), int(results.xyxy[0][4][1].item())), (int(results.xyxy[0][4][2].item()), int(results.xyxy[0][4][3].item())), (255,255,255))
cv2.imwrite('result1.png', tmp_img)

opencv의 rectangle을 활욯하여 tmp_img안에서 class가 사람으로 분류되는 값 5개에 사각형을 입히고 그 색은 흰색(255,255,255)로 지정하였고 결과물을 result1.png에 저장하도록 했다.

마지막으로 각 사람들의 이미지만 따로 잘라내 people1~5.png에 저장하게 설정하면 쪽지시험은 완료인데 이 부분은 어제 배운 내용안에 포함되지 않아 해결을 위해 구글링을 해 보았다.

opencv에서 이미지파일을 잘라내려면
이미지파일[잘라낼 x축의 범위, 잘라낼 y축의 범위] 인데 이 x축 y축의 범위를 알 필요가 있었다.

print(tep_img.pandas().xyxy[0])를 통해 찾아보니

         xmin        ymin        xmax        ymax  confidence  class    name
0  437.679291  163.035065  631.465515  806.554688    0.919314      0  person
1  623.300171  155.730515  790.887573  806.233215    0.906667      0  person
2  763.604370  131.484940  950.967285  816.322571    0.898564      0  person
3   99.867783  106.271996  314.064270  823.680542    0.879437      0  person
4  271.601868  175.287766  458.354980  803.830566    0.856607      0  person
5  513.423645  272.386627  551.081421  458.215179    0.361376     27     tie

이라는 범위가 나왔고 여기서 5번째 index는 class가 27번 tie이기 때문에 필요가 없으므로 0부터 4번까지만 사용하게 될 것이다.
x축의 범위 = xmin:xmax이고 y축의 범위=ymin:ymax이기 때문에 이를 대입해보면

people1 = tmp_img[int(results.xyxy[0][0][0].item()):int(results.xyxy[0][0][2].item()), int(results.xyxy[0][0][1].item()):int(results.xyxy[0][0][3].item())].copy()
cv2.imwrite('people1.png', people1)
people2 = tmp_img[int(results.xyxy[0][1][0].item()):int(results.xyxy[0][1][2].item()), int(results.xyxy[0][1][1].item()):int(results.xyxy[0][1][3].item())].copy()
cv2.imwrite('people2.png', people2)
people3 = tmp_img[int(results.xyxy[0][2][0].item()):int(results.xyxy[0][2][2].item()), int(results.xyxy[0][2][1].item()):int(results.xyxy[0][2][3].item())].copy()
cv2.imwrite('people3.png', people3)
people4 = tmp_img[int(results.xyxy[0][3][0].item()):int(results.xyxy[0][3][2].item()), int(results.xyxy[0][3][1].item()):int(results.xyxy[0][3][3].item())].copy()
cv2.imwrite('people4.png', people4)
people5 = tmp_img[int(results.xyxy[0][4][0].item()):int(results.xyxy[0][4][2].item()), int(results.xyxy[0][4][1].item()):int(results.xyxy[0][4][3].item())].copy()
cv2.imwrite('people5.png', people5)

그런데 막상 작성한 코드로 나온 결과물을 확인해보니 원하는 사람부분이 잘린게 아니라 엉뚱하게 잘려 있었다. 내가 코드작성을 잘못했나 싶어서 여러번 새로 작성해보고 범위지정도 다시해보고 구글링도 새로 해보았지만 해결이 되지않아 결국 튜터님께 여쭤보는게 가장 빠르겠다는 생각에 점심시간이 끝나자마자 튜터님께 질문을 했다.

늘 그랬듯이 해결법은 아주 쉬운것이었는데 x축 y축 순서로 범위를 지정해 둔 것을 y축 x축 순서로 범위를 지정했더니 바로 해결이 되었다. opencv에서는 y축 즉 높이를 먼저 두고 넓이를 두어야 하는 것이다. 일반적으로는 x축이 먼저오는 경우가 많다보니 이런 실수를 하고 만 것이다. 덕분에 이것만 수정하니 금방 해결되었다.

people1 = tmp_img[int(results.xyxy[0][0][1].item()):int(results.xyxy[0][0][3].item()), int(results.xyxy[0][0][0].item()):int(results.xyxy[0][0][2].item())].copy()
cv2.imwrite('people1.png', people1)
people2 = tmp_img[int(results.xyxy[0][1][1].item()):int(results.xyxy[0][1][3].item()), int(results.xyxy[0][1][0].item()):int(results.xyxy[0][1][2].item())].copy()
cv2.imwrite('people2.png', people2)
people3 = tmp_img[int(results.xyxy[0][2][1].item()):int(results.xyxy[0][2][3].item()), int(results.xyxy[0][2][0].item()):int(results.xyxy[0][2][2].item())].copy()
cv2.imwrite('people3.png', people3)
people4 = tmp_img[int(results.xyxy[0][3][1].item()):int(results.xyxy[0][3][3].item()), int(results.xyxy[0][3][0].item()):int(results.xyxy[0][3][2].item())].copy()
cv2.imwrite('people4.png', people4)
people5 = tmp_img[int(results.xyxy[0][4][1].item()):int(results.xyxy[0][4][3].item()), int(results.xyxy[0][4][0].item()):int(results.xyxy[0][4][2].item())].copy()
cv2.imwrite('people5.png', people5)

대신 이렇게 하니까 앞에 만들어 둔 흰색 네모들이 잘라진 이미지에 나와 거슬렸다.

tmp_img = cv2.imread("10.13test\photo.jpg")
people1 = tmp_img[int(results.xyxy[0][0][1].item()):int(results.xyxy[0][0][3].item()), int(results.xyxy[0][0][0].item()):int(results.xyxy[0][0][2].item())].copy()
cv2.imwrite('people1.png', people1)
people2 = tmp_img[int(results.xyxy[0][1][1].item()):int(results.xyxy[0][1][3].item()), int(results.xyxy[0][1][0].item()):int(results.xyxy[0][1][2].item())].copy()
cv2.imwrite('people2.png', people2)
people3 = tmp_img[int(results.xyxy[0][2][1].item()):int(results.xyxy[0][2][3].item()), int(results.xyxy[0][2][0].item()):int(results.xyxy[0][2][2].item())].copy()
cv2.imwrite('people3.png', people3)
people4 = tmp_img[int(results.xyxy[0][3][1].item()):int(results.xyxy[0][3][3].item()), int(results.xyxy[0][3][0].item()):int(results.xyxy[0][3][2].item())].copy()
cv2.imwrite('people4.png', people4)
people5 = tmp_img[int(results.xyxy[0][4][1].item()):int(results.xyxy[0][4][3].item()), int(results.xyxy[0][4][0].item()):int(results.xyxy[0][4][2].item())].copy()
cv2.imwrite('people5.png', people5)

그냥 tmp_img파일을 흰 네모가 그려지기 전인 새걸로 가져와서 이를 해결했다.

이렇게 해서 나온 결과물을 GitHub에 올리고나니 오늘의 쪽지시험내용이 끝이났다.
10.13 쪽지시험 결과물 GitHub 링크

원래는 1시간짜리 쪽지시험인데 시간안에 해결하지 못하고 오전시간을 전부 소모해버렸다. 시간안에 한번에 해결한 분들은 이걸 어떻게 한시간안에 한건지 정말 대단하다고 생각이 들었다.

머신러닝 적용 원격 강의

- 4주차

  • 신경망
    • 신경망을 구성하는 방법은 정말 여러가지가 있는데, 이 중 가장 많이 쓰이는 것은 합성곱 신경망(CNN), 순환 신경망(RNN), 생성적 적대 신경망(GAN)이다.
  • 전이학습
    • 이미 학습된 모델을 비슷한 문제를 푸는데 다시 사용하는 것
  • 합성곱(convolution) : 하나의 함수와 또 다른 함수를 반전 이동한 값을 곱한 다음, 구간에 대해 적분하여 새로운 함수를 구하는 연산자이다.
    • 이러한 합성곱 연산을 사용하는 인공신경망(Artificial Neural Network, ANN) 중의 하나가 합성곱 신경망이다.

오늘 하루를 마치며

오늘도 하루종일 열심히 머신러닝을 배웠는데 머리가 채워지고는 있지만 이해가 되고있냐라고 묻는다면 아직도 물음표이다. 그래도 쪽지시험을 통해 시간과 노력을 부으면 할 수 있다는 것을 알게되었으니 나쁘지않은 하루였다고 생각한다.

profile
스파르타 내일배움캠프 3기 수강생 정형빈

0개의 댓글