보다 자세하게는 현미경 소견에서 관찰되는 개체를 인식할 수 있는가에 대한 것이다. 일단 고전적인 방법으로 접근하여 보았다. 인터넷 동호회의 정보를 바탕으로 모멘트(moments)에 대한 것을 검색하기 시작했고, 컨투어(contour)가 내가 원하는 기능이라는 것을 확인했다. 유채색을 고려하는 알고리즘은 못 찾았다. 그래서, 고전적인 방법으로 해보기로 했다. 이 방법에 있어서
가장 중요한 것은 분석 대상이 잘 구분되는 gray scale 이미지 변환이다.
OpenCV를 이용하여 시도해 보았던 방법은 RGB를 HSV로 변경하여 low와 high 범위내의 색상을 추출하는 것인데, 영 시원찮았다. CellProfiler를 이용하여 추출한 흑백 이미지를 이용했다. 이 경우에도 1-channel이 아니었기 때문에 변환시켜 준다.
src = cv2.imread("seq2337_1gray.tiff", cv2.IMREAD_GRAYSCALE)
Python의 경우 함수에서 결과를 여러개 나오는 경우가 있다. 이럴 경우 순서에 맞게 출력하거나, 불필요하게 들어오는 것은 대충 처리하거나 하는 것 같다.
분석 대상이 아닌 배경 이미지는 확실하게 지워줘야 한다. threshold의 경우 첫 번째꺼는 쓰지 않는 정보이다. 2번째는 low값, 3번째는 high 값, 4번째는 출력 방식이다.
ret, gray_th = cv2.threshold(src, 100, 255, cv2.THRESH_BINARY)
아니면
gray_th = cv2.threshold(src, 100, 255, cv2.THRESH_BINARY)[1]
Contours를 찾아주는 것은 아래와 같이 하면 된다. 2번째와 3번째는 contours를 설정하는 방법에 대한 것이다. 나는 findContours의 결과 중 첫 번째 Contours에 위치에 대한 정보만 있으면 된다. R과 Python의 중요한 차이점으로 처음이 1이 아닌 0이다.
contours = cv2.findContours(
gray_th, cv2.RETR_TREE, cv2.CHAIN_APPROX_TC89_KCOS)[0]
Contours가 여러개 나오기 때문에 반복문을 이용해서 [i]가 있다. 이미지는 항상 똑바르게 서있거나 누워 있지 않기 때문에, 기울어진 직사각형으로 contours를 찾는 minAreaRect를 이용했다.
rect = cv2.minAreaRect(contours[i])
minAreaRect에서는 결과값이 3개가 나온다. 첫 번째 항목은 그림 파일에서 중앙 위치에 대한 것으로 (X, Y) 형태이다. 두 번째는 직사각형의 (폭, 넒이)이다. 가로 길쭉과 세로 길쭉 형태를 구분하지는 않는다. 세 번째는 기울어지는 정도이다. 시계 방향이면 양수, 시계 반대 방향이면 음수인 것 같다. 나의 경우에는 폭과 넓이만 필요해서 w와 h로 결과를 받았다.
(w, h) = rect
[1]
이렇게 찾은 contour가 올바른게 확인해 보려면 역시 봐야 한다. drawContours로 할 수 있다. 첫 번째는 이미지, 두번째는 좌표이다. minAreaRect로는 사각형을 그리는게 어려우니까 boxPoints로 그릴 수 있는 4개의 좌표로 변환한다. 픽셀에 소수점은 없으니까 NumPy를 이용하여 정수로 변환한다. 3번째는 첫 번째 contour를 뜻하는 0을 기술한다. 4번째는 색상이다. 추가 옵션으로 두께 같은 것이나, 모든 contour에 대한 것도 있다. 원하는 대로 잘 찾아졌는지 Pyplot으로 그려보면 된다.
cv2.drawContours(src, [np.int64(cv2.boxPoints(rect))], 0, [255, 0, 0])
분석 속도는 꽤 빠르다.