코딩일지/TIL: Today I Learned

20221129 TIL

야언 2022. 11. 29. 10:32

오늘의 한 일

  • 협력사 특강
  • 지금까지 했던 프로젝트 총정리

 

프로젝트 총정리

 

 

 

 

project 1 - Spartagram

 

https://github.com/jihyun-cho-0/spartagram

 

GitHub - jihyun-cho-0/spartagram: project-1. 스파르타그램

project-1. 스파르타그램. Contribute to jihyun-cho-0/spartagram development by creating an account on GitHub.

github.com

 

장고 템플릿을 이용한 회원가입, 로그인, 포스팅, 좋아요와 북마크 기능등 sns에 필요한 기본 기능 구현, runserver를 이용한 AWS EC2 환경 배포 등 전반 수행

 


 

project 2 - PetDictionary

 

https://github.com/Taeeun99/sparta_PetDictionary_2L3J_project2

 

GitHub - Taeeun99/sparta_PetDictionary_2L3J_project2: 사물인식 팀 프로젝트

사물인식 팀 프로젝트 . Contribute to Taeeun99/sparta_PetDictionary_2L3J_project2 development by creating an account on GitHub.

github.com

머신러닝을 통한 사물인식(YOLOv5 모델)

PyTorch를 이용하여 Yolov5 모델로 Oxford Pets datasets를 학습시킨 pt모델을 적용시켜 사용자가 입력한 이미지에 포함된 개/고양이 객체를 식별하기 (종과 품종명) (담당)

결과의 품종명을 활용하여 네이버에 검색요청을 보내 결과를 크롤링(bs4 모듈 이용), 원하는 정보들만 정제해 출력

결과 만족도를 yes/no의 형태로 받아 정확도 출력

원하는 결과가 아닐 시, 사용자가 원했던 답을 입력받아 이미지 모델에 저장, 향후 이미지 추가 학습에 활용 예정


 

project 3 - NWRS (Naver Webtoon Recommend System)

 

backend : https://github.com/A7-Lucky/NWRS

 

GitHub - A7-Lucky/NWRS: NaverWebtoonRecommendSystem(Backend)

NaverWebtoonRecommendSystem(Backend). Contribute to A7-Lucky/NWRS development by creating an account on GitHub.

github.com

 

frontend : https://github.com/A7-Lucky/NWRS_Front

 

GitHub - A7-Lucky/NWRS_Front: NaverWebtoonRecommendSystem(Front)

NaverWebtoonRecommendSystem(Front). Contribute to A7-Lucky/NWRS_Front development by creating an account on GitHub.

github.com

 

jwt 토큰 인증방식의 회원가입, 로그인 시스템 구현

pandas와 numpy를 이용, 준비된 웹툰 리스트 데이터(csv)와 유저간 평점 리스트 데이터(csv)를 웹툰id기준으로 묶어

sklearn의 코사인 유사도(cosine_similarity)를 이용해 아이템 기반 필터링을 거쳐 해당 웹툰과 유사도가 가장 높은 웹툰을 추천해주는 추천 시스템 알고리즘 담당

drf search 모듈을 활용한 검색 시스템 담당


 

project 4 - OilPainting, 油畵(유화)

 

backend : https://github.com/A7-Lucky/OilPainting 

 

GitHub - A7-Lucky/OilPainting

Contribute to A7-Lucky/OilPainting development by creating an account on GitHub.

github.com

 

frontend : https://github.com/A7-Lucky/OilPainting_Front

 

GitHub - A7-Lucky/OilPainting_Front

Contribute to A7-Lucky/OilPainting_Front development by creating an account on GitHub.

github.com

 

jwt 토큰 인증방식의 회원가입, 로그인 시스템 구현

openCV의 DNN(Deep Nural Network) 모듈을 활용해 미리 학습된 스타일 모델을 불러와 사용자가 입력한 이미지에 스타일을 입히는 알고리즘 (담당)

drf pagination을 사용한 페이지네이션 기능 구현 (담당)

 

 


 

기억에 남는 COMMIT

 

PetDictionary - 처음으로 머신러닝 모델을 웹서비스 내에 적용시켜서 업로드한 커밋

 

OilPainting - PR 컨벤션과 커밋 컨벤션을 모두 지켜가면서 쓴 만족스러운 커밋, 처음 시도해보는 페이지네이션 작업을 성                      공적으로 마무리지어 더욱 좋았다.

 

 


기억에 남는 TroubleShooting

 

  • 머신러닝 모델을 돌리면서 이미지 변환에 대해 고민하게 된 점

단순하게 이미지를 컴퓨터 내에서 돌리는 것이 아니라 웹 서버에서 받고, 변환하고, 올리는 과정을 동반하기 때문에 이미지의 형식에 대해 많이 고민하게 되었다.

 

PetDictionary 프로젝트에서는 이미지 모델을 base64필드로 잡고 이미지를 base64로 인코딩해 저장, 디코딩하며 보여주는 방식을 사용해보았고

 

NWRS 프로젝트에서는 프로필 모델에서 프로필 이미지를 ImageField로 만들어 사용자의 이미지를 그대로 받아오고 그대로 보내주는 방식을 사용하려 해보았으나 프론트엔드 부분에서 실패했다

 

油畵(유화) 프로젝트에서는 사용자가 입력한 이미지를 받아 openCV dnn모듈로 추론을 돌리는 과정중에 input한 이미지에 대한 imread오류가 생겨 이미지를 npstring으로 변환하는 과정을 집어넣어 해결하였다. 

 

 

  • 페이지네이션 구현 - 프론트엔드 내에서 정보 정제하기

프론트엔드 내에서 페이지네이션 viewset으로 get요청을 보냈을 시 받는 데이터를 정제해나가는 과정이 재미있었다.

viewset에 get요청을 보내서 받은 데이터

받은 데이터에서 results만 빼내서 원하는 아티클에 대한 정보만 받기

 

최종적으로는 페이지네이션바의 구성을 위해 데이터의 count 수를 한 페이지당 수로 나눠

Math.ceil 함수를 사용해 소숫점이 있을 시 값을 올려 정수형으로 만들어 총 페이지 수를 만들고

temp_html형식으로 각 페이지에 해당하는 수를 해당 페이지로 이동하는 하이퍼링크를 걸어 

페이지네이션 바에append 형식으로 생성해내는 함수까지 구현했다.

 

index.js

// 아티클 리스트 가져오기 (페이지네이션 적용)  //
window.onload = async function loadArticleList() {
  viewset = await getArticleList();
  // 아티클 받아오기 //
  articles = viewset["results"];
  // 페이지 수 가져오기 // 
  pages = viewset['count']
  pages = Math.ceil(Number(pages)/3)

  // 아티클 생성하기 //
  const article_list = document.getElementById("article_list");

  articles.forEach((article) => {
    // 사진만 들어가는 버전
    const newimage = document.createElement("img");

    newimage.setAttribute("src", `${backend_base_url}/${article.image}`);
    newimage.setAttribute("id", article.id);

    newimage.setAttribute("onclick", "ArticleDetail(this.id)");

    article_list.appendChild(newimage);

    // 제목+내용까지
    // const newuser = document.createElement("ol")
    // const newtitle = document.createElement("ol")
    // newtitle.setAttribute("id", article.id)
    // newuser.innerText = article.user
    // newtitle.innerText = article.title
    // newtitle.setAttribute("onclick", "ArticleDetail(this.id)")
    // article_list.appendChild(newuser)
    // article_list.appendChild(newtitle)
  });

  // 페이지네이션 페이지 생성하기 //
  for (let i = 1; i < pages+1; i++) {
    let temp_html = `
    <li class="page-item"><a class="page-link" href="?page=${i}">${i}</a></li>
    `
    
    $('#pagination').append(temp_html)
  }
};

 

 

 

 


협업을 하면서 의견차이를 극복한 방법

 

 

내일배움캠프 멤버들 모두 코딩에 대해서 새내기들이고, 각자 찾은 방법들이 다르고 이해한 정도가 다르기때문에 활발히 의견을 교류하면서 어떤 방식이 더 나을지 함께 찾아가는 느낌으로 협업을 진행했다

 


개발을 하면서 경험했던 내용들 + 해결방법

 

 

이미지를 모델을 돌리면서 변형시키는 작업을 굉장히 많이 했는데

그냥 pc환경에서는 imread로 편하게 읽고 변형 및 저장할 수 있었던것을 웹에서 구현하려고 하니 받는 그대로 이용할 수가 없어서

PetDictionary 프로젝트때는 base64로 인코딩해 base64Field로 이미지 업로드 / 유화 프로젝트때는 numpy 모듈의 formstring 함수를 통해 변환시켜 사용하는 것으로 해결

 

Petdictionary - input/inference.py

import torch
from PIL import Image
import base64
import io
from django.shortcuts import render, redirect
from django.views.generic import ListView, TemplateView






def inference(img):
    model = torch.hub.load('ultralytics/yolov5', 'custom', path='models_train/best.pt', force_reload=True)  # 커스텀 학습 모델 사용
    img = Image.open(img)
    

    results = model(img, size=640)  # inference 추론
    result = results.pandas().xyxy[0].to_numpy()  # 종-품명 추출하기 위해 numpy array

    if len(result) != 0:

        keyword = result[0][6]
        search_link = "https://www.google.com/search?q="+keyword
        species = keyword[:3]  # 종
        breed = keyword[4:]  # 품명
        breed = breed.replace('_'," ")
        results.ims  # array of original images (as np array) passed to model for inference 원본 이미지(np 배열) 추론모델로 보내기
        results.render()  # updates results.imgs with boxes and labels  이미지에 박스와 라벨 붙이기
        for img in results.ims:  # 'JpegImageFile' -> bytes-like object
            buffered = io.BytesIO()
            img_base64 = Image.fromarray(img)
            img_base64.save(buffered, format="JPEG")
            encoded_img_data = base64.b64encode(buffered.getvalue()).decode(
                'utf-8')  # base64 encoded image with results
            
        
        outputs_data = {
            'img_data' : encoded_img_data,
            'species' : species,
            'breed' : breed,
            'search_link' : search_link,
            }
        
        return outputs_data
    else:
        return 1

 

 

 

Oilpainting - articles/utils.py

from datetime import datetime
import cv2
import numpy as np
import os


def inference(img_input, style):
    # 이미지 불러오기
    npimg = np.fromstring(img_input, np.uint8)
    input_img = cv2.imdecode(npimg, cv2.IMREAD_COLOR)
    style = cv2.dnn.readNetFromTorch(f"articles/models/{style}")

    # 전처리 코드
    h, w, c = input_img.shape
    input_img = cv2.resize(input_img, dsize=(500, int(h / w * 500)))
    MEAN_VALUE = [103.939, 116.779, 123.680]
    blob = cv2.dnn.blobFromImage(input_img, mean=MEAN_VALUE)

    # 결과 추론하기
    style.setInput(blob)
    output = style.forward()
    # 전처리한 이미지(blob)를 모델에 넣고 추론, output 변수에 추론한 결과 저장(forward)

    # 결과 후처리
    output = output.squeeze().transpose((1, 2, 0))
    output += MEAN_VALUE
    output = np.clip(output, 0, 255)
    output = output.astype("uint8")

    # 폴더가 없을 시 생성
    if not os.path.exists("media/articles"):
        os.makedirs("media/articles")

    # 생성시간을 이름으로 저장
    time = datetime.now().strftime("%y%m%d%H%M%S")
    cv2.imwrite(f"media/articles/{time}.jpeg", output)
    result = f"media/articles/{time}.jpeg"

    return