이미지 분석으로 발 사이즈 측정하기 #첫 시도
재미로 말고 프로덕션 목적으로 이미지 분석은 처음이랄까..
허접하다...
lowestPoint 와 highestPoint 함수를 보명 for 문의 가장 안쪽에 if 문이 있는데 이 것으로 이미지의 테두리에 찍혀있는 contour 점들을 걸러낸다.
그런데 highestPoint 에 if y < temp_y and x > 30 and y > 30: 이게 있는 덕택에 고점이 잘못 찍힌 것은 함정..
밑에 이미지를 보면 우연찮게 발뒤꿈치 쪽에 점이 찍혀있는 걸 볼 수 있는데 순전히 저 30 상수 때문에 찍힌 것이다. 실제로 발뒷꿈치의 끝부분에 점을 찍을 수 있는지는 아직 모른다.. 안될거같으....
이 값이 나왔다..
지수 발사이즈는 230인데...
일단 opencv 를 사용하는 것을 전제로 하고..
요구조건은 다음과 같다.
1. 핸드폰 카메라로 찍힌 발 사진의 발볼길이, 발길이를 mm단위로 추출한다.
2. 길이를 재기 위한 기준으로 사용자는 a4용지 위에 발을 올리고 사진을 찍는다.
3. x,y,z 축 즉 발의 3면을 각각 찍어 사용자별로 사진이 3개씩 주어진다.
솔직히 처음에는 여차여차 공부하며 하면 되겠지 라고 생각했는데 역시나 쉽지 않다.
오늘은 이미지 분석의 첫 시도로 뻘글을 싼다.
1. 일단 주어진 발 사진을 a4용지의 축척에 맞추어 리사이징 한다. 이 과정에서 찍은 각도가 보정되고, 사진상으로 mm를 확인할 수 있게 된다.
%matplotlib inline import numpy as np import matplotlib.pyplot as plt import cv2 img = cv2.imread("foot.jpeg") blur = cv2.blur(img,(5,10)) rows,cols,ch = img.shape point=[[170,270],[480,220],[240, 710],[540,650]] pts1 = np.float32(point) pts2 = np.float32([[0,0],[210,0],[0,297],[210,297]]) M = cv2.getPerspectiveTransform(pts1,pts2) dst = cv2.warpPerspective(img,M,(210,297)) plt.subplot(121),plt.imshow(img),plt.title('Input') plt.plot(*zip(*point), marker='.', color='r', ls='') plt.subplot(122),plt.imshow(dst),plt.title('Output') plt.show()
사진을 보면 a4용지의 4 귀퉁이를 기준으로 210 * 290 사이즈로 맞춘다.
a4용지의 4귀퉁이를 이미지 분석으로 알아내기는 불가능 한것으로 보인다. 바닥과 차이가 안나는 경우도 있을 것이기에..
그런데 이 각도의 사진은 발 뒤꿈치의 끝을 알아내기 어려워 발 길이를 재기에는 적절치 않다는 게 이 시점에서 생각이 들었다.
그래서 다시 측면사진으로
2. 측면 사진 분석
%matplotlib inline import numpy as np import matplotlib.pyplot as plt import cv2 import math img = cv2.imread("foot-side.jpeg") imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) point=[[825,470],[780,140],[230, 460], [285,130]] pts1 = np.float32(point) pts2 = np.float32([[0,0],[210,0],[0,297],[210,297]]) ####### plt.figure(1) plt.subplot(111),plt.imshow(img),plt.title('Input') plt.plot(*zip(*point), marker='.', color='r', ls='') ######### plt.figure(2) M = cv2.getPerspectiveTransform(pts1,pts2) dst = cv2.warpPerspective(imgray,M,(210,297)) plt.subplot(111),plt.imshow(dst),plt.title('Adjust Size Output') ######### plt.figure(3); ret,thresh = cv2.threshold(dst,127,255,0) image, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) rows,cols,ch = img.shape contourImg = cv2.drawContours(dst, contours, -1, (0,255,0), 1) plt.subplot(111) plt.imshow(contourImg) plt.title('Contour Output') ######### plt.figure(4); newContour = []; for c in contours: if is_contour_good(c): newContour.append(c) newContourImg = cv2.drawContours(dst, newContour, -1, (0,255,0), 1) h_x,h_y = highestPoint(newContour); l_x,l_y = lowestPoint(newContour); lowestContourImg = cv2.circle(newContourImg, (l_x,l_y), 1, (255,255,255), thickness=3, lineType=8, shift=0) highestContourImg = cv2.circle(lowestContourImg, (h_x,h_y), 1, (255,255,255), thickness=3, lineType=8, shift=0) plt.subplot(111),plt.imshow(highestContourImg),plt.title('Contour Lowest/Highest Point') plt.show() print(math.sqrt((l_y - h_y)**2+(l_x - h_x)**2))
4개 figure로 뽑아보았는데
figure 1 |
측면 사진의 a4용지 네 귀퉁이를 잡는다.
여기서도 문제가 한 귀퉁이가 사진상에 나오지 않아서 어림짐작으로 점을 찍을 수 밖에 없었다.
물론 a4용지의 범위를 인식해서 교차선을 그을 수 있다면 문제가 되지 않겠지만.. 그렇게 할 수 있으면 점을 수동으로 찍지도 않았겠지..
figure 2 |
사이즈가 보정된 상태이다.
figure 3 |
여기서 contour를 써보았는데 여기를 참고했다
그런데 나중에 안 사실이지만 이렇게 오브젝트의 경계가 확실하지 않은 경우에는 먼저 경계가 확실히 드러나게 해 준 후 사용해야한다.
이거 실행할 당시에는 이 것만 해도 매우 신기했다..
그런데 문제가 있었다.
위에서 이미지를 warpPerspective 해준 것 때문인지 위 이미지의 바깥 경계 부분까지도 contour로 잡혔다. 그래서 높이 값으로 간단하게 해볼려고 했던 내 의도가 무산되었다.
그래서 짠 코드가 이것
def lowestPoint(contours): temp_y = 0 temp_x = 0; for index, i in enumerate(contours): if index == 0: continue for j in i: x,y = j[0] if y > temp_y and x != 1: temp_y = y temp_x = x return temp_x, temp_y def highestPoint(contours): temp_y = 999 temp_x = 0; for index, i in enumerate(contours): if index == 0: continue for j in i: x,y = j[0] if y < temp_y and x > 30 and y > 30: temp_y = y temp_x = x return temp_x, temp_y def is_contour_good(c): peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.02 * peri, True) return len(approx) > 4
허접하다...
lowestPoint 와 highestPoint 함수를 보명 for 문의 가장 안쪽에 if 문이 있는데 이 것으로 이미지의 테두리에 찍혀있는 contour 점들을 걸러낸다.
그런데 highestPoint 에 if y < temp_y and x > 30 and y > 30: 이게 있는 덕택에 고점이 잘못 찍힌 것은 함정..
밑에 이미지를 보면 우연찮게 발뒤꿈치 쪽에 점이 찍혀있는 걸 볼 수 있는데 순전히 저 30 상수 때문에 찍힌 것이다. 실제로 발뒷꿈치의 끝부분에 점을 찍을 수 있는지는 아직 모른다.. 안될거같으....
figure 4 |
그래도 여차저차 점 두개를 구해서 그 길이를 재보니 왠걸..
210.02142747824567
이 값이 나왔다..
지수 발사이즈는 230인데...
ㅎㅎㅎ
안녕하세요 혹시 궁금한 게 있는데 물어봐도 될까요?
답글삭제