MediaPipe와 Selenium을 이용해서 웹 CCTV 영상속 고양이 포착하기

  • MediaPipe 유용하게 쓰고 있나요? 저는 이것 저것 잘 쓰고 있습니다.
  • 물체인식이나 이미지분류, 얼굴인식, 얼굴 표시게 인식 등 정말 잘 쓰고 있어요.
  • 그 중에서도 오늘은 물체인식(Object Detection)에 관한 내용입니다.
  • 예전에 Flutter를 이용해서 비슷한 이슈를 다룬적이 있으니 아래 링크 참고해주시면 감사하겠구요.
  • 오늘은 이미 만들어져 있는 DIY CCTV 웹 모니터링 화면을 Selenium Webdriver를 이용해서 캡쳐한 다음
  • 캡쳐 화면속에 고양이가 있으면 해당 화면의 사진을 저장하는 프로그램을 만들어 봤습니다.
  • 매우 간단하니까 한 번 코드리뷰를 해봐주시면 감사하겠습니다.

  • CCTV는 라즈베리파이를 이용해서 자작한 건데요. 이것과 관련한 사연은 아래 블로그 글과 유튜브 영상을 참고해주세요.
  • 원격에서 확인할 수 있도록 만들어진 CCTV 모니터링 페이지에 접속하면 이런 화면이 나타납니다.
    • 화면
    • 위와 같이 고양이가 있으면 캡쳐해서 저장하면 되는거에요.
  • 코드는 아래와 같습니다. 아주 간단하죠??
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep
import mediapipe as mp
from mediapipe.tasks import python
from mediapipe.tasks.python import vision

options = Options()
# 브라우저 창을 띄우지 않고 처리 합니다.
options.add_argument("--headless")

driver = webdriver.Chrome(options=options)

# 모니터링 페이지의 URL이 들어갑니다.
driver.get("http://")

# https://storage.googleapis.com/mediapipe-models/object_detector/efficientdet_lite0/int8/1/efficientdet_lite0.tflite 파일을 다운로드 해서 이름만 바꿨어요.
base_options = python.BaseOptions(model_asset_path='cat.tflite')
options = vision.ObjectDetectorOptions(base_options=base_options,
                                       score_threshold=0.5)
detector = vision.ObjectDetector.create_from_options(options)
i = 0
while True:
    # 5초마다 수행됩니다.
    sleep(5)
    driver.save_screenshot("screenshot.png")
    image = mp.Image.create_from_file("screenshot.png")
    detection_result = detector.detect(image)
    if len(detection_result.detections) > 0 and \
            detection_result.detections[0].categories is not None:
        for item in detection_result.detections[0].categories:
            # cat이 들어가면 일단 걸립니다. 판독가능한 레이블에 cat이란 단어가 들어가는건 말그대로 cat 밖에 없기 때문에 == 을 써도 무방합니다.
            # 레이블 리스트 : https://storage.googleapis.com/mediapipe-tasks/object_detector/labelmap.txt
            if 'cat' in item.category_name:
                print(item.category_name)
                i = i + 1
                driver.save_screenshot("screenshot_%s.png" % i)
                break

AWS API-GATEWAY에서 이미지 파일을 읽어보자

  • API-GATEWAY를 통해서 Rest API를 구현할 경우 기본적으로 텍스트 형태의 반응값을 받게 됩니다.
  • 그런데 프록시 서버등을 통해서 이미지 파일을 그대로 전달받는 경우, 결과가 이진(BINARY) 데이터여야만 하죠
  • 이럴 때 설정을 어떻게 하는지 소개해보고자 합니다.
  • 먼저 API 설정 메뉴로 가주세요.

STEP1

  • 거기서 이진 미디어 유형 관리를 선택해주세요. 그런 다음 아래처럼 image/png를 입력해주세요.

STEP2

  • 그런 다음에 해당 리소스 상의 메소드에서 “메서드 응답” 탭으로 이동합니다. 편집을 클릭해서 아래와 같이 입력합니다.
    • 이렇게 Content-Type을 설정해 줘야 합니다.

STEP3

  • 마지막으로 “통합 응답” 택에서 편집을 클릭해주세요.
    • 콘텐츠 처리를 “이진으로 변환”으로 지정하고
    • 아까 입력한 Content-Type을 ‘image/png’로 입력해주세요. 여기서 중요한 점은 작은따옴표를 함께 입력한다는 점 입니다.

STEP4

  • 그러면 이미지가 온전히 전달되는 것을 확인 할 수 있습니다.

STEP5

  • 제대로 설정이 되지 않으면 {"message": "Internal server error"}가 출력된다던가, 이진 파일이 텍스트로 출력되는 결과가 나타날수도 있으니 위 과정을 그대로 따라해주세요.

파이썬에서 이미지 파일의 진짜 속성을 알아보자

  • 이미지를 이용하는 서비스를 운영하는 경우 정말 다양한 확장자의 이미지 파일들을 다루게 되는데요.
  • 대표적인 이미지 타입인 PNG,JPG는 물론이거니와 최근에 많이 사용하는 HEIC나 WEBP등의 파일도 처리해야 하는 경우가 있습니다.
  • 이와 관련해서는 제 블로그에 포스팅을 남긴바가 있죠.
  • 그런데 간혹가다가 확장자는 PNG인데 파일의 진짜 속성은 그렇지 않은 파일이 업로드되는 경우도 경험하게 됩니다.
  • 즉, 파일의 확장자만 믿고 해당 파일타입으로 이미지를 로딩하면 문제가 발생할 수 있다는 의미입니다.
  • 이럴때 파이썬에서 사용할 수 있는 방법들이 몇 가지 있는데요. 먼저 내장된 패키지인 mimetypes를 생각해 볼 수 있을겁니다.
    • 아래 이미지를 heic, jfif, webp, jpg, png 형태로 각각 저장하여 mimetypes를 이용해서 파일속성을 판단해 보겠습니다.
      • 사용이미지
    import mimetypes

    print("\n\nUse Mimetypes\n")
    print(mimetypes.guess_type("./test/imgs/1.heic"))
    print(mimetypes.guess_type("./test/imgs/2.jfif"))
    print(mimetypes.guess_type("./test/imgs/3.webp"))
    print(mimetypes.guess_type("./test/imgs/4.jpg"))
    print(mimetypes.guess_type("./test/imgs/5.png"))
  • 이러면 결과는 아래처럼 나타납니다.
    Use Mimetypes
    
    (None, None)
    (None, None)
    (None, None)
    ('image/jpeg', None)
    ('image/png', None)
    
  • 결과를 보면 PNG, JPG를 제외하고는 속성 파악을 못하는 것으로 확인되는데요.
  • 그렇다면 heic, jfif, webp를 png로 확장자만 바꾸고 같은 소스를 실행하면 어떻게 될까요?
    Use Mimetypes
    
    ('image/png', None)
    ('image/png', None)
    ('image/png', None)
    ('image/jpeg', None)
    ('image/png', None)
    
  • 세 경우 모두 확장자인 PNG로 인식하게 됩니다. 즉, 진짜 이미지의 파일속성을 알고 싶다면 mimetypes는 쓰지 않는게 좋아요.

  • 다음으로 imghdr을 이용해서 확인해 봅시다.
    • 같은 이미지를 사용했구요, png로 바꾼 세개의 파일도 그대로 사용합니다. 아래처럼 소스코드를 작성해보았습니다.
      import imghdr
      
      print("\n\nUse Imghdr\n")
      print(imghdr.what("./test/imgs/1.png")) #원래 heic
      print(imghdr.what("./test/imgs/2.png")) #원래 jfif
      print(imghdr.what("./test/imgs/3.png")) #원래 webp
      print(imghdr.what("./test/imgs/4.jpg"))
      print(imghdr.what("./test/imgs/5.png"))
      
    • 그리고 결과는 다음과 같습니다.
      Use Imghdr
      
      None
      jpeg
      webp
      jpeg
      png
      
    • imghdr은 heic는 파악하지 못하는 것으로 보이구요, jfif는 JPG의 변형판 같은거라 같은 JPG로 나옵니다.
  • heic를 파악하지 못하는 아쉬움으로 인해 다른 대안을 찾아봐야 겠군요. python-magic을 사용해 봅시다.
    • 이번에도 역시 같은 이미지를 사용했습니다.
      import magic
          
      print("Use Magic\n")
      print(magic.from_file("./test/imgs/1.png", mime=True)) #원래 heic
      print(magic.from_file("./test/imgs/2.png", mime=True)) #원래 jfif
      print(magic.from_file("./test/imgs/3.png", mime=True)) #원래 webp
      print(magic.from_file("./test/imgs/4.jpg", mime=True))
      print(magic.from_file("./test/imgs/5.png", mime=True))
      
    • 결과를 보면 다음과 같습니다.
      Use Magic
      
      image/heic
      image/jpeg
      image/webp
      image/jpeg
      image/png
      
    • 다행이군요, python-magic은 heic까지 판별해냅니다.