OpenCV의 이미지 분할

Manav Narula 2023년1월30일
  1. Python에서 opencv를 사용한 이미지 분할
  2. opencv를 사용하여 이미지 분할에 GrabCut 알고리즘 사용
  3. opencv를 사용하여 이미지 분할에 색상 감지 사용
  4. 결론
OpenCV의 이미지 분할

이미지 처리는 Computer Vision 작업에서 중요한 단계입니다. Python에서 opencv 라이브러리를 사용하여 다양한 객체와 방법을 사용하는 여러 이미지 처리 기술을 구현할 수 있습니다.

이 튜토리얼은 파이썬에서 opencv를 사용하여 이미지 분할을 수행하는 방법을 보여줍니다.

Python에서 opencv를 사용한 이미지 분할

이미지 분할은 주어진 이미지를 여러 부분으로 나누는 과정을 말합니다.

분할된 부분의 경계를 따라 점을 연결하는 곡선을 추가합니다. 이러한 곡선을 등고선이라고 합니다.

이미지 분할은 Computer Vision에서 매우 유용하며 많은 실제 응용 프로그램이 있습니다. 이 기술을 사용하여 이미지의 일부를 분할하여 다양한 객체를 분류할 수 있습니다.

Python에서 opencv를 사용하여 이미지 분할에 사용할 수 있는 몇 가지 방법을 사용할 수 있습니다.

모든 영상 분할 기법에서 다른 주된 방법은 일반적으로 분할된 영상의 기준에 따른다. 일부 색상 감지, Watershed 알고리즘, 에지 감지와 같은 사전 정의된 알고리즘을 기반으로 이미지 분할을 수행하고 사용자 입력을 기반으로 분할된 부분을 선택할 수도 있습니다.

다음 섹션에서 이러한 방법 중 일부에 대해 설명합니다.

opencv를 사용하여 이미지 분할에 GrabCut 알고리즘 사용

이 방법을 사용하려면 사용자가 마우스와 키보드를 사용해야 합니다. 내장된 opencv 라이브러리에는 마우스와 키보드에서 사용자 입력을 읽을 수 있는 개체와 메서드가 있습니다.

GrabCut 알고리즘은 이미지 분할을 위한 매우 간단하고 유용한 도구입니다. 이 기술에서는 사용자 입력을 사용하여 주어진 이미지의 일부 영역을 선택합니다.

이 알고리즘은 분할된 부분의 전경과 배경을 자동으로 감지하여 표시할 수 있습니다.

이 알고리즘을 구현하기 위해 opencv 라이브러리의 grabCut() 함수를 사용할 수 있습니다. 이미지 분할을 위해 이 함수 내에서 선택한 영역의 상자와 함께 이미지를 전달합니다.

예제는 다음 코드를 참조하십시오.

import cv2
import numpy as np


def algo_grabcut(img, bounding_box):
    seg = np.zeros(img.shape[:2], np.uint8)
    x, y, width, height = bounding_box
    seg[y : y + height, x : x + width] = 1
    background_mdl = np.zeros((1, 65), np.float64)
    foreground_mdl = np.zeros((1, 65), np.float64)

    cv2.grabCut(
        img, seg, bounding_box, background_mdl, foreground_mdl, 5, cv2.GC_INIT_WITH_RECT
    )

    mask_new = np.where((seg == 2) | (seg == 0), 0, 1).astype("uint8")
    img = img * mask_new[:, :, np.newaxis]
    cv2.imshow("Output", img)


def box_draw(click, x, y, flag_param, parameters):
    global x_pt, y_pt, drawing, topleft_pt, bottomright_pt, img

    if click == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        x_pt, y_pt = x, y

    elif click == cv2.EVENT_MOUSEMOVE:
        if drawing:
            topleft_pt, bottomright_pt = (x_pt, y_pt), (x, y)
            image[y_pt:y, x_pt:x] = 255 - img[y_pt:y, x_pt:x]
            cv2.rectangle(image, topleft_pt, bottomright_pt, (0, 255, 0), 2)

    elif click == cv2.EVENT_LBUTTONUP:
        drawing = False
        topleft_pt, bottomright_pt = (x_pt, y_pt), (x, y)
        image[y_pt:y, x_pt:x] = 255 - image[y_pt:y, x_pt:x]
        cv2.rectangle(image, topleft_pt, bottomright_pt, (0, 255, 0), 2)
        bounding_box = (x_pt, y_pt, x - x_pt, y - y_pt)

        algo_grabcut(img, bounding_box)


drawing = False
topleft_pt, bottomright_pt = (-1, -1), (-1, -1)

img = cv2.imread("img4.jpg")
img = cv2.resize(img, (500, 500))
image = img.copy()
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", box_draw)

while True:
    cv2.imshow("Frame", image)
    ch = cv2.waitKey(1)
    if ch == 32:
        break

cv2.destroyAllWindows()

출력:

Grabcut 알고리즘의 선택된 영역

GrabCut 알고리즘을 사용한 분할 이미지

위의 예에서 무슨 일이 일어나고 있는지 이해합시다.

box_draw() 함수는 이미지 분할 영역을 선택하기 위해 마우스와의 사용자 상호 작용을 읽습니다. 상자와 이미지는 이미지를 가져와 분할된 이미지에 대한 이진 마스크를 생성하는 algo_grabcut() 함수로 전달됩니다.

이 마스크를 사용하여 분할된 부분의 전경을 표시합니다.

opencv를 사용하여 이미지 분할에 색상 감지 사용

Python에서는 색상 감지를 위해 opencv를 사용할 수 있습니다. 이미지의 색상을 나타내는 데 사용할 수 있는 다양한 색상 공간이 있습니다.

우리의 경우 HSV 색상 공간을 사용하여 주어진 색상의 범위를 결정합니다.

우리는 이미지 분할을 위해 다른 색상을 사용할 것입니다. 주어진 색상에 대한 범위를 만들고 opencv 라이브러리의 inRange() 함수를 사용하여 이 색상과 일치하는 객체를 감지합니다.

이것은 바이너리 마스크를 반환합니다. 그런 다음 이 마스크를 수정하고 이 감지된 부분에 윤곽을 추가합니다.

앞에서 설명한 것처럼 윤곽선은 분할된 부분의 경계에 있는 곡선입니다. findContours() 함수를 사용하여 생성된 마스크를 사용하여 경계를 찾은 다음 drawContours() 함수로 이러한 윤곽선을 그립니다.

아래 코드를 참조하십시오.

import cv2
import numpy as np

img = cv2.imread("img4.jpg")
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
bound_lower = np.array([36, 25, 25])
bound_upper = np.array([70, 255, 255])

mask_green = cv2.inRange(hsv_img, bound_lower, bound_upper)
kernel = np.ones((7, 7), np.uint8)

mask_green = cv2.morphologyEx(mask_green, cv2.MORPH_CLOSE, kernel)
mask_green = cv2.morphologyEx(mask_green, cv2.MORPH_OPEN, kernel)

seg_img = cv2.bitwise_and(img, img, mask=mask_green)
contours, hier = cv2.findContours(
    mask_green.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
output = cv2.drawContours(seg_img, contours, -1, (0, 0, 255), 3)

cv2.imshow("Result", seg_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

출력:

색상 감지를 사용한 이미지 분할

위의 코드에서 우리는 주어진 이미지에서 녹색 객체를 분할합니다. 먼저 cvtColor 함수를 사용하여 이미지를 HSV 색상 공간으로 변환합니다.

그런 다음 감지된 색상을 저장하는 마스크를 생성합니다. 이 마스크에서 원하지 않는 노이즈도 제거합니다.

그런 다음 감지된 세그먼트에 등고선을 그리고 표시합니다. waitKey() 함수는 이미지 창이 자동으로 닫히는 것을 방지합니다.

사용자가 일부 키를 누른 다음 닫을 때까지 기다립니다.

결론

이 튜토리얼에서는 Python의 opencv 라이브러리를 사용한 이미지 분할에 대해 논의했습니다. 또한 더 많은 것이 가능하지만 이를 위해 몇 가지 기술을 구현했습니다.

우리는 이미지 분할 이면의 기본 사항과 모든 방법에서 접근 방식과 최종 결과가 무엇인지에 대해 논의했습니다.

두 가지 방법에 대해 자세히 논의했습니다. 먼저 GrabCut 알고리즘을 구현했습니다.

이 알고리즘에서 사용자는 분할에 사용할 영역을 선택합니다. 이 부분에서 전경 객체를 감지하고 표시합니다.

두 번째 기술에서는 색상 감지를 사용했습니다. 녹색 물체를 감지했습니다.

이러한 유형의 분할에서는 이미지를 주어진 색상 공간으로 변환하고 이 모델의 색상 범위를 사용하여 inRange() 함수를 사용하여 색상을 감지합니다. 우리는 이 마스크를 이미지 분할에 사용하고 가장자리 주위에 윤곽을 그립니다.

작가: Manav Narula
Manav Narula avatar Manav Narula avatar

Manav is a IT Professional who has a lot of experience as a core developer in many live projects. He is an avid learner who enjoys learning new things and sharing his findings whenever possible.

LinkedIn