신규 블로그를 만들었습니다!

2020년 이후부터는 아래 블로그에서 활동합니다.

댓글로 질문 주셔도 확인하기 어려울 수 있습니다.

>> https://bluemiv.tistory.com/

OpenCV 설치

pip 최신버전으로 업데이트를 진행합니다.

python -m pip install --upgrade pip

 

pip를 이용한 필요한 패키지 설치를 합니다. 

pip install matplotlib
pip install numpy
pip install OpenCV-Python

 

 

설치 확인

설치가 완료되었으면, python에서 import cv2를 통해 제대로 import가 이루어지는지 확인합니다. 만약 import를 할 수 없다는 에러(Error)가 발생하면 제대로 설치되지 않았다는 뜻이므로, 처음부터 절차대로 다시 진행하시길 바랍니다.

 

OpenCV를 이용한 Feature Matching

위에서 설치를 하셨다면, 이제 Feature Matching을 진행합니다. 코드는 비교적 간단합니다. 요약하면 순서는 2단계로 나눠집니다. 내용은 아래와 같습니다.

2개의 이미지 객체 생성 > 만들어진 이미지 객체들을 서로 비교

 

1. 이미지 객체 가져오기

보통 이미지 객체를 생성할 때, 색상을 제거하고 흑백으로 생성을 합니다. 이 부분에 대해서는 자세히는 모르겠지만, 이미지를 서로 비교하기 좋게 만드는 과정 중 하나입니다.

 

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

class compareImg :
    def __init__(self) :
        pass

    def readImg(self, filepath) :
        img = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)
        cv2.namedWindow("root", cv2.WINDOW_NORMAL) # window 생성
        cv2.imshow("root", img) # window에 이미지 띄우기
        cv2.waitKey(5000) # 5초 기다림. 아무키나 입력되면 대기 종료
        cv2.destroyAllWindows() # window 제거
        return img

    def run(self) :
        # 이미지 파일 경로 설정
        filepath1 = r"C:\dev\python\workspace\img\simson1.png"
        filepath2 = r"C:\dev\python\workspace\img\simson2.png"
        
        # 이미지 객체 가져옴
        img1 = self.readImg(filepath1)
        img2 = self.readImg(filepath2)

if __name__ == '__main__':
    cImg = compareImg()
    cImg.run()

 

일단, 이미지 객체를 잘 불러오는지 확인을 해봅니다.

10번째 줄 : 이미지 객체 생성

11번째 줄 ~ 14번째 줄 : 윈도우 창 생성 및 이미지 출력

15번째 줄 : 추후에 이미지 객체를 사용해야 하므로, 이미지 객체를 return값으로 설정

 

실행 결과

심슨 사진을 가지고 진행했습니다. 정상적으로 이미지를 가져옵니다.

위 과정은 확인 차원에서 해본 것이고, 본격적으로 두개의 이미지를 비교합니다.

 

2. 이미지 비교(피처 매칭)

가져온 2개의 이미지를 서로 비교합니다.

 

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

class compareImg :
    def __init__(self) :
        pass

    def readImg(self, filepath) :
        img = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)
        # cv2.namedWindow("root", cv2.WINDOW_NORMAL) # window 생성
        # cv2.imshow("root", img) # window에 이미지 띄우기
        # cv2.waitKey(5000) # 5초 기다림. 아무키나 입력되면 대기 종료
        # cv2.destroyAllWindows() # window 제거
        return img


    def diffImg(self, img1, img2) :
        # Initiate SIFT detector
        orb = cv2.ORB_create()

        # find the keypoints and descriptors with SIFT
        kp1, des1 = orb.detectAndCompute(img1, None)
        kp2, des2 = orb.detectAndCompute(img2, None)

        # create BFMatcher object
        bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

        # Match descriptors.
        matches = bf.match(des1,des2)

        # Sort them in the order of their distance.
        matches = sorted(matches, key = lambda x:x.distance)

        # BFMatcher with default params
        bf = cv2.BFMatcher()
        matches = bf.knnMatch(des1, des2, k=2)

        # Apply ratio test
        good = []
        for m,n in matches:
            if m.distance < 0.75 * n.distance:
                good.append([m])

        # Draw first 10 matches.
        knn_image = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good, None, flags=2)
        plt.imshow(knn_image)
        plt.show()

    def run(self) :
        # 이미지 파일 경로 설정
        filepath1 = r"C:\dev\python\workspace\img\simson1.png"
        filepath2 = r"C:\dev\python\workspace\img\simson2.png"
        
        # 이미지 객체 가져옴
        img1 = self.readImg(filepath1)
        img2 = self.readImg(filepath2)

        # 2개의 이미지 비교
        self.diffImg(img1, img2)

if __name__ == '__main__':
    cImg = compareImg()
    cImg.run()

 

20번째 줄 ~ 24번째 줄 : keypoint와 descriptor를 가져옵니다.

27번째 줄 ~ 37번째 줄 : Match를 통해 이미지를 비교합니다.

40번째 줄 ~ 43번째 줄 : ratio를 설정해서 좀 더 정확한 값을 얻을 수 있습니다. ratio에 따라 결과가 어떻게 달라지는지 아래에서 소개하겠습니다. 비교해서 유사한 점을 얻어 "good"이라는 임의의 리스트에 넣습니다.

47번째 줄 ~ 48번째 줄 : 비교한 이미지를 윈도우 창에 띄어줍니다.

 

실행결과

Ratio에 따른 결과

Ratio 1부터 0까지 조금씩 줄여보면서, 차이를 살펴보겠습니다. Ratio의 값을 줄일수록 이미지 유사도 거리가 줄어들어 조금 더 정확한 값을 보입니다. 하지만 너무 줄이면, 원하는 결과를 얻기 힘듭니다.

상황에 따라 적당한 ratio값을 설정해주는 것이 중요해 보입니다.

 

Ratio : 1

Ratio 1.0

전혀 알 수 없는 결과가 나옵니다. 

 

Ratio : 0.8

Ratio 0.8

0.8로 유사도 거리를 줄여본 결과, 어느 부분이 비슷한지 얼추 나옵니다.

 

Ratio : 0.75

Ratio 0.75

점점 줄여보면 조금 더 정확한 값이 나옵니다.

 

Ratio : 0.6

Ratio 0.6

대략 0.6일때 정확한 값들이 나오는군요.

 

Ratio : 0.4

Ratio 0.4

 

Ratio : 0.3

Ratio 0.3

 

Ratio : 0.2

Ratio 0.2

 

 

Ratio : 0

Ratio 0

일치하는 부분이 없다고 나옵니다.

 

느낀점

사실 거의 동일한 사진이어서 유사한 부분이 많이 나올줄 알았지만, 생각보다 그러진 않았습니다.

 

아직 OpenCV를 많이 사용해보지도 않았고, 이미지 비교하는 것에 대한 공부를 이제 막 시작하여 부족한 부분이 많습니다.

위 내용은 간단한 기능만을 이용해 만들었습니다. 코딩해보고 결과를 통해 느낀바로는... 이미지 비교하는데 Feature Matching을 이용하는 것이 그렇게 효율적이지는 않아보인다는 것입니다.

 

좀 더 공부를 통해 효율적인 이미지 비교하는 방법을 포스팅 하도록 하겠습니다.

 

다른 글

2018/05/25 - [IoT] - 정적인 사진에서 OpenCV를 이용한 얼굴인식(Python 파이썬 코드)

 

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기