OpenCV를 이용한 이미지 전처리 윤곽선 찾기

프로젝트명 :

치킨카운터

카테고리 :

개발 > 이미지처리

기간 :

2021.11 – 2021.12

개발범위 :

이미지 처리를 이용한 저울 위 닭 개수 카운팅

개요 :

전공을 공부하면서 리빙랩을 통해 팀프로젝트를 진행하게 되었는데 주제로 닭장 내 저울 위에 있는 닭의 개수를 세는 것을 자동화해주는 것으로 정하고 각지의 아이디어를 가지고 공부하고 구현해보는 시간을 갖게 되었습니다.

적용 기술:

개발 툴 : Pycham
언어 : Python
라이브러리 : OpenCV, numpy

기타

본 프로젝트를 진행하면서 요즘 이슈가 되고 있는 영상 인식 기술, 인공지능 분야에 이미지 전처리 기술이 많이 중요함을 알게되었습니다. 사전 데이터의 품질에 따라 인식률이 달라지기 때문에 데이터를 얼마나 잘 처리하느냐에 따라 결과가 달라질 수 있음을 알 수 있었습니다.

전체 코드

import numpy as np
import cv2
import os

outline_w = 950

def im_trim(img, x, y, w, h):
    imgtrim = img[y: y + h, x: x + w]
    return imgtrim


def show_image(name, image):
    cv2.imshow(name, image)
    cv2.waitKey()
    cv2.destroyAllWindows()
 
def mopology(image):
    # 포폴로지
    structuringElement = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

    imgTopHat = cv2.morphologyEx(image, cv2.MORPH_TOPHAT, structuringElement)
    imgBlackHat = cv2.morphologyEx(image, cv2.MORPH_BLACKHAT, structuringElement)

    imgGrayscalePlusTopHat = cv2.add(image, imgTopHat)
    subtract = cv2.subtract(imgGrayscalePlusTopHat, imgBlackHat)
    # show_image('subtract', subtract)
    return subtract


def denoise(image):
    return cv2.fastNlMeansDenoisingColored(image, None, 10, 10, 7, 21)


def gray_scale(image):
    return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)


def threshold_image(image):
    return cv2.threshold(image, 110, 255, cv2.THRESH_BINARY * cv2.THRESH_OTSU)[1]

def open_closing(image):
    kernel = np.ones((7, 7), np.uint8)
    opening = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
    # show_image('opening',opening)
    closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel)
    return closing

def find(file):
    cnt = 0
    img = cv2.imread('img/' + file)
    w, h, _ = img.shape

    #임으로 저울 부분 Crop
    result = im_trim(img, outline_w + 30, outline_w -50, w - (outline_w + 300), 250)
    # show_image('result',result)

    #노이즈 제거
    denoiseimg = result
    for i in range(2):
        denoiseimg = denoise(denoiseimg)
    # show_image('denoiseimg',denoiseimg)

    #확대축소
    oc_img = open_closing(denoiseimg)
    # show_image('oc_img', oc_img)

    #색상 영역 추출
    mark = np.copy(result)
    blue_threshold = 130
    green_threshold = 130
    red_threshold = 130
    bgr_threshold = [blue_threshold, green_threshold, red_threshold]
    thresholds = (oc_img[:, :, 0] < bgr_threshold[0]) \
                 | (oc_img[:, :, 1] < bgr_threshold[1]) \
                 | (oc_img[:, :, 2] < bgr_threshold[2])
    mark[thresholds] = [0, 0, 0]
    # show_image('mark', mark)

    #RGB TO HSV
    src_hsv = cv2.cvtColor(mark, cv2.COLOR_BGR2HSV)
    # show_image('src_hsv', src_hsv)

    h, s, v = cv2.split(src_hsv)
    # show_image('V', v)
    #경계선 찾기
    thresimg = threshold_image(v)
    # show_image('thresimg', thresimg)

    #윤곽선 그리기
    color = (92, 163, 95)
    h, w = result.shape[:2]
    findMethod = cv2.RETR_LIST
    method =  cv2.CHAIN_APPROX_SIMPLE
    contours, hierarchy = cv2.findContours(thresimg, findMethod,method)

    # 윤곽선 그리기
    dst = np.zeros((h, w, 3), np.uint8)

    for i in range(len(contours)):
        #둘레
        area = cv2.contourArea(contours[i])
        # print(area)
        # cv2.drawContours(dst, contours, i, color, 0, cv2.LINE_AA)
        #
        # show_image('dst',dst)
        #일정 둘레 이상만 추출
        if area > 8500:
            # print(area)
            cnt += int(area / 8000)
            cv2.drawContours(dst, contours, i, color, 0, cv2.LINE_AA)
    # show_image('dst',dst)
    # dst = cv2.cvtColor(dst, cv2.COLOR_BGR2HSV)
    h, s, v = cv2.split(dst)
    contours, hierarchy = cv2.findContours(v, findMethod, cv2.CHAIN_APPROX_SIMPLE)

    for i in contours:
        epsilon = 0.02 * cv2.arcLength(i, True)
        approx = cv2.approxPolyDP(i, epsilon, True)
        # print(len(approx))

        cv2.drawContours(result, [approx], 0, (0, 255, 255), 5)
    show_image("result",result)
    # show_image('dst',dst)


    print(cnt,"마리")
    # cv2.imwrite('result_img/find_'+str(cnt)+"cnt_"+file+".jpg", result)
file_list = os.listdir("img")
print(file_list)
k = 1
for file in file_list:
    find(file)
    print("__________진행상태 : ",len(file_list)," / ",k,"__________")
    k +=1

# find("2021_10_23_00_00_35_99.png")

보고 이미지

Leave a Comment