일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- XAI
- 트랜스포머
- AI
- ai 챗봇
- 인공지능
- AI 기술
- PYTHON
- 휴머노이드 로봇
- ChatGPT
- 다국어 지원
- 3d 재구성
- 오픈소스
- 오픈AI
- 일론 머스크
- LORA
- tts
- OpenAI
- 우분투
- 시간적 일관성
- 강화 학습
- 생성형AI
- 딥러닝
- OpenCV
- 오블완
- 확산 모델
- 티스토리챌린지
- 메타
- 코딩
- ubuntu
- LLM
- Today
- Total
AI 탐구노트
영상 기반 강물의 표면 유속 측정 본문
1. 프로젝트 개요
- 목표 : 카메라로 촬영된 강물 영상에서 표면 유속을 계산
- 도구 : Vision AI (예: OpenCV, TensorFlow, YOLO 등)와 실시간 영상 처리
- 방법 : 강물 표면의 움직이는 물체(예: 부유물, 파문 등)를 추적하여 속도를 측정
- 적용 기법 : 광학흐름 (Optical Flow) 방식, 부유물 객체 감지 방식 두 방식을 개별 혹은 동시 적용 (보정)
2. 혼용 방식의 기본 개념
- YOLOv11 기반 부유물 추적
- 부유물(나뭇잎, 잔해물 등)을 객체로 감지하고, 프레임 간 이동 거리를 계산하여 속도를 측정
- 장점: 명확한 객체를 기반으로 속도를 계산하므로 직관적이고 정확도가 높음
- 단점: 부유물이 없는 경우 적용 불가
- Optical Flow 기반 유속 측정
- 전체 픽셀의 움직임을 분석하여 평균 유속을 계산
- 장점: 부유물이 없어도 강물의 흐름을 측정 가능
- 단점: 빛 반사나 노이즈에 민감할 수 있음
- 혼용 전략:
- 부유물이 감지되지 않을 경우 : Optical Flow만 사용
- 부유물이 감지될 경우 : YOLOv11 기반 속도와 Optical Flow 속도를 비교하거나 평균을 내어 보정
적용 기법에 두 가지 기법을 함께 사용하려는 것은 각각이 가진 장점이 있는데 이를 서로의 측정치를 보정하는 용도로 기능 자체는 넣어두기 위함입니다. 예를 들어 YOLOv11은 부유물(특정 객체)을 감지하고 추적하는 데 강점이 있고, Optical Flow는 전체적인 흐름 패턴을 분석하는 데 유리하므로, 이 둘을 보완적으로 사용하면 신뢰성을 높일 수 있을 거라 생각한 것이죠.
3. 필요한 구성 요소
1️⃣ 하드웨어
- 강물을 비추는 고정된 카메라 (예: 웹캠, IP 카메라 등)
- 카메라는 충분한 해상도와 프레임 속도(FPS)가 지원되어야 함
2️⃣ 소프트웨어
- Python (영상 처리 및 AI 작업에 적합)
- OpenCV (실시간 영상 처리 및 객체 추적)
- (선택) 머신러닝 프레임워크 (필요 시 특정 물체 인식에 활용)
3️⃣ 알고리즘
- 광학 흐름(Optical Flow) 또는 객체 추적 알고리즘
4. 구현 단계
1) 영상 데이터 수집
- 카메라를 통해 실시간으로 강물 표면을 촬영합니다.
OpenCV를 사용해 직접 연결된 기본 카메라 혹은 IP 카메라의 RTSP 스트림을 이용합니다.
2) 속도 계산 (Optical Flow)
- 픽셀 단위 속도 → 실제 속도 변환:
- 카메라의 시야각(FOV)과 강물까지의 거리를 알아야 합니다.
- 예: 1초에 픽셀이 50만큼 이동하고, 1픽셀이 0.02m라면 유속은 1m/s
- 계산 공식
3) Vision AI 활용
- 부유물을 객체로 인식하기 위해 YOLO v11 모델을 이용합니다. (SSD와 같은 다른 모델도 가능합니다)
- 사전 학습된 모델을 fine-tuning하여 강물 속 부유물을 탐지하도록 훈련해야 합니다.
사실 이걸 제대로 하지 않으면 부유물 자체를 감지할 수 없게 됩니다... 흠... 기본 모델로 해 보려는데 제대로 되는지만 확인하겠습니다. - 객체의 위치 변화를 추적하여 속도를 계산합니다.
5. 고려 사항
- 카메라 캘리브레이션 : 정확한 속도를 위해 카메라의 초점 거리와 시야각을 측정해야 합니다.
- 조명 조건 : 강물 표면은 빛 반사로 인해 노이즈가 생길 수 있으니 필터링(예: Gaussian Blur) 사용을 고려해야 합니다.
- 실시간 성능 : 고해상도 영상은 처리 속도를 느리게 할 수 있으니 적절한 해상도를 선택하는 것이 좋습니다.
6. 테스트 (코드)
1) 환경 구성
$ pip install opencv-python ultralytics
2) 혼용 알고리즘 설계
- 프레임별로 YOLOv11을 실행해 부유물을 감지
- 부유물이 있으면 추적하여 속도를 계산
- 동시에 Optical Flow로 전체 흐름 속도를 계산
- 상황에 따라 두 값을 선택하거나 결합
3) 코드
Optical Flow를 이용하는 방식의 경우 코드는 다음과 같습니다.
import cv2
import numpy as np
from ultralytics import YOLO
import time
from collections import deque
# YOLOv11 모델 로드
model = YOLO("yolo11x.pt") # 실제 모델 경로로 변경 필요
# 비디오 파일 열기
cap = cv2.VideoCapture('1.mp4')
cap.set(cv2.CAP_PROP_POS_MSEC, 48000) # 48초 지점부터 시작
ret, prev_frame = cap.read()
if not ret:
raise RuntimeError("비디오를 읽을 수 없습니다.")
prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)
# 설정값
PIXEL_TO_METER = 0.12 # 추후 캘리브레이션 필요
prev_objects = {}
prev_time = time.time()
flow_speeds = deque(maxlen=10) # 2초 평균용
cv2.namedWindow("River Flow")
while True:
ret, frame = cap.read()
if not ret:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
current_time = time.time()
dt = current_time - prev_time
prev_time = current_time
results = model(frame, verbose=False)
yolo_speed = None
current_objects = {}
for r in results:
boxes = r.boxes.xyxy.cpu().numpy()
for box in boxes:
x1, y1, x2, y2 = box
center_x, center_y = (x1 + x2) / 2, (y1 + y2) / 2
obj_id = f"{int(center_x)}_{int(center_y)}"
if obj_id in prev_objects:
prev_x, prev_y = prev_objects[obj_id]
dist_pixels = np.hypot(center_x - prev_x, center_y - prev_y)
yolo_speed = dist_pixels * PIXEL_TO_METER / dt # m/s
current_objects[obj_id] = (center_x, center_y)
# Optical Flow
flow = cv2.calcOpticalFlowFarneback(prev_gray, gray, None,
0.5, 3, 15, 3, 5, 1.1, 0)
magnitude, _ = cv2.cartToPolar(flow[..., 0], flow[..., 1])
flow_speed = np.mean(magnitude) * PIXEL_TO_METER / dt
flow_speeds.append(flow_speed)
avg_flow_speed = np.mean(flow_speeds)
# 최종 유속 결정
final_speed = flow_speed
if yolo_speed is not None:
final_speed = (yolo_speed + flow_speed) / 2
# 출력
print(f"최종 유속: {final_speed:.2f} m/s (YOLO: {yolo_speed}, Flow: {flow_speed:.2f}, 평균 Flow: {avg_flow_speed:.2f})")
# 시각화
cv2.putText(frame, f"Speed: {final_speed:.2f} m/s", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
cv2.putText(frame, f"Avg Flow: {avg_flow_speed:.2f} m/s", (10, 60),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 0), 2)
cv2.imshow("River Flow", frame)
prev_gray = gray
prev_objects = current_objects
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
elif key == ord('s'):
cv2.waitKey(0)
cap.release()
cv2.destroyAllWindows()
4) 보정 전략
- 부유물 유무에 따른 선택
- 부유물 없음: final_speed = flow_speed
- 부유물 있음: YOLO와 Optical Flow 값을 결합
- 값 결합 방법
- 평균 내기 : (yolo_speed + flow_speed) / 2
- 가중치 평균 : YOLO가 더 신뢰할 만하다면 가중치를 조정 (예: 70% YOLO + 30% Flow)
- 오차 범위 확인 : 두 값의 차이가 크면 더 신뢰할 만한 값을 선택 (예: Optical Flow가 비정상적으로 크면 YOLO 값만 사용)
- 신뢰도 기준
- YOLO의 confidence score를 활용해 부유물 감지의 신뢰도를 판단
- Optical Flow의 magnitude 분산이 크면 노이즈가 많다고 간주하고 신뢰도 하락
5) 테스트 영상
찍으려니 가까운데 딱 맞는 곳이 없고... 그래서, 유튜브를 뒤졌는데 영상 구하는 게 어려웠습니다. -_-; 그나마 하나 찾은 것도 같은 목적으로 비전 기반의 수위측정, 유속 측정을 하는 AI 업체의 AI 적용 결과였습니다. 오호... 수위는 게이지에서 읽은 것이라치고 유속은 측정된 것이 있으니 이걸로 비교하면 되겠다 싶었습니다.
- 카메라와 지점까지의 거리나 FOV 등을 알 수 없기 때문에 일단 화면 상에 측정된 실제 속도와 Optical Flow를 이용해 나온 수치를 매칭해서 대략적인 픽셀 간 거리를 지정했습니다. (픽셀간 0.12m)
- 테스트 영상) (유속계측) 인공지능 기술에 의해 '22년 판교 운중천 홍수기 빠른 유속을 실시간으로 정확히 계측하는 영상 (WaterAI 유튜브 영상, 2023.5)
6) 결과 분석
1️⃣ 측정값
- AI업체에서 측정한 실제 측정값은 2.679 m/s -> 거의 변화하지 않는 것으로 봐선 특정 시간 동안의 평균치를 구하는 방식으로 되어 있지 않나 싶었습니다.
- 일반 Optical Flow 기반 측정값은 프레임 간 속도는 2.36 m/s, 10 프레임 평균값은 2.46 m/s
추가로 Optical flow의 평균과 표준편차를 계산해, 이상치 (Threshold 이상 속도)를 가진 벡터만 필터링해서 측정하는 방식(Dense Optical Flow)을 적용하면 다음과 같이 나왔습니다. (프레임 간 2.61m/s, 2초 평균 2.51 m/s)
2️⃣ 의견
- 픽셀간 거리에 대한 캘리브레이션을 정밀하게 맞출 필요는 있음 -> 카메라 FOV와 실제 지점까지의 거리 측정을 통해 이뤄질 수 있음
- Yolo11X 모델을 사용했음에도 불구하고 학습 때 정의되지 않은 객체에 대한 감지가 되지 않았음 -> 결과적으로 OpticalFlow 방식의 속도 측정만 됨 (아래 이미지)
7. 추가 개선 방안
- YOLO 모델 Fine-Tuning : 강물 부유물(나뭇잎, 플라스틱 등)에 맞게 모델을 재학습시켜 정확도를 높임
- 객체 추적 알고리즘 결합 : YOLO에 SORT나 DeepSORT를 추가해 부유물의 프레임 간 추적을 개선
- 노이즈 필터링 : Optical Flow 결과에 Gaussian Blur나 thresholding 적용
8.참고자료
- 영상) 파도나 바람의 영향을 최소화해 유속을 측정하는 유속 맞춤 측정 GPS 플로터 (유속 측정기, GPS 플로터, 초음파 유량계) (한국기술마켓 채널)
- 영상) 한국수자원조사기술원 교육동영상(전자파표면유속계 측정) (한국수자원조사기술원 채널)
- 영상) 비접촉식 유속계 및 초음파센서를 활용한 하천 유량 및 유사량 조사기술 개발 (한국수자원조사기술원)
- 영상) AI 기술 실증 테스트베드 활용 과제(⑥CCTV 영상을 활용한 AI 기반 재난 방재) (NIPA)
- 영상) CCTV 기반 실시간 소하천 자동유량계측 기술 (하이드로셈)
- 제품) 야간 측정을 위한 EIZO의 초고감도 카메라 제품 사례 (링크)
- 논문) Technical Note: Flow velocity and discharge measurement in rivers using terrestrial and unmanned-aerial-vehicle imagery (링크)
- 논문) Adaptively monitoring streamflow using a stereo computer vision system (링크)
유속 측정은 다소 이 분야의 전문적인 영역일 겁니다. 전문 업체에서 사용하는 방식은 제가 시도한 것과는 달리 좀 더 정교한 수식과 레이저 센서 등을 이용해 수집한 실제 수치 데이터를 이용한 보정, 학습 등이 적목되어 있을 것입니다. 그러니 위의 시도는 대충 이런 방식으로 할 수 있지 않을까 하는 아이디어 차원으로 봐 주시면 좋겠습니다.
현재는 정말 단순한 코드로 되어 있는데 나중에 실제로 측정해야 하는 필요성이 생기면 그때는 좀 더 다른 아이디어들을 결합해서 해 봐야겠습니다. ^^;
'DIY 테스트' 카테고리의 다른 글
뉴스 타이틀 추출 및 워드 클라우드 생성기 만들기 (0) | 2025.04.28 |
---|---|
감성과 기능을 더한 틀린 그림 찾기 게임, 바이브 코딩으로 구현하다 (2) | 2025.04.25 |
로컬 LLM과 LM Studio API 기능을 이용한 간단한 어플리케이션 (0) | 2025.04.17 |
DeepSite로 만든 사다리타기 게임, 저도 Vibe Coding 한번 해봤습니다 (0) | 2025.04.15 |
[코딩] 초간단 청기 백기 게임 만들어보기 (0) | 2025.04.03 |