오늘은 실습 문제를 푸는 과정과 최종 작성된 코드가 리더님께서 풀이해주신 과정과 결과에 근접했던 문제들이 많아서 어제 코드를 열심히 뜯어본 보람이 느껴졌다. 또 리스트 컴프리헨션 등의 파이썬스러운 코드를 자연스럽게 사용하고 있는 스스로를 보니까 꾸준하게 프로그래머스 문제를 풀었던 점도 많은 도움이 되고 있는 것 같아서 더 열심히 공부할 수 있는 동기부여가 되는 것 같다.
img = cv.imread(DOG_PATH)
coppied = img.copy()
# 그레이 스케일로 변환
gray = cv.cvtColor(coppied, cv.COLOR_BGR2GRAY)
# Canny
canny = cv.Canny(gray, 50, 150)
# 윤곽선 찾기
contours, hierachy = cv.findContours(canny, cv.RETR_CCOMP, cv.CHAIN_APPROX_NONE)
# 윤곽선 그리기
cv.drawContours(img, contours, -1, (0,255,0), 2)
cv.imshow("Contours", img)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)
img = cv.imread(DOG_PATH)
coppied = img.copy()
# 그레이 스케일로 변환
gray = cv.cvtColor(coppied, cv.COLOR_BGR2GRAY)
# 이진화
ret, binary = cv.threshold(gray, -1, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
# Canny
canny = cv.Canny(binary, 50, 150)
# 윤곽선 찾기
contours, hierachy = cv.findContours(canny, cv.RETR_CCOMP, cv.CHAIN_APPROX_NONE)
# 윤곽선 그리기
cv.drawContours(img, contours, -1, (0,255,0), 2)
cv.imshow("Contours", img)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)
img = cv.imread(DOG_PATH)
coppied = img.copy()
gray = cv.cvtColor(coppied, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, -1, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
contours, hierachy = cv.findContours(binary, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)
for contour in contours:
x, y, width, height = cv.boundingRect(contour)
cv.rectangle(img, (x,y), (x+width, y+height), (255,0,0), 2, cv.LINE_AA)
cv.imshow("Bounding Rect", img)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)
img = cv.imread(CAT_PATH)
coppied = img.copy()
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, -1, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
contours, hierachy = cv.findContours(binary, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)
for contour in contours:
# contour의 면적이 1000보다 큰 영역만 표시
if cv.contourArea(contour) > 1000:
x, y, width, height = cv.boundingRect(contour)
cv.rectangle(img, (x,y), (x+width, y+height), (255,0,0), 2, cv.LINE_AA)
cv.imshow("Bounding Rect", img)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)
img = cv.imread("../images/vehicles.png")
coppied = img.copy()
gray = cv.cvtColor(coppied, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, -1, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
contours, hierachy = cv.findContours(binary, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)
name = "Index Trackbar"
cv.namedWindow(name)
filtered_contours = [c for c in contours if cv.contourArea(c) > 700]
cv.createTrackbar("index", name, 0, len(filtered_contours)-1, lambda x:x)
while True:
coppied = img.copy()
index = cv.getTrackbarPos("index", name)
contour = filtered_contours[index]
x, y, width, height = cv.boundingRect(contour)
cv.rectangle(coppied, (x,y), (x+width, y+height), (255,0,0), 2, cv.LINE_AA)
cv.imshow(name, coppied)
if cv.waitKey(1) == ord("q"):
break
cv.destroyAllWindows()
cv.waitKey(1)
img = cv.imread("../images/playing_cards.png")
coppied = img.copy()
gray = cv.cvtColor(coppied, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, -1, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
contours, hierachy = cv.findContours(binary, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)
crops = []
for idx, contour in enumerate(contours):
if cv.contourArea(contour) > 1300:
x, y, width, height = cv.boundingRect(contour)
cv.rectangle(coppied, (x,y), (x+width, y+height), (0,255,0), 2, cv.LINE_AA)
crop = img[y:y+height, x:x+width]
crops.append(crop)
def on_trackbar(val):
target = crops[val]
cv.imshow("Card", target)
name = "Original"
cv.namedWindow(name)
cv.createTrackbar("index", name, 0, len(crops)-1, on_trackbar)
cv.imshow(name, coppied)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)
img = cv.imread(CAT_PATH)
b = cv.calcHist([img], [0], None, [256], [0, 256])
g = cv.calcHist([img], [1], None, [256], [0, 256])
r = cv.calcHist([img], [2], None, [256], [0, 256])
plt.plot(b, color="b")
plt.plot(g, color="g")
plt.plot(r, color="r")
plt.title("Image Histogram")
plt.xlabel("Pixel Value")
plt.ylabel("Frequency")
plt.show()
img = cv.imread(DILATE)
kernel = np.ones((3,3), dtype=np.uint8)
dilate_1 = cv.dilate(img, kernel, iterations=1)
dilate_2 = cv.dilate(img, kernel, iterations=2)
dilate_3 = cv.dilate(img, kernel, iterations=3)
cv.imshow("img", img)
cv.imshow("dilate_1", dilate_1)
cv.imshow("dilate_2", dilate_2)
cv.imshow("dilate_3", dilate_3)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)
img = cv.imread(ERODE)
kernel = np.ones((3,3), dtype=np.uint8)
erode_1 = cv.erode(img, kernel, iterations=1)
erode_2 = cv.erode(img, kernel, iterations=2)
erode_3 = cv.erode(img, kernel, iterations=3)
cv.imshow("img", img)
cv.imshow("erode_1", erode_1)
cv.imshow("erode_2", erode_2)
cv.imshow("erode_3", erode_3)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)
img = cv.imread(ERODE)
kernel = np.ones((3,3), dtype=np.uint8)
erode = cv.erode(img, kernel, iterations=3)
dilate = cv.dilate(erode, kernel, iterations=3)
cv.imshow("img", img)
cv.imshow("open", dilate)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)
img = cv.imread(DILATE)
kernel = np.ones((3,3), dtype=np.uint8)
dilate = cv.dilate(img, kernel, iterations=3)
erode = cv.erode(dilate, kernel, iterations=3)
cv.imshow("img", img)
cv.imshow("close", erode)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)
cv2.detectMultiScalescaleFactor : 이미지 크기를 얼마나 줄여가며 검출을 진행할지를 결정, 기본적으로 1.1로 많이 사용minNeighbors : 검출된 객체 주변에 얼마나 많은 "이웃" 검출이 있어야 최종적으로 객체로 간주할지 결정minSize / maxSize : 검출할 객체의 최소 / 최대 크기, 해당 사이즈보다 작거나 큰 객체는 제외# 얼굴인식
face_cascade = cv.CascadeClassifier(FACE_CASCADE)
img = cv.imread(FACE)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(
gray, scaleFactor=1.1, minNeighbors=10, minSize=(10,10)
)
if len(faces):
for face in faces:
x, y, width, height = face
cv.rectangle(img, (x,y), (x+width, y+height), (0,255,0), 2, cv.LINE_AA)
cv.imshow("img", img)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)
# 눈인식
eye_cascade = cv.CascadeClassifier(EYE_CASCADE)
img = cv.imread(FACE)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
eyes = eye_cascade.detectMultiScale(
gray, scaleFactor=1.1, minNeighbors=15, minSize=(10,10)
)
if len(eyes):
for eye in eyes:
x, y, width, height = eye
cv.rectangle(img, (x,y), (x+width, y+height), (0,255,0), 2, cv.LINE_AA)
cv.imshow("img", img)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(1)
얼굴 인식을 간단히 살펴보고 수업이 마무리되었는데 꽤 재미있는 파트인 것 같다. 그리고 트랙바를 구현할 때 while문 대신 콜백 함수를 사용하는 방법이 더 직관적이고 편한 것 같다고 느꼈다. 윈도우를 하나만 표시할 때는 최초에 함수를 따로 실행해줘야 하는 귀찮은 부분이 있긴 하지만, getTrackbarPos()와 while문을 사용하는 것보다는 더 편한 것 같아서 계속 사용해보면서 장단점을 더 느껴봐야겠다.