[프로젝트]python 프로젝트 오류 #1

YongHo·2024년 3월 21일

레이더 센서와 카메라 모듈을 함께 사용하여, 객체로 인식을 하여 감지되었다고 알림을 주면 카메라 모듈로 장면을 촬영해 저장하는 프로젝트를 진행중에 있었다. 왜 이렇게 감지됐을 때의 카메라 찍힌 걸 보면 아무것도 없지? 너무 안 맞는데 라는 생각으로 코드를 다시 보기로 했다.

기존에는, Main Loop 따로, 카메라 프레임 읽어오는 쓰레드 Loop 따로 작동을 시키고 있었다. 그러다 문뜩 '왜 이렇게 계속해서 프레임을 읽어와야하는거지?, 이러면 더 CPU 사용량이 많아지는거 아니야? 괜히 발열이 심할 것 같은데?' 라는 생각과 함께 레이더 센서가 객체로 인식을 했을때만 read를 해주면 되잖아! 라고 생각하여, 진행하였다.
결론은 문제가 심했다라는거다.

일단 기본적인 OpenCV 카메라 웹캠 읽어오는 코드를 작성해보겠다.

1. OpenCV 웹캠 읽어오기 기본 예제

cap = cv2.VideoCapture(0)            # 카메라 캡처 객체 생성
width = cap.set(cv2.CAP_PROP_FAME_WIDTH, 640)     # 카메라 넓이 지정
height = cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)   # 카메라 높이 지정

if cap.isOpened() :
   while True :
      ret, frame = capture.read()
      cv2.imshow('ExampleVideo', frame)
cap.release()
cv2.destroyAllWindows()
'''

나는 위 예제를 보면서 루프 안에서 반복하면서 read로 프레임을 읽어오고, 기존의 프레임을 덮어 씌워주는구나 라는 생각을 했고, Main Loop와 카메라 쓰레드를 별도로 돌려 객체 인식을 했을 경우에만 이미지를 저장해주게끔 코딩을 했었다. 그러다 발열도 심해지고 죽어버려서 뭐가 문제인지 보던 도중에 "왜 프레임을 계속해서 읽어와야하지?", 이러면 CPU는 더 일을 하게 되는거 같은데?" 라는 생각과 아래와 같이 코딩을 재작성 했다. 아래는 코드의 일부분이다.

2. 내가 작성한 OpenCV 웹캠 읽어오는 코드

while True :
   try :
      if totalDetectLength > noCatchObject :
         ret, frame = CameraModule.read()
      ... ( 내부 생략 )
      if detect == 1 :
         cv2.imwrite( filename, frame )
      ... ( 내부 생략 )
      time.sleep(10)
'''

위에는 time.sleep(10)을 넣어줬지만 실제 코드에서는 다른 방식으로 10초 정도 쉬기 때문에 대체해서 넣었놓았다. 나는 객체가 인식되면 카메라 프레임을 읽어오게끔 해놨으니 이제 사진도 저장 잘 되고, 문제가 없겠지?! 라는 생각으로 코드를 돌려보았다.

3. 코드 변경 결과

내가 생각했던 것과 아주 반대로 나왔다..
일단 사진 자체가 뭐 적게는 몇 분 많게는 몇 시간 전 프레임을 찍어서 놓는것 아니겠는가.. 왜 그럴까 하며 찾아본 결과 생각보다 답은 간단했던 것 같다..
결론적으로 time.sleep()을 걸어 시스템을 멈추어도 OpenCV.videoCapture함수는 내부 버퍼에 프레임을 쌓는다고 한다. 그래서 sleep() 이후에 프레임을 가져다 쓰려고 해도 전에 쌓인 프레임 데이터부터 read하고 있던 것이다!

4. 회고

다시 기존 코드처럼 쓰레드를 돌려주고 대신 timer를 줘서 조금씩 딜레이 줘 실행시키니 그나마 조금 괜찮아진 것 같다.

def emptyRead(cap):
    if cap.isOpened() == False:
        print('saveImage closed the cam')
        cap = initCam(0, 1024, 768)
        if cap.isOpened() == False:
            return None
    
    ret, frame = cap.read()  # capture frame
        
    if frame is None:
        closeCam(0)
        print('saveImage frame is not exist')
        return None
    
    if ret != True:
        closeCam(0)
        print('saveImage Fail to get image frame')
        return None

def captureCam():
    global CameraModule
    
    videoCapture.emptyRead(CameraModule)
    timer=threading.Timer(0.1,captureCam)
    timer.start()
    
def main():

    #카메라 캡쳐 쓰레드 (0.1초마다 동작)
    t4 = threading.Thread(target=captureCam, args=())
    t4.start()

	... # 내부 자체 코드
    print('run service')

    while True:
    ... # 메인 루프

아직 많이 멀었지만 내가 상상하지 못했던 에러를 알게되어서 신기하고 놀라웠다. 나는 당연히 내 코드에서 문제가 있을거라고 생각했다. 아 물론 내 코드가 문제인건 맞지만 구체적인 원인이 하드웨어와 연관되어 있을거라고는 생각하지 못했다. 이 외에도 사실 문제들이 좀 더 있지만 차근차근 알아가보려 한다!

OpenCV 함수 참고 자료
https://docs.opencv.org/3.4/d8/dfe/classcv_1_1VideoCapture.html#a85b55cf6a4a50451367ba96b65218ba1

0개의 댓글