상세 컨텐츠

본문 제목

[K-DIGITAL] 파이널프로젝트. BEERCRAFT 맥주 추천 서비스(4) openCV YOLO 이용한 이미지 분석

PYTHON/K-DIGITAL

by ranlan 2021. 8. 11. 10:48

본문

728x90

 

(3)은 코사인 유사도 기반 새로운 맥주에 대한 평점 예측 관련이지만 내가 이해를 다 못하였기에 패스(깃 참고) 🥺

[GITHUB] https://github.com/ijo0r98/likelion-kdigital/tree/main/final-project > 3. 새로운 맥주에 대한 별점 예측.ipynb

 


 

 

https://github.com/ijo0r98/likelion-kdigital/tree/main/final-project > 4-1. YOLO 맥주 이미지데이터 분석.ipynb

 

GitHub - ijo0r98/likelion-kdigital: [국비교육] AI 인재 양성 프로그램

[국비교육] AI 인재 양성 프로그램. Contribute to ijo0r98/likelion-kdigital development by creating an account on GitHub.

github.com

 

내가 시도하려했던 방식은 직접 이미지를 크롤링해서 모으고 학습시키는 방법이였다

(모델링을 처음부터 하기 힘들거같아서 전이학습도 함께 고려중이였삼)

 

강사님께서 많은 시간이 필요할것이니 카테고리를 10개정도로 줄이고 각 카테고리마다 최소 100장의 사진을 모으라고 하셨다.

그래서 난 65개의 맥주 종류 중 3~5개 정도 선택하여 먼저 이미지 데이터를 100장씩 모았다.!

대부분 이미지에 맥주만 있는게 아니라 뒤의 배경도 있고 여러 다른 물체도 함께 포함되어 있어

이를 제거하기 위해 openCV YOLO 물체 감지를 이용하였고 bottle이나 can 이미지만 따로 추출 후 저장하였다.

이렇게 노이즈 제거된 맥주 이미지들로만 학습을 시킬 예정이였다.

 

 

 

구글 이미지 검색 크롤링

크롤링은 selenium 이용

import os
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time

크롬 드라이버 준비

driver = webdriver.Chrome(r'/Users/juran/tool/chromedriver') # chromedriver 위치

이미지를 모을 맥주 리스트

beer_list = ['fitz super clear', 'TSINGTAO WHEAT BEER', 'Kozel Dark 10', 'OB premier pilsner', 'Hoegarden']

모은 이미지를 각 맥주명으로 만들어진 폴더 안에 저장

# image/beer_name
def createFolder(directory):
    try:
        if not os.path.exists('image/' + directory):
            os.makedirs('image/' + directory)
    except OSError:
        print ('Error: Creating directory. ' + directory)

구글 이미지 검색 크롤링

def crawling(keyword):
    url = 'https://www.google.co.kr/imghp?hl=ko'
    driver.get(url)
    
    # 검색 정확도를 높이기 위해 맥주명 뒤에 bottle 추가
    driver.find_element_by_xpath('//*[@id="sbtc"]/div/div[2]/input').send_keys(keyword + ' bottle')
    driver.find_element_by_xpath('//*[@id="sbtc"]/button').click()
    
    body = driver.find_element_by_tag_name("body")

    # 스크롤 내림
    # 구글 이미지검색에서는 스크롤을 내려야 더 많은 이미지가 보임
    for i in range(10):
        body.send_keys(Keys.PAGE_DOWN)
        time.sleep(0.1)
    
    # 폴더 생성
    createFolder(keyword)
    
    links=[]
    images = driver.find_elements_by_css_selector("img.rg_i.Q4LuWd")

    # 이미지 url
    for image in images:
        if image.get_attribute('src')!=None:
            links.append(image.get_attribute('src'))
    
    for k,i in enumerate(links[:120]): # 120개의 이미지 다운로드
        url = i
        start = time.time()
        urllib.request.urlretrieve(i, "./image/" + keyword +'/' +keyword+"_"+str(k)+".jpg")
        print(str(k+1)+'/'+str(len(links))+' '+keyword+' 다운로드 중....... Download time : '+str(time.time() - start)[:5]+' 초')
        print(keyword + ' ---다운로드 완료---')
        time.sleep(1)

각 맥주마다 검색 후 이미지 저장

for beer in beer_list:
    crawling(beer)

실행 결과

image/
image/beer/

 

 

YOLO (You Only Look Once)

물체 감지를 위한 CNN 기반의 물체 인식 알고리즘

 

YOLO 사용을 위해 딥러닝 프레임워크가 필요하여 openCV를 함께 사용

import cv2
import numpy as np

알고리즘 로드

yolo/

net = cv2.dnn.readNet("yolo/yolov3.weights", "yolo/yolov3.cfg")
classes = []

with open("yolo/coco.names", "r") as f:
    classes = [line.strip() for line in f.readlines()]

layer_names = net.getLayerNames()
output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
colors = np.random.uniform(0, 255, size=(len(classes), 3))

이미지 가져오기

img_ttl = 'Kozel Dark 10_19'
img_path = "image/Kozel Dark 10/" + img_ttl + ".jpg"
img = cv2.imread(img_path)
height, width, channels = img.shape

물체 감지

blob = cv2.dnn.blobFromImage(img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)

물체 정보 표시

class_ids = []
confidences = []
boxes = []
for out in outs:
    for detection in out:
        scores = detection[5:]
        class_id = np.argmax(scores)
        confidence = scores[class_id]
        if confidence > 0.5:
            # Object detected
            center_x = int(detection[0] * width)
            center_y = int(detection[1] * height)
            w = int(detection[2] * width)
            h = int(detection[3] * height)
            # 좌표
            x = int(center_x - w / 2)
            y = int(center_y - h / 2)
            boxes.append([x, y, w, h])
            confidences.append(float(confidence))
            class_ids.append(class_id)

Non maximum suppresion 노이즈 제거(같은 물체에 대한 박스가 많은 것 제거)

indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)

새로운 윈도우에서 이미지 보여줌

font = cv2.FONT_HERSHEY_PLAIN
for i in range(len(boxes)):
    if i in indexes:
        x, y, w, h = boxes[i]
        label = str(classes[class_ids[i]])
        color = colors[i]
        # 물체 사각형
        cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)
        # 물체명
        cv2.putText(img, label, (x, y + 30), font, 3, color, 3)
cv2.imshow("Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 종료 - 이미지 윈도우에서 ctrl+c

감지된 물체 좌표들 확인

for i in range(len(boxes)):
    if i in indexes:
        x, y, w, h = boxes[i]
        print('x {} / y {} / x+w {} / y+h {}'.format(x, y, x + w, y + h))

해당 좌표들을 이용하여 이미지 자르기 & 저장

from PIL import Image

for i in range(len(boxes)):
    if i in indexes:
        x, y, w, h = boxes[i]
        croppedImage = image.crop((x, y, x + w, y + h))
        print("잘려진 사진 크기 :", croppedImage.size)
        croppedImage.save("image/Kozel Dark 10/" + img_ttl + '_' + str(i) + ".jpg")

원본 이미지(물체 감지 전) 삭제

img_path = "image/Kozel Dark 10/" + img_ttl + ".jpg"
os.remove(img_path)

 


 

다른 팀원분께서 정리해주신 pytorch와 Flask는 좀 더 공부한 뒤에 작성하기로(이것도 깃 참고) 👋🏻

[GITHUB] https://github.com/ijo0r98/likelion-kdigital/tree/main/final-project > 4-2. PyTorch 전이학습 이용한 맥주 이미지 분류.ipynb

 

GitHub - ijo0r98/likelion-kdigital: [국비교육] AI 인재 양성 프로그램

[국비교육] AI 인재 양성 프로그램. Contribute to ijo0r98/likelion-kdigital development by creating an account on GitHub.

github.com

 

728x90

관련글 더보기

댓글 영역