어찌어찌 올해가 넘어가는중...
거의 막바지에 새로운 먼가를 하기위해 또 배워가는중!
그래서 이번엔 이미지 Warping에 대해서 알아보려 합니다.
그렇게 막 어렵거나 긴 내용은 아니지만, 작성한 코드부분도 있고, 이런 부분도 있구나... 싶어서 작성합니다!
그럼 시작!
먼저 Warping이란...?
특정한 이미지나 마크가 기울어지거나, 크기가 변한다던가... 일그러진다거나!
인식에 불편한 부분들이 생기게 될때 이를 재배열하여 정규화 하는 기법입니다.
...음... 아래처럼 특정 부분을 어디에서 찍느냐에 따라 완전히 다르게 보이기에 이 부분을 해결하기 위해 개발된 기법!
(사람은 구분가능하지만, 컴퓨터는 ....멍..)
이 부분에 대해서도 다양한 방법들이 존재하고, 완전히 일그러진 이미지에 대해서도 복원시키는걸 보니...
공부가 많이 필요할듯 하네요... (아래는 참고 블로그!)
그래서 일단은 접어두고..... 진행하던 부분에 대해서 마저 진행해 보았습니다!
저에게 필요한 부분은....
빔 프로젝터와 그에 맞게 설치된 탑뷰 웹캠을 통해 영상을 녹화할때,
프로젝터의 각도와 위치, 상관없이 정확한 영상의 정보만을 받아오기위한 이미지 워핑 방식이 필요했습니다.
물론 이 정도는 프로젝터를 이동 시키면 충분히 맞춰 볼 수 있겠지만,
프로젝터가 이동될 수도 있고, 흐트러질 수 도 있다고 판단하여 찾아보게 되었습니다!
그래서 위의 블로그들을 찾아보게 되고... 생각보다 어렵겠다고 생각하였지만....
이미 제가 원하는 정도의 warping은 Python의 OpenCv에 구현이 되어있어, 매우 쉽게 구현할 수 있었습니다!
그럼 일단 코드부터!
코드 자체는 간단하긴 한데, 제 실험환경에 맞춰 구성했기에... 불필요한 부분에 대해서는 수정해서 사용해주세요!
코드 실행 순서는 다음과 같습니다.
1. 웹캠의 첫번째 프레임을 받아온다
2. 그 프레임을 통해 각 빔 프로젝터의 꼭짓점을 체킹해준다.
3. 새로운 창에 웹캠의 영상을 Warping하여 출력한다.
가장 먼저 웹캠을 받아오는 부분은 웹캠의 해상도 부분과 전체화면으로 열어주는 부분만 추가해 주었습니다.
import cv2
import numpy as np
import asyncio
# 마우스 클릭으로 얻은 점들 저장
points = []
....
# 메인 실행 함수
async def Asy_main():
global frame_copy
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Cannot open webcam")
return
frame_width = 1280
frame_height = 960
cap.set(cv2.CAP_PROP_FRAME_WIDTH, frame_width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, frame_height)
ret, frame = cap.read()
if not ret:
cap.release()
return
window_name = "CheckPoint"
cv2.namedWindow(window_name, cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
frame_copy = frame.copy()
cv2.imshow(window_name, frame_copy)
# 초기 화면 출력
cv2.imshow(window_name, frame_copy)
cv2.setMouseCallback(window_name, get_points)
그리고 웹캠의 장면에서 꼭짓점을 체킹해주는 부분에서는 점을 4개찍을때까지 대기하게 만들고,
이 점들이 실제로 화면에 표시되게끔 구성해 주었습니다.
def get_points(event, x, y, flags, param):
global points
if event == cv2.EVENT_LBUTTONDOWN:
if len(points) < 4:
points.append((x, y))
......
# 마우스 클릭으로 4개의 점을 얻을 때까지 대기
while len(points) < 4:
cv2.imshow(window_name, frame_copy)
await asyncio.sleep(0.01)
마지막으로 Warping하는 부분에서는 앞선 4개의 지점을 토대로 웹캠의 영상을 계속해서 Warping하고
그 결과이미지의 크기에 맞춰 화면을 새로 출력해주었습니다.
# Warping 처리 함수
def perform_warping(frame, points, w, h):
src_pts = np.array(points, dtype=np.float32)
dst_pts = np.array([[0, 0], [w, 0], [w, h], [0, h]], dtype=np.float32)
trans_mat = cv2.getPerspectiveTransform(src_pts, dst_pts)
warped_image = cv2.warpPerspective(frame, trans_mat, (w, h))
return warped_image
def WarpingCalculate():
w_Cal = max(abs(points[0][0] - points[1][0]), abs(points[2][0] - points[3][0]))
h_Cal = max(abs(points[0][1] - points[2][1]), abs(points[1][1] - points[3][1]))
return w_Cal, h_Cal
.....
# Warping 계산된 크기
w, h = WarpingCalculate()
# 실시간 Warping 처리
while True:
ret, frame = cap.read()
if not ret:
cap.release()
cv2.destroyAllWindows()
return
warped_image = perform_warping(frame, points, w, h)
cv2.imshow("Warped Image", warped_image)
# ESC 키로 종료
if cv2.waitKey(1) & 0xFF == 27:
cap.release()
cv2.destroyAllWindows()
return
# asyncio 실행
if __name__ == "__main__":
asyncio.run(Asy_main())
아래는 결과!
(조명때문에... 웹캠에서 아래처럼 찍히네요...)
워핑에 주요 함수! warpPerspective()함수의 내용은 아래에서!
개념과 심화 부분은 많이 어려웠지만...
특정 지점들을 통해 재배열하고 원본이미지나, 원하는 데이터로써 정규화 시킨다는 부분이 핵심인 것 같습니다!
위 코드는 4개의 지점만을 사용했지만, 이 부분이 늘어나면 늘어날수록 좀 더 정교하게 재배열할 수 있을것 같네요..
일단 이번글은 여기서 끝!
'공부공부 > 2024 쌓여가는 나의 지식~' 카테고리의 다른 글
구글 폼(Google Forms)을 이용한 설문지 사용 방법 (0) | 2024.12.17 |
---|---|
Pc 게임 개발 프로젝트 [Die and Dice] 1차 진행 상황 (2) | 2024.10.24 |
[Blender]블렌더를 이용해 리깅 작업 (Robot Arms 리깅) (0) | 2024.10.20 |
스팀(STEAM) 게임 출시를 위한 준비 준비! [1]- 스팀 개발자 (STEAM WORKS) 등록 절차 (9) | 2024.09.03 |
[AI생성] 생성형 AI를 이용한 3D 오브젝트생성 및 애니메이션 적용 - [Rodin.ai / Mixamo] (0) | 2024.08.17 |
댓글