본문 바로가기

IT

Opencv - Saliency map 사용해 보기

반응형

우선 Saliency map이란

영상(사진)을 어떤 기준에 따라 분석하기 쉽도록 단순하게 변환하는 것을 말합니다. 

쉽게 이야기하면, 한 사진에서 유독 두드러지게 다른 부분이 있다는 가정하에 그 차이를 명확하게 보이도록 하는 것인데... 대표적인 예시로 배경과 물체의 구분이 있습니다. 보통 그 기준으로 평균값을 사용합니다.

파이썬에 경우 opencv에 Saliency map이 존재합니다. 이 함수가 완벽하지는 않지만 꽤 쓸 만 한편이에요. 단 픽셀의 수가 많을수록 -당연하겠지만- 시간이 꽤 걸리는 편입니다. 요즘 나오는 스마트폰 사진을 노트북으로 처리했을 때 거진 2-3초가량이 걸렸어요. 사실 제 컴퓨터가 느려서 그런 거 같기는 한데...(LG 노트북 사용 중)

많이 쓰는 Saliency map의 방식이 궁금한 사람은 위키피디아의 정리를 참고해봐도 좋을것같습니다.

 

# import the necessary packages
import cv2
import numpy as np
import os

def step1_getarea(image) :
    """
    step1-물체의 주변부 찾기
    :param image: 물체를 찾을 사진의 이미지
    :return res : 찾아낸 물체 사진
    """
    #원본 이미지 사진 크기 재조정 할일이 있을 경우 사용
    imageHeight, imageWidth = image.shape[:2]
    resizeImage = image

    # 우리 코드의 핵심 cv2를 이용해 Saliencymap을 계산
    saliency = cv2.saliency.StaticSaliencyFineGrained_create()
    (success, saliencyMap) = saliency.computeSaliency(resizeImage)
    saliencyMap = (saliencyMap * 255).astype("uint8")  # 0-1사이의 값을 0-255의 값으로 변환
    cv2.imwrite(os.path.join(os.getcwd(),"sailencyMap.jpg"),saliencyMap) #비교를 위해 저장

    # the saliency map에 추가적으로 threshold 과정을 넣어준다. 
    threshMap = cv2.threshold(saliencyMap.astype("uint8"), 0, 255,
                              cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
    cv2.imwrite(os.path.join(os.getcwd(),"thresholdMap.jpg"),threshMap) #비교를 위해 저장

    # 이진화 이미지의 윤곽선을 검색
    # cv2.findContours(이진화 이미지, 검색 방법, 근사화 방법) return 윤곽선, 계층 구조
    contours, hierachy = cv2.findContours(threshMap, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
    area, output = 0, contours[0]

    #가장 큰 윤곽선을 찾는 과정
    for cnt in contours:
        if (area < cv2.contourArea(cnt)):
            area = cv2.contourArea(cnt)
            output = cnt

    # 근사치 구하기
    epsilon = 0.02 * cv2.arcLength(output, True)
    approx = cv2.approxPolyDP(output, epsilon, True)

    #찾은 물체의 근사치 좌표 구하기
    x, y, w, h = cv2.boundingRect(approx)
    rx = x
    ry = y
    if (x > 30):
        rx = x - 30
    if (y > 100):
        ry = y - 100

    #사진 자르기
    dst = resizeImage[ry:y + h + 100,rx:x + w + 100]  # NOTE: its img[y: y + h, x: x + w] and *not* img[x: x + w, y: y + h]]
    return dst

 

위 코드는 파이썬의 opencv를 이용한 Saliency map의 간단한 예제입니다. 사실 위의 코드로 처리하기 어려운 여러 예외상황들이 있습니다. 완벽한 영상처리라는 건 정말 어려운 일이에요. 

 

드에서 몇단계를 더 지나서 최종적으로 아래의 사진을 얻어내는 게 제 코드의 목표였습니다. 물체와 배경의 분리가 간단해 보이는 첫 단계이지만 사실 실제로 해보니 그렇게 간단하기만 한 일은 아니었어요.

 



요즘 AI 및 머신러닝 같은 부분들이 유행한 지 시간이 좀 지났는데, 그런 부분들이 영상처리에서 큰 활약을 하고 있죠. 슬금슬금 공부해두면 좋을 거 같습니다.

반응형