[openCV] 모조리 싸그리 가려버리기

HeeSung Lee·2024년 3월 27일
0

오늘은 openCV를 이용해서 싸그리 검열해보자.

Blur, Canny, Erode,Dilation

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('data/lena.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

kernal = np.ones((5,5), np.uint8)

blur = cv2.blur(img, (5, 5))
canny = cv2.Canny(img, 100, 200)
dilation = cv2.dilate(canny, kernal, iterations = 1)
eroded = cv2.erode(dilation, kernal, iterations = 1)

cv2.imshow('Blur', blur)
cv2.imshow('Canny', canny)
cv2.imshow('Dilation', dilation)
cv2.imshow('Erode', eroded)

cv2.waitKey()
cv2.destroyAllWindows()

위 코드는 Blur, Canny, Erode,Dilation 를 사진에 적용한 코드다.

Blur

Blur는 이미지의 노이즈를 감소시키거나 선명도를 줄이는 데 사용된다. 주로 이미지를 부드럽게 만들어 더 이상한 노이즈나 세부적인 구조를 감춘다. 이를 위해 이미지의 각 픽셀을 중심으로 주변 픽셀을 고려하여 값을 평균화한다. 이렇게 함으로써 이미지의 부드러움을 증가시키고 경계를 흐리게 만든다.

Canny

Canny는 엣지 검출기는 이미지의 엣지를 검출하는 데 사용된다. 이는 이미지에서 갑작스러운 밝기 변화를 찾아내어 엣지로 추정한다. 이러한 엣지는 물체의 경계를 나타내는 데 유용하다. 캐니 엣지 검출은 여러 단계로 이루어지며, 노이즈 제거, 경계 강도 추정, 비최대 억제, 이중 임계값 처리 및 엣지 연결이 포함된다.

Erode

Erode는 이미지 처리에서 모양을 축소시키는 데 사용된다. 이는 이미지에서 작은 세부 정보를 제거하거나 물체를 축소하는 데 유용하다. 이 작업은 이미지의 각 픽셀을 중심으로 커널(필터)을 슬라이딩하고 주변 픽셀 값 중 가장 작은 값을 선택하여 중심 픽셀의 값을 대체함으로써 수행된다.

Dilation

Dilation은 Erode와 반대로 이미지에서 모양을 확장시키는 데 사용된다. 이는 물체의 크기를 키우거나 작은 구멍을 메우는 데 유용하다. 이 작업은 이미지의 각 픽셀을 중심으로 커널(필터)을 슬라이딩하고 주변 픽셀 값 중 가장 큰 값을 선택하여 중심 픽셀의 값을 대체함으로써 수행된다.

Affine

애핀 변환(Affine Transformation)은 기하학적인 변환 중 하나로, 원래의 객체를 층이나 크기를 조정하거나 회전시키는 것을 포함한다. 이 변환은 선의 평행성을 보존하며 직선은 직선으로 변환된다. 여러 가지 형태의 애핀 변환에는 다음과 같은 것들이 있다.

이동(Translation)

이동은 객체를 지정된 벡터만큼 평행 이동시키는 변환이며, 각 점의 좌표에 일정한 값을 더하거나 뺌으로써 수행된다. 예를 들어, (x, y) 좌표가 (dx, dy)만큼 이동하면 새로운 좌표는 (x+dx, y+dy)가 된다.

회전(Rotation)

회전은 객체를 지정된 각도만큼 회전시키는 변환이며, 중심점을 중심으로 수행된다. 회전 변환은 원점을 기준으로 공식을 사용하여 새로운 좌표를 계산하여 수행된다.

크기 조절(Scaling)

크기 조절은 객체의 크기를 변경하는 변환이다. 이는 각 좌표에 대해 스케일링 요인을 곱함으로써 수행된다. 이 때, 각 차원(가로 및 세로)별로 다른 스케일링 요소를 사용할 수 있다.

전단(Shearing)

전단은 객체를 지정된 방향으로 기울이는 변환이다. 이는 각 좌표에 대해 추가적인 값을 더함으로써 수행된다. 전단 변환은 가로 또는 세로 방향으로만 수행될 수도 있다.

애핀 변환은 이미지 처리, 컴퓨터 비전, 그래픽스 및 기타 관련 분야에서 널리 사용된다. 예를 들어, 이미지의 크기를 조절하거나 회전시키는 데 사용되며, 이미지의 일부 영역을 왜곡하여 특정 작업에 더 적합하게 만드는 데에도 활용될 수 있다.

import cv2

img = cv2.imread('data/god.jpg')
print(img.shape)


imgResize = cv2.resize(img, (1000, 500))

imgCropped = img[0:200, 200:500]

cv2.imshow('image',img)
cv2.imshow('Resized',imgResize)
cv2.imshow('Cropped',imgCropped)
cv2.waitKey()
cv2.destroyAllWindows()

위와 같이 코드를 짜면 사진을 크롭할 수 있다.

import cv2
import numpy as np

img = cv2.imread('data/god.jpg',0)
rows,cols = img.shape

M1 = np.float32([[1,0,100],[0,1,50]])
dst1 = cv2.warpAffine(img,M1,(cols,rows))

M2 = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst2 = cv2.warpAffine(img,M2,(cols,rows))

cv2.imshow('img',img)
cv2.imshow('dst1',dst1)
cv2.imshow('dst2',dst2)
cv2.waitKey(0)
cv2.destroyAllWindows()

이렇게 기하학적 변환도 줄 수 있다.

Contour

Contour은 이미지에서 연속된 점으로 이루어진 동일한 색상 또는 강도를 가진 영역의 경계를 나타낸다. 윤곽선은 객체의 외형을 파악하고 분석하는 데 사용된다. openCV와 같은 이미지 처리 라이브러리에서 윤곽선을 찾고 분석하는 기능이 많이 제공된다.

윤곽선을 찾는 과정은 다음과 같다.

  1. 전처리(Preprocessing)
    이미지를 그레이스케일 또는 이진화하여 윤곽선을 더 쉽게 검출할 수 있도록 전처리를 수행한다.

  2. 윤곽선 검출(Finding Contours):
    전처리된 이미지에서 윤곽선을 검출한다. 이를 위해 주로 흑백 이미지에서 빛이 밝은 영역의 윤곽선을 찾는 방법이 사용된다. OpenCV에서는 findContours 함수를 사용하여 윤곽선을 검출할 수 있다.

  3. 윤곽선 표시(Visualizing Contours):
    검출된 윤곽선을 이미지에 표시한다. 이를 통해 윤곽선을 시각적으로 확인할 수 있다.

  4. 윤곽선 특성 추출(Extracting Contour Features):
    윤곽선의 특성(예: 면적, 둘레, 중심점 등)을 추출하여 객체를 식별하거나 분석하는 데 사용된다.

해보자!

내 친구 노트북 사진을 마구마구 찹찹해보자.

윤곽선 따기

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('data/chin9.jpg')
imgResize = cv2.resize(img, (1000, 500))

kernal = np.ones((5,5), np.uint8)
canny = cv2.Canny(imgResize, 100, 200)
cv2.imshow('Canny', canny)

cv2.waitKey()
cv2.destroyAllWindows()

affine으로 노트북 세우기

import cv2
import numpy as np

img = cv2.imread('data/notebook.jpg')
imgResize = cv2.resize(img, (800, 800))

rows, cols = imgResize.shape[:2]
center = (cols / 2, rows / 2)
angle = -55
scale = 1.0
rotation_matrix = cv2.getRotationMatrix2D(center, angle, scale)

rotated_img = cv2.warpAffine(imgResize, rotation_matrix, (cols, rows))

cv2.imshow('Rotated', rotated_img)
cv2.waitKey()
cv2.destroyAllWindows()

노트북을 벌떡 세워봤다.

도형을 검출 해보자

친구 노트북이 어떻게 생겨먹은 녀석인지 알아보자.

import cv2
import matplotlib.pyplot as plt


block_size = 9
C = 5
img = cv2.imread('data/notebook.jpg', cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, (800, 500))
img = cv2.blur(img, (5,7))
img = cv2.adaptiveThreshold(img, 205, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, block_size, C)

contours, _ = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

for contour in contours:
    approx = cv2.approxPolyDP(contour, 0.01* cv2.arcLength(contour, True), True)
    cnt = approx
    area = cv2.contourArea(cnt)
    if area < 4700:
        continue;
    cv2.drawContours(img, [approx], 0, (0, 123, 0), 5)
    x = approx.ravel()[0]
    y = approx.ravel()[1] - 5
    if len(approx) == 3:
        cv2.putText(img, "Triangle", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
    elif len(approx) == 4:
        x1 ,y1, w, h = cv2.boundingRect(approx)
        aspectRatio = float(w)/h
        print(aspectRatio)
        if aspectRatio >= 0.95 and aspectRatio <= 1.05:
            cv2.putText(img, "square", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
        else:
            cv2.putText(img, "rectangle", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
    elif len(approx) == 5:
        cv2.putText(img, "Pentagon", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
    elif len(approx) == 10:
        cv2.putText(img, "star", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
    else:
        cv2.putText(img, "Circle", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))

cv2.imshow("shapes", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

이렇게 하면 사진에서 도형을 검출할 수 있다.

Rectangle이라 한다.

haar cascade

Haar Cascade는 객체 인식을 위한 컴퓨터 비전 및 이미지 처리 기술 중 하나다. 특히, 얼굴, 눈, 손가락, 차량 번호판 등과 같은 객체를 식별하는 데 널리 사용된다. 이 기술은 머신 러닝 기술 중 하나인 기계 학습을 기반으로 한다.

Haar Cascade는 특정 객체의 특징을 나타내는 학습된 XML 파일이다. 이러한 파일은 학습된 객체에 대한 패턴을 정의하고, 이 패턴을 사용하여 이미지에서 해당 객체를 식별한다. 일반적으로, Haar Cascade는 다음과 같은 단계로 구성된다

양성(Positive) 이미지 수집:

Haar Cascade를 생성하기 위해 양성 이미지(찾으려는 객체가 포함된 이미지)를 수집한다.

음성(Negative) 이미지 수집:

양성 이미지와 유사한 크기와 해상도를 가진 음성 이미지(찾으려는 객체가 없는 이미지)를 수집한다.

Haar 특징 계산

양성 및 음성 이미지에서 Haar 특징을 계산한다. 이러한 특징은 객체의 특징을 설명하는데 사용된다. 이러한 특징은 각각의 픽셀의 높이, 너비, 밝기 등에 기반한다.

Adaboost 학습

Adaboost 알고리즘을 사용하여 Haar 특징을 기반으로 하는 분류기를 학습한다. 이 분류기는 양성 및 음성 이미지를 구별하도록 학습된다.

Cascade 학습

다수의 Adaboost 분류기를 결합하여 Cascade를 생성한다. Cascade는 다단계 검출 프로세스를 나타낸다. 각 단계는 특정 정확도를 가지고 객체를 거부하거나 검출하는 역할을 수행한다.

검출

학습된 Haar Cascade를 사용하여 새로운 이미지에서 객체를 검출한다

. 이미지에서 슬라이딩 윈도우 기법을 사용하여 객체 후보를 생성하고, 각 후보가 Cascade를 통과하여 실제 객체인지 판별된다.

그것이 알고싶다

이제 사람들 얼굴이란 얼굴은 싸그리빡빡 가려버리는 모자이크 프로그램을 짜보자.

import cv2

# 웹캠 비디오 스트림 열기
cap = cv2.VideoCapture(0)

# 얼굴 감지를 위한 Haar Cascade 분류기 불러오기
faceCascade = cv2.CascadeClassifier("data/haarcascade_frontalface_default.xml")

# 무한 반복
while True:
    # 비디오 프레임 읽기
    ret, frame = cap.read()
    
    # 그레이스케일로 변환
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    
    # 얼굴 감지
    faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
    
    # 감지된 얼굴 주위에 재미있는 효과 적용
    for (x, y, w, h) in faces:
        # 얼굴 영역 잘라내기
        roi = frame[y:y+h, x:x+w]
        
        # 얼굴 영역 축소 후 확대하여 특별한 효과 적용
        small_roi = cv2.resize(roi, (0, 0), fx=0.05, fy=0.05)
        large_roi = cv2.resize(small_roi, (w, h), interpolation=cv2.INTER_NEAREST)
        
        # 특별한 효과를 적용한 영역 다시 원본 크기로 복원
        frame[y:y+h, x:x+w] = large_roi
    
    # 프레임 화면에 표시
    cv2.imshow('Webcam Face Detection', frame)
    
    # 'q' 키를 누르면 종료
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 비디오 스트림 및 창 해제
cap.release()
cv2.destroyAllWindows()

위와같이 범위를 정해서 확대했다가 다시 축소시키면 화질이 깨져서 모자이크가 되는 원리다. 잘생긴 얼굴이 보이지 않아서 아쉽겠지만 다음 글에서 돌아오겠다.

profile
프론트엔드 개발자를 꿈꾸는 고등학생입니다⌨️💻

0개의 댓글