기계 학습 중 공유 공간 이용 상황의 해석

계기.


내가 일하는gifte 사무실은 2017/05/08로 옮겼다.
새 사무실에는 소파석, 가정식당석 등이 있다
다양한 유형의 공유 공간을 늘렸다.
https://www.wantedly.com/companies/giftee/post_articles/64703
따라서 어떤 유형의 공유 공간이 얼마나 많이 이용되었는지 파악하고 싶다
의 요구로 상황을 이용한 획득 방법을 논의하기로 했다.

탐구하다


사용 상황을 파악하는 데 있어서 인감 센서, 감압 센서 등을 사용하는 것도 후보가 되었다
인감 센서로는 인원수에 도달할 수 없다
감압 센서는 좌석마다 센서가 필요하다
공유공간마다 정기적으로 사진을 찍어 그곳에서 찍은 사람의 수를 측정한다.

인원수 분석 방법


그림에서 인원을 얻는 것에 관해서는 기계 학습 프레임워크를 사용하기로 결정했다.
이번에는
· 이미 학습한 데이터 공개
• 사용 방법이 간단하다
의 두 점은darknet을 사용하기 시작한다.

darknet


설치하다.


설치는 매우 간단합니다.github에서clone에서make를 실행하기만 하면 됩니다.
git clone https://github.com/pjreddie/darknet
cd darknet
make
학습이 끝난 가중 데이터를 다운로드하면 준비가 완료된다.
wget https://pjreddie.com/media/files/yolo.weights

이미지 분석


darknet 옵션에서detect를 지정하여 config, 데이터, 대상 사진을 상대방에게 건네줍니다.
소스에는 데이터/person이 포함되어 있습니다.jpg에 대한 해석은 다음과 같다.
./darknet detect cfg/yolo.cfg yolo.weights data/person.jpg
결과는'predictions.png'이라는 이름으로 같은 층으로 출력됩니다.

원본 이미지



분석된 이미지



인원수 획득 방법


데이터 네트워크의 해석 결과는 표준 출력에서도 다음과 같이 출력된다.
data/person.jpg: Predicted in 14.067749 seconds.
person: 86%
horse: 82%
dog: 86%
이번에는 단순히 표준 출력의 개인 그린으로 계산하는 방식으로 그림의 인원수를 얻었다.
./darknet detect cfg/yolo.cfg yolo.weights data/person.jpg | grep person | wc -l

시스템의 전체 프로세스


이번에 제작된 시스템은 크게 세 단계로 나뉜다.
1. 아이폰으로 주기적으로 대상구역 간격을 두고 S3에 올리기
2. 크론 모바일 분석 스크립트를 통해 정기적으로 사진 속 인원수 얻기
DynamoDB에 insert 확보
3.re: DynamoDB의 데이터를 Dash로 시각화

1단계


@koh518 아이폰 앱을 이용해 공유 공간을 일정 간격으로 촬영한다.(이번엔 5분 간격으로)
아이폰의 받침대가 고정되지 않아 머그컵에 넣어 고정한다.

촬영한 이미지가 S3에 업로드됩니다.
S3의 키 이름은'공유 공간 이름/시간.jpeg'(e.g dining/20170620131500.jpeg)이다.

2단계


cron에서 시작한 분석 스크립트에서 S3에 누적된 이미지를 순서대로 꺼내 인원수 분석을 합니다.
그러나darknet에서 jpeg의 exif의oricontation 정보를 식별할 수 없기 때문에
ImageMagick의 convert 명령을 사용하여 올바른 방향으로 변환합니다.
convert iphone.jpg -auto-orient converted.png
이렇게 하지 않으면 가로 분석의 정밀도가 상당히 떨어질 것이다.
그리고 변환된 이미지를darknet에 건네주고 개인 계수를 얻습니다.
./darknet detect cfg/yolo.cfg yolo.weights ../converted.png | grep person | wc -l
이미지 분석은 다음과 같습니다.

원본 이미지



분석 후



보라색 테두리가 겹쳐 이해하기는 어렵지만, 정확한 퍼슨은 3명으로 여겨진다.
이 인원을 insert에서 DynamoDB로 옮겨라.
분석이 끝난 이미지는 다른 S3 세그먼트로 이동합니다.
분석된 출력 이미지는 이후 유효성 검사를 위해 S3에도 함께 업로드됩니다.
이번 단계 2는 싸이혼 스크립트로 진행됐습니다.
소스는 아래와 같다.
import boto3
import botocore
import subprocess
import os
import subprocess

BUCKET_NAME = os.environ["BUCKET_NAME"]
BUCKET_NAME_DONE = os.environ["BUCKET_NAME_DONE"]
DYNAMODB_REGION = os.environ["DYNAMODB_REGION"]
DYNAMODB_TABLE = os.environ["DYNAMODB_TABLE"]

s3 = boto3.resource('s3')
bucket = s3.Bucket(BUCKET_NAME)
client = boto3.client('s3')

for obj in bucket.objects.all():
    key = obj.key
    shared_space_name, filename = key.split('/')

    # "prefix/"のobjectも取得してくるのでskip
    if not filename:
      continue

    created_at, extention = filename.split('.')

    # download
    s3.Bucket(BUCKET_NAME).download_file(key, 'iphone.jpg')

    command = "convert iphone.jpg -auto-orient converted.png"
    proc = subprocess.Popen(
      command,
      shell  = True,
      stdin  = subprocess.PIPE,
      stdout = subprocess.PIPE,
      stderr = subprocess.PIPE)

    stdout_data, stderr_data = proc.communicate()

    # yolo
    command = "cd darknet;./darknet detect cfg/yolo.cfg yolo.weights ../converted.png | grep person | wc -l"
    proc = subprocess.Popen(
      command,
      shell  = True,
      stdin  = subprocess.PIPE,
      stdout = subprocess.PIPE,
      stderr = subprocess.PIPE)

    stdout_data, stderr_data = proc.communicate()

    value = int(stdout_data.decode('ascii'))

    # insert dynamo
    dynamodb = boto3.resource('dynamodb', region_name=DYNAMODB_REGION)
    table = dynamodb.Table(DYNAMODB_TABLE)

    resposne = table.put_item(
      Item = {
        'shared_space_name' : shared_space_name,
        'created_at' : created_at,
        'value': value
      }
    )

    # copy file to done bucket
    copy_source = {
      'Bucket': BUCKET_NAME,
      'Key': key
    }
    s3.meta.client.copy(copy_source, BUCKET_NAME_DONE, key)

    # delete file
    obj.delete()

    # upload image
    yolo_key = shared_space_name + '/' + created_at + '_yolo.png'
    client.upload_file('darknet/predictions.png', BUCKET_NAME_DONE, yolo_key)

3단계


DynamoDB의 데이터를 시각화하기 위해re:dash를 사용합니다.
이번 타임 스탬프는 스트링형 YYYYMMDDhmmss 형식입니다.
만약 직접 얻게 된다면 정상적인 시간은 아닐 것이다
TIMESTAMP 함수를 시간 문자열에 덮어쓰여 정상 시간을 표시합니다.
다음은 취득 시 사용되는 DQL입니다.
SCAN shared_space_name,TIMESTAMP(created_at),value FROM tbl_name
결과는 다음과 같습니다.

또한re:dash와 해석용 스크립트는 EC2 1대에 docker를 넣고 각자의 용기로 작동합니다.

과제.


임계값


분석 과정에서 한 사람만 찍힌 이미지를 두 사람으로 판단하는 사람은 드물다.
darknet은thresh 옵션으로 한도값을 지정할 수 있기 때문이다
개인의 확률이 낮은 상황에서 계수를 세지 않는 등의 설정이 가능하다.
이번에는 기본 25% 로 이동했지만, 이 값의 조정 정밀도는 높아지지 않을 것이다.

사용되지 않는 사람의 이미지


우연히 공유공간 근처를 걸어가는 사람이 찍히면 실제보다 인원수가 많아진다.
그렇게 높은 정밀도를 추구하지 않는다면 무시할 수도 있다
한 번에 몇 십 초마다 몇 장씩 찍어서 찍은 사람의 최소치를 측정한다
들어오는 인원을 배제할 수 있을까 해서요.(우리도 아직 시도하지 않았다.)

최후


주식회사가 엔지니어를 모집하고 있다.
이번 시스템에 관심 있는 사람, 새 사무실에 놀러 오고 싶은 사람
마음대로 가세요여기..

좋은 웹페이지 즐겨찾기