이것저것 기록

[python, shapely] 이미지(raster)에서 폴리곤(vector) 추출하기 본문

코린이/실무를 위한 코딩 기록

[python, shapely] 이미지(raster)에서 폴리곤(vector) 추출하기

anweh 2020. 9. 21. 19:48

이미지(raster)파일, 

정확히는 흑백 이미지 파일에서 검정 픽셀을 .shp 파일의 폴리곤으로 추출해보자. 

 

우선 필요한 라이브러리부터 import 해준다. 

import os
import cv2
from shapely.geometry import Polygon
import numpy as np
import geopandas as gpd

shapely는 다각형, 선, 점의 벡터 파일을 다룰 때 사용하기 용이한 라이브러리이다. 

비슷한 기능을 하는 라이브러리로는 geopandas, fiona등이 있는데 나는 shapely가 편하더라... 

shapely.readthedocs.io/en/latest/manual.html 에서 메뉴얼을 참고! shapely는 정말 다양한 함수를 제공한다. 

잘만 사용하면 벡터 파일을 다룰 때 아주 유용함! 개인적으론 fiona 메뉴얼보다 친절하게 적혀있어서 shapely 라이브러리를 선호하는 편이다. 

 

 

 

쨌든, 코드로 넘어가자. 

내가 사용한 이미지는 아래의 별 사진이다. 

이 이미지에서 검정색 픽셀에 해당하는 부분만 shape파일로 바꿀 예정! 

간단히 두 단계면 끝나는 작업이다. 

 

 

 

1. 컨투어 찾기 

os.chdir('C:/Users/user/Desktop/hehe/') #폴더 경로
img = cv2.imread('star.png') #파일명

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #흑백사진으로 변환
ret, binary = cv2.threshold(gray, 240, 255, 0) 

contours, h = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
image = cv2.drawContours(img, contours, -1, (0,255,0), 1)

여기서 cv2.threshold로 이진화하는 이유는 정확도를 높히기 위해서이다. 

그리고 cv2.findContours() 함수는 원본 이미지에 직접 수정하기 때문에, 웬만하면 원본이미지를 따로 copy해놓는 것이 정석이긴함. 

해당 함수의 파라미터에 대한 추가적인 정보는 openCV 메뉴얼을 참고해보길 바란다. (opencv-python.readthedocs.io/en/latest/doc/15.imageContours/imageContours.html)

openCV에서 컨투어를 찾는 방식은 검은색 배경에서 하얀색 대상을 찾는 것과 비슷하기 때문에, 타겟 이미지의 대상은 흰색, 배경은 검은색으로 해야한다. 

 

 

2. 폴리곤 변환

poly_objs = []
for i in range(len(contours)):
    if (i > 0) and (len(contours[i]))>2:
        poly_objs.append(Polygon(np.squeeze(contours[i]))) #여기

polygons = poly_objs
polygons = gpd.GeoDataFrame(polygons, columns = ['geometry'])
polygons.to_file('star_polygons.shp')

contours라는 곳엔 컨투어 포인트들이 저장되어 있다. 

이제 이 컨투어 포인트들을 꼭지점으로 가지는 폴리곤을 생성할 차례다. 

poly_objs라는 list에 contours의 점들을 꼭지점으로 가지는 폴리곤을 만들어 넣어준다. (#여기 부분) 

폴리곤을 만들어 넣어줬으면, 이 폴리곤을 파일로 저장한다. 

벡터파일로 내보낼때는 '.to_file(저장할 파일 이름)' 을 사용한다. 

 

 

 

짠 

별 모양의 벡터 폴리곤이 완성! 

별이 상하 반전 된 것은 벡터와 레스터의 기준좌표가 다르기 때문이니까 무시하고 넘어가자 ㅎㅎ

 

 

 

 

Comments