MeanShift와 CamShift로 물체를 추적할 수 있다. 배경을 제거하기 위해 backprojection을 어떻게 사용하는지 알아야 했다.
back projection은 배경 등 변화가 없는 이미지를 마스킹하기 위해 사용한다. 다음 동영상을 보면 알기 쉽다. cv2.imshow는 여러 창을 보여주지 못한다. matplot.pyplot을 사용했다. opencv의 색과 matplot.pyplot 색이 다르기 때문에 변경해야 제대로 표시된다.
class BackProjection(object): def __init__(self): self._imgPath = "./20160910_134843_2.jpg" self._img = cv2.imread("./20160910_134843_2.jpg",cv2.IMREAD_COLOR) self._roi = cv2.imread("./roi2.jpg") scale_percent = 40 # percent of original size self._width = int(self._img.shape[1] * scale_percent / 100) self._height = int(self._img.shape[0] * scale_percent / 100) self._dim = (self._width, self._height) self._hsv = cv2.cvtColor(self._img, cv2.COLOR_BGR2HSV) self._roi_hsv = cv2.cvtColor(self._roi, cv2.COLOR_BGR2HSV) self._roi_hist = cv2.calcHist([self._roi_hsv],[0,1], None, [180,256],[0,180,0,256]) self._mask = cv2.calcBackProject([self._hsv], [0,1], self._roi_hist, [0, 180, 0, 256],1) #kernel kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5)) self._mask = cv2.filter2D(self._mask, -1, kernel) _, self._mask = cv2.threshold(self._mask, 50, 255, cv2.THRESH_BINARY) self._mask = cv2.merge((self._mask, self._mask, self._mask)) self._result = cv2.bitwise_and(self._img, self._mask) def run(self): cv2.resize(self._img,self._dim,interpolation=cv2.INTER_AREA) plt.figure(1) plt.imshow(self._mask) plt.figure(2) #matplot으로 표시하면 BRG을 RGB로 바꿔야 됨 plt.imshow(cv2.cvtColor(self._img, cv2.COLOR_BGR2RGB)) plt.figure(3) plt.imshow(cv2.cvtColor(self._result, cv2.COLOR_BGR2RGB)) plt.show() if __name__ == '__main__': BackProjection().run()
결과를 보면 배경을 깔끔하게 지우지 못했다. 이미지 어느 부분을 roi_hsv로 설정하냐에 배경을 어떻게 지울지 결정한다. 더 나가 camshift로 물체를 추적할 수 있다. 그러나 값을 어떻게 넣고 배경이 어떤지에 따라 많은 영향을 받는다. 결국은 노가다..