프로젝트명 :
치킨카운터
카테고리 :
개발 > 이미지처리
기간 :
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")