2024.07.25(목) 세미나까지 아래의 distance 부분까지 계산한 내용을 발표했다.
참고로,
distance = focal_length * ( actual_area_meters / pixel_area)로 구했다.
머리속 이론이라 틀릴 수도 있지만,,,? 결과는 나름(?)잘 나오니 킵고잉,,,,,ㅎㅡㅎ
어쨌든 나는 distance가 아닌 실제로 이동해야할 거리를 구해야하는데,
이 문제는 간단한 삼각비로 해결할 수 있다.(로봇의 목 각도를 내가 알고 있다는 가정하에.)
결론은 아래 그림에서의 walk_distance가 필요한데, 계산 공식도 그림에 적었으니 참고 바람

import cv2
import numpy as np
# 모든 길이 단위는 m 기준
actual_diameter_meters = 0.05 # 공의 직경
actual_area_meters = np.pi * (actual_diameter_meters / 2) ** 2 # 공의 면적(직경으로 계산한 값)
focal_length = 403 # 초점 거리 값 # 캘리 매트릭스에서 ((fx+fy)/2)로 평균한 결과 # 509.0532269132008(새거)403.01356509306765(구)
robot_height = 0.4 # 로봇 높이 (실제론 카메라 높이로 변경해야함)
neck_angle = 60 # 임시 목 각도 (degree)
# 빨간 공 탐지 및 거리 추정 함수
def detect_and_calculate_distance(frame):
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
lower_red = np.array([170, 50, 70])
upper_red = np.array([180, 255, 255])
mask = cv2.inRange(hsv, lower_red, upper_red)
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
if contours:
largest_contour = max(contours, key=cv2.contourArea)
((x, y), radius) = cv2.minEnclosingCircle(largest_contour)
if contours:
largest_radius = 0
largest_contour = None
for contour in contours:
((x, y), radius) = cv2.minEnclosingCircle(contour)
if radius > largest_radius:
largest_radius = radius
largest_contour = contour
if largest_radius > 0 and largest_contour is not None:
center = (int(x), int(y))
radius = int(largest_radius)
cv2.circle(frame, center, radius, (0, 255, 0), 2)
cv2.drawContours(frame, [largest_contour], -1, (255, 0, 0), 2)
# 중심점 표시는 내가 볼라고
cv2.circle(frame, center, 5, (0, 0, 255), -1)
cv2.putText(frame, "Center", (center[0] - 20, center[1] - 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
# 면적 계산
pixel_area = np.pi * (radius ** 2)
# 거리 계산
distance = focal_length * np.sqrt(actual_area_meters / pixel_area)
# walk_dist 계산
neck_angle_radians = np.radians(neck_angle) # degree to radian
walk_dist = distance * np.cos(np.pi/2 - neck_angle_radians)
return frame, distance, center, pixel_area, walk_dist
return frame, None, None, None, None
cap = cv2.VideoCapture(1)
while True:
ret, frame = cap.read()
if not ret:
break
frame, distance, center, pixel_area, walk_dist = detect_and_calculate_distance(frame)
if distance:
cv2.putText(frame, f"Distance: {distance:.2f} m", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
if center:
cv2.putText(frame, f"Center: {center}", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.putText(frame, f"Area: {pixel_area:.2f} pixels^2", (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.putText(frame, f"Walk Dist: {walk_dist:.2f} m", (10, 120), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.imshow("Frame", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
'Embedded LAB Semina' 카테고리의 다른 글
| github error 해결 :: nothing to commit, working tree clean (0) | 2024.09.09 |
|---|---|
| 타 방향 확인하기 (0) | 2024.08.12 |
| 공까지의 거리 추적하기(2) :: 발돋움,, 이미지 캡쳐 + 카메라 캘리브레이션 (0) | 2024.07.26 |
| 공까지의 거리 추적하기(1) (0) | 2024.07.16 |
| 초록색 필드 구별하기(구별된 영역 위의 객체만 추적하도록) (0) | 2024.07.16 |