Project/Proj-Nova Vision

Nova-Vision은 어떻게 개발했을까?: AI 가축 체중측정 알고리즘 개발

dohyeon2 2024. 7. 30. 21:54

목차

    이번 글에서는 "영상데이터(RGB,3D 깊이)만으로 닭의 체중을 예측하는 알고리즘"의 개발과정과 마주했던 문제 해결방법들에 대해 정리하였습니다.

    (농진청 스마트팜다부처패키지 기술개발사업 과제, 2022.04~2023.05)

     

    이전글: Nova-Vision은 어떻게 개발했을까?: 3D Depth camera 개발

    Github: https://github.com/dohyeonYoon/BRODY

     

    연구 개요


    • 2020년 축산업의 총 생산액은 20조 7,000억 원으로 2008년에 비해 약 2배 증가하였고, 농업 생산액에서 차지하는 비중도 39.6%로 매우 빠르게 증가하고 있음(그림 1)
    • 2021년 12월 기준, 전국 육계 사육수수는 7,190만 수이며, 이는 전년 대비 2.0%, 평년 대비 1.8% 증가한 수치임
    • 최근 농가의 규모화로 인해 농가 가구당 평균 사육수수도 크게 증가하여, 육계는 평균 5.6만 수에 달함(통계청, 21)
    • 2020년 12월 기준, 우리나라 농업 인구수는 231만 7,000명으로 지난 2000년 대비 42.5% 감소하였음. 또한 이들의 평균 연령은 49.9세에서 65.6세로 증가하였음(통계청, 21)(그림 1)
    • 사육농가 가구당 사육 수수는 증가하였으나 관련 기술이나 농가 인력은 증가하지 않고 농업 종사자의 고령화가 진행됨에 따라 농가의 인력난이 점차 심각한 문제로 대두됨

    그림 1. 축산물 소비추세 변화 및 연도별 농업 종사자 연령비율 변화(통계청, 2021)

     

    연구 필요성


    그림 2. 체중예측 시스템 개발의 필요성

     

    • 우리나라 육계의 94%는 가공업체로부터 위탁받아 농가에서 사육되기 때문에 출하체중 오차(±50g) 발생 시, 오차에 따른 패널티를 농가에서 부담하고 있음
    • 따라서, 잘못된 체중 측정은 패널티 부과, 추가 사료비 등 농가에게 경제적 손실을 발생시킬 수 있어 출하시기에 앞서 육계의 평균 체중을 정확히 측정하는 것은 매우 중요함
    • 기존 농가에서 이용하는 체중 측정 방법(그림 3)은 매우 많은 시간과 노동력을 요구하며, 사람의 개입으로 인해 전염병 및 스트레스로 인한 폐사의 위험이 높음
    • 따라서 닭에게 전염병 및 스트레스를 최소화할 수 있도록 하는 비접촉방식, 적은 노동력과 많은 표본으로 평균 체중을 정확하게 측정할 수 있는 예측 시스템이 필요함

    프로젝트 기획 및 필요 데이터 정의


    [국내외 관련 논문 survey]

    1. Anders Krogh Mortensen et al., "weight prediction of broiler chickens using 3D computer vision", Computers and Electronics in Agriculture, 2016, Pages 319-326
    2. Somaye Amraei et al., "Application of computer vision and support vector regression for weight vector regression for weight prediction of live broiler chicken", Engineering in Agriculture Environment and Food, 2017, Pages 266-271 
    3. Innocent Nyalala et al., "On-line weight estimation of broiler carcass and cuts by a computer vision system", Poultry Science, 2021, Vol 100
    4. Innocent Nyalala et al., "Weight and volume estimation of poultry and products based on computer vision systems: a review", Poultry Science, 2021, Vol 100
    5. Kaiming He et al., "Mask R-CNN", IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 2017, arXiv:1703.06870
    6. Kai Chen et al., "MMDetection: Open MMLab Detection Toolvox and Benchmark", IEEE Conference on Computer Vision and Pattern Recognition (CVPR), 2019, arXiv:1906.07155

     

    [Overview]

    그림 3. 가축 체중측정 시스템 Overview

     

    개발된 시스템의 workflow를 간단하게 설명하면 다음과 같습니다.

    1. 육계사 천장에 설치된 3D 깊이 카메라로 육계 군집의 사진을 촬영하고 데이터(RGB, 3D 깊이) 획득
    2. Instance Segmentation Network를 이용하여 입력 이미지(RGB)에서 육계영역을 분할하고 mask 정보 획득 
    3. 육계의 mask 정보와 매칭되는 3D 깊이 데이터를 활용하여 육계의 1D, 2D, 3D feature 추출
    4. 추출된 feature를 선형회귀 네트워크의 입력으로 활용하여 체중예측

     

    [필요 데이터 정의]

    딥러닝 관련 문제들을 풀다 보면, 중요한 것은 "얼마나 좋은 모델이나 프레임워크를 사용하느냐"가 아니라 "얼마나 적절한 데이터를 사용하느냐" 임을 알 수 있습니다. 문제를 해결하기 위해 사용하고자 하는 전체적인 방법론(시스템의 overview)이 정해지면 우리에게 필요한 적절한 데이터를 정의할 수 있습니다.

    • [overview] 2단계의 Instance Segmentation Network를 학습시키기 위해서 육계 군집 RGB 데이터와 라벨링 데이터가 필요합니다.
    • [overview] 3단계의 1D, 2D, 3D feature를 추출하기 위해서는 육계 군집 RGB 데이터에 1:1로 매칭되는 3D 깊이 데이터가 필요합니다.
    • [overview] 4단계의 선형회귀 네트워크를 학습하기 위해서는 육계 군집이 아니라 개별 육계의 RGB 데이터, 3D 깊이 데이터, 체중 데이터가 필요합니다. 왜냐하면 수백마리의 육계 각각을 촬영하고 RGB, 3D 깊이, 체중 데이터를 획득한 뒤, 해당 육계의 1D, 2D, 3D feature를 추출하고 실제 체중을 측정한 다음 선형회귀 네트워크의 학습 데이터로 사용해야 육계 군집 이미지에서 추출된 육계 각각의 feature들을 미리 학습된 개별 육계의 feature들과 실제체중을 토대로 체중을 예측할 수 있기 때문입니다.
    1. 군집 육계 RGB 데이터, 라벨링 데이터 → Segmentation 네트워크 학습용 
    2. 군집 육계 3D 깊이 데이터 → 1D, 2D, 3D feature 추출용
    3. 군집 육계 평균체중 데이터(개별 육계 체중데이터의 평균값) → 체중측정 정확도 검증용
    4. 개별 육계 RGB 데이터 → 선형회귀 네트워크 학습용
    5. 개별 육계 3D 깊이 데이터 → 선형회귀 네트워크 학습용
    6. 개별 육계 체중 데이터(실제 측정값) → 선형회귀 네트워크 학습용

     

    데이터 수집


    [군집 육계 데이터 수집 - RGB, 3D 깊이, 평균체중]

    군집 육계 데이터(RGB, 3D 깊이, 체중)를 수집하기 위해 국립축산과학원 가금연구소에 실험 테스트베드(그림 4, 왼쪽)를 구축하였습니다.

    그림 4. 육계 군집 촬영 테스트베드 구축 및 학습데이터 수집

     

    실험은 가금연구소 측의 사육 스케줄에 따라 총 3번(1차년도 1번, 2차년도 2번) 진행되었습니다. 가금연구소 내 육계사 천장에 3D 깊이 카메라(stereolabs ZED2i)를 설치하고 1시간 간격으로 총 35일간 군집 육계 데이터(RGB, 3D 깊이)를 획득하였습니다. 이후 데이터는 연구실 내 Synology NAS 서버에 실시간으로 연동되어 백업됩니다. 육계 군집의 평균체중은 동일한 날짜의 개별육계 실제 체중값의 평균입니다.

     

    [개별 육계 데이터 수집 - RGB, 3D 깊이, 체중]

    그림 5. 개별 육계 촬영 테스트베드 구축 및 학습데이터 수집

     

    개별 육계 실험 역시 총 3번(1차년도 1번, 2차년도 2번) 진행되었습니다. 개별 육계 촬영 테스트베드는 CATIA로 설계하여 제작하였습니다. 35일간 이틀 간격으로 하루 60마리씩 개별 육계를 촬영하고 체중을 측정하여 데이터(RGB, 3D 깊이, 체중)를 수집하였습니다.

    그러나, 첫째날 수집된 데이터를 확인하였을 때 터무니없는 3D 깊이정보가 저장되는 문제가 발생하였습니다. 문제 해결을 위해 카메라 parameter와 조명조건을 바꿔가면서 다시 실험해봐도 여전히 동일한 문제가 발생하였습니다. 결론적으로 원인은 제작한 테스트베드의 바닥 및 벽면이 거울처럼 매끄러운 아크릴 재질이었는데 아크릴과 같이 textureless한 환경에서 깊이 측정 정확도가 떨어지는 stereo camera의 특징 때문이었습니다. 그래서 전기테이프로 바닥 및 벽면을 한번 더 마감하여 texture줌으로서 측정 정확도 문제를 해결하였습니다.

     

    [데이터 라벨링 서버구축 및 라벨링]

    데이터 라벨링 서버를 구축할 당시, 저희 연구실 상황은 Roboflow, Labelbox등 유료 툴에 지출할 수 있는 금액이 부족하였고, 교수님께서 촬영 데이터를 타사 클라우드 서버에 업로드하는 것을 원치 않으셨습니다. 따라서 저는 다음과 같은 기준으로 라벨링 툴을 결정하였습니다.

    • 첫째, 오픈소스로 제공되는 무료 라벨링 툴일 것. 
    • 둘째, 웹에서 진행되지 않고 로컬 서버에 데이터가 저장될 것(데이터 유출 방지).

    결론적으로 저는 로컬 서버에 Docker로 빌드하여 데이터 유출 우려없이 작업가능하고, Task와 작업자를 할당하여 여러명이 동시에 작업 가능하며, 향후 데이터 라벨링 작업이 진행됨에 따라 auto labeling 기능 지원하는 CVAT를 선택하였습니다.

    더보기

    Docker를 이용한 CVAT server 구축 및 외부접속 허용방법(ubuntu 18.04)

     

    1. 필요 라이브러리 설치

    $ sudo apt-get update
    
    $ sudo apt-get --no-install-recommends install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
    
    $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
    
    $ sudo apt-get update
    
    $ sudo apt-get --no-install-recommends install -y docker-ce docker-ce-cli containerd.io

     

    2. Docker Compose 설치(다중 컨테이너 실행을 위한 tool)

    $ sudo apt-get --no-install-recommends install -y python3-pip python3-setuptools
    
    $ sudo python3 -m pip install setuptools docker-compose

     

    3. Clone CVAT source code

    $ sudo apt-get --no-install-recommends install -y git
    
    $ git clone https://github.com/opencv/cvat #원하는 위치에 clone
    
    $ cd cvat

     

    3. 외부접속 허용을 위한 환경변수 설정 및 docker-compose.yml file 수정

    $ export CVAT_HOST= 본인 서버 ip주소
    
    $ sudo vim docker-compose.yml # 아래 사진에서 밑줄친 부분 기존 -localhost에서 -본인서버ip주소로 변경

     

    4. 도커 Root Dir 수정

    도커는 처음 설치하면 기본적으로 부팅 디스크(우분투 기준 /var/lib/docker)에 Root directory가 설정됩니다. Docker로 간단한 작업만 실행한다면 문제되지 않겠지만, 도커로 DB를 올리거나 컨테이너의 용량이 지속적으로 커지는 작업등을 한다면 저장공간이 부족해지는 이슈가 발생할 수 있습니다. 우리가 설치하려는 데이터 라벨링 서버(CVAT)는 DB와 웹서버 2개의 컨테이너를 올리는 작업이기 때문에 데이터가 저장되는 위치를 변경해주는 것이 꼭 필요합니다.

     

    4-1 기본 저장소 위치 확인

    $ docker info | grep “Docker Root Dir”

     

    기본적으로  /var/lib/docker 에 저장되는 것을 확인할 수 있습니다.

     

    4-2 새로운 도커 저장소 디렉토리 생성

    $ mkdir /scratch/data/docker

     

    저는 HDD를 마운트한 /scratch 디렉토리 내의 data/docker 디렉토리를 생성하였고, 이를 새로운 도커 저장소로 지정할 예정입니다.

     

    4-3 도커 저장소 위치 변경

    $ cd /etc/docker
    
    위 경로에 daemon.json 파일이 없다면 파일을 하나 생성하고 아래 내용을 추가
    
    {
    
    “graph”: “/scratch/data/docker”
    
    }

     

    4-4 도커 재시작(선택  이미 docker build되 있을 때만 실행)

    $ sudo service docker stop
    
    $ sudo systemctl daemon-reload
    
    $ sudo service docker start

     

    5. 도커 컨테이너 실행 (cvat, postgres, redis 등 기타 필수 컨태이너 생성)

    $ docker-compose up -d

     

    6. 슈퍼유저 생성(관리자 패널을 이용해 사용자에게 그룹할당 가능한 유저)

    $ docker exec -it cvat bash -ic 'python3 ~/manage.py createsuperuser'

     

    7. 서버 실행

    주소창에 본인서버ip주소:8080

     

    8. 슈퍼유저로 로그인

     

    9. 관리자 패널에서 유저 추가 및 organization 할당

     

    10. user마다 task 할당

     

    참조

    여러명의 작업자가 동일한 데이터를 라벨링하더라도, 작업자의 주관에 따라 조금씩 다르게 라벨링이 진행됩니다. 이렇게 발생된 애매한 데이터들은 결과적으로 모델의 성능을 떨어뜨리게 되는데요. 이러한 애매한 데이터가 발생되지 않도록 명확한 기준을 세워서 통일성 있게 라벨링을 진행하는 것이 매우 중요합니다. 따라서 저는 다음과 같은 기준으로 데이터를 라벨링하였습니다.

    그림 6. 데이터 라벨링 가이드라인

    • 일반적인 경우에는 닭발 등 다른곳은 제외하고 닭의 윗면만 가능한 object에 fit하게 라벨링한다.
    • 기둥에 끝부분이 가려진 경우는 가려진 형상을 예측할 수 없으므로 가려지지 않은 부분만 라벨링한다.
    • 기둥에 일부분이 가려졌지만 예측 가능한 경우는 몸의 일부분이 가려졌지만 형상을 충분히 예측할 수 있으므로 예측되는 형상을 모두 라벨링한다.
    • 모이통에 끝부분이 가려진 경우는 가려진 형상을 예측할 수 없으므로 가려지지 않은 부분만 라벨링한다.
    • 날개짓하는 경우는 일반적이지 않고 형상이 일정하지 않으므로 라벨링하지 않는다.
    • 다른 닭에 의해 일부분이 가려진 경우는 가려진 닭의 형상을 예측할 수 없으므로 가려지지 않은 부분만 라벨링한다.
    • 이미지 경계에 걸려 잘린 경우 segmentation 모델에 의해 검출된 뒤, 추후 알고리즘을 통해 해당 개체를 배제할 수 있도록 가려지지 않은 부분만 라벨링한다.
    • 구조물에 가려 닭끼리 경계가 모호한 경우 segmentation 모델에 의해 검출되지 않도록 라벨링하지 않는다.  

    Instance Segmentation Model 개발


    [Instance Segmentation Model 학습]

    여러 model을 학습하고 성능을 비교하려면 동일한 실험조건(backbone, learning rate, batch size 등)에서 학습 및 성능평가가 이뤄져야 합니다. 그러나 오픈소스로 공개된 공식 repository들의 코드를 직접 수정하여 실험조건을 맞추는 것은 많은 시간과 노력이 필요한 작업이였습니다. 따라서 저는 config 설정만으로 네트워크의 backbone, mask_head 등을 손쉽게 변경하고 학습할 수 있는 mmdetection이라는 Toolbox를 도입하였고, 결과적으로 총 21개 model의 학습 및 성능평가를 진행하였습니다.

     

    [모델 성능평가]

    저는 Instance Segmentation 모델 성능평가를 위한 지표로 Pixel Accuract, MIoU 두 가지를 사용하였습니다. 평가지표로 이 두가지를 선택한 근거는 다음과 같습니다.

    평가지표 1. Pixel Accuracy

    Deep learning에서 Instance Segmentation task는 이미지의 픽셀 수준에서 각 픽셀이 어떤 의미를 갖는지 구분하는 작업입니다.

    따라서 Segmentation 문제를 픽셀에 따른 image classification 문제로 생각했을 때, 픽셀별 분류 정확도를 Segmentation model의 성능을 평가하는 하나의 지표로 사용할 수 있습니다.

     

    평가지표 2. Mean Intersection-over-Union

    우리는 object detection 모델을 평가할 때 ground truth bbox와 predicted bbox가 겹치는 비율을 뜻하는 IoU(Intersection over Union)를 평가지표로 사용합니다. Mask도 일종의 region으로 생각할 수 있기 때문에, Segmentation 모델을 평가할 때 ground truth region과 predicted region 사이의 IoU를 계산할 수 있습니다. 아래의 코드를 통해 Segmentation의 IoU는 손쉽게 게산할 수 있습니다.

    Intersection = np.logical_and(target, prediction)
    union = np.logical_or(target, prediction)
    Iou_score = np.sum(intersection) / np.sum(union)

     IoU를 class 별로 계산하면 하나의 이미지에서 multi class에 대한 평균 IoU도 계산할 수 있지만 저의 경우 탐지하고자 하는 class는 "chicken" 단 하나이므로 IoU == mIoU입니다.

     

    실험결과는 다음과 같았습니다. (backbone은 resnet50으로 통일)

    model test set
    Pixel Accuracy
    test set
    mIoU
    mask-rcnn + resnet50 91.094 0.449
    point-rend + resnet50 92.305 0.456
    queryinst + resnet50 90.998 0.412
    scnet + resnet50 91.392 0.393

     

    실험결과 픽셀별 분류 정확도를 뜻하는 Pixel Accuracy와 예측픽셀이 ground truth 픽셀과 겹치는 정도를 뜻하는 mIoU 모두 point-rend + resnet50 모델이 가장 우수하였습니다. 따라서 point-rend + resnet50 조합을 Baseline으로 선택하였습니다.

     

    2D(투영 면적, 둘레, 장축,단축), 3D(표면적) feature 추출 알고리즘 개발


    육계의 다양한 생체지표(표면적, 부피, 머리 길이, 부리 길이, 몸통 길이, 키 등)와 무게 사이의 상관관계를 분석하여 3D 깊이 카메라로 측정할 수 있고, 체중과 유의미한 상관관계를 갖는 4가지 feature를 결정하였습니다.

     

    [2D feature- 투영면적]

    그림 7. 2D 투영면적 계산 알고리즘

    앞서 Instance Segmentation model을 이용하여 육계 군집 이미지 내에 위치한 각 육계의 영역을 masking 할 수 있었습니다. 이렇게 얻어진 masking 영역을 이진화 한 뒤 openCV의 findContours() 함수를 활용하여 외곽선을 찾습니다. 이후 외곽선에 대응되는 2D 픽셀 좌표를 depth map에서 찾아서 3D 월드좌표로 변환합니다. 2D 픽셀좌표(u,v)를 3D 월드 좌표(X,Y,Z)로 변환하는 공식은 다음과 같습니다. 

    Z = 깊이 맵의 픽셀 (u,v)의 깊이 값 
    X = (( u - c_x) * Z) / (f_x) 
    Y = (( v - c_y) * Z) / (f_y)
    
    이때, f_x, f_y는 픽셀단위 초점 거리를 뜻하며, c_x, c_y는 주점의 좌표를 뜻합니다.

     

    변환된 contour points의 Z좌표를 무게중심점의 z 좌표로 대체하고 좌표평면 상에서 꼭짓점의 좌표를 알 때 다각형의 면적을 계산할 수 있는 shoelace formula를 적용하여 다각형의 면적을 계산합니다.

     

     

    [2D feature - 둘레]

    다각형의 둘레를 구하는 방법은 다각형을 이루는 각 선분의 길이를 합산하면 손쉽게 구할 수 있습니다. 앞서 contour points의 월드좌표(X,Y,Z)를 얻었으므로 각 점사이의 유클리드 거리를 계산하여 다각형의 둘레를 계산합니다.

     

    계산방법 1. 유클리드 거리 공식을 활용한 둘레 계산 방법

    from shapely.geometry import Polygon
    
    # 다각형 예시
    polygon_coords = [(0, 0), (0, 1), (1, 1), (1, 0)]
    polygon = Polygon(polygon_coords)
    
    # 다각형의 각 변의 길이 계산
    perimeter = 0.0
    
    for i in range(len(polygon_coords)):
        x1, y1 = polygon_coords[i]
        x2, y2 = polygon_coords[(i + 1) % len(polygon_coords)]  # 마지막 점과 첫 번째 점을 연결
        
        # 유클리드 거리 계산
        distance = ((x2 - x1)**2 + (y2 - y1)**2)**0.5
        
        # 둘레에 길이 추가
        perimeter += distance
    
    print(f"다각형의 둘레: {perimeter}")

     

    계산방법 2. Shapely 라이브러리를 활용한 둘레 계산 방법

    from shapely.geometry import Polygon
    
    # 다각형 예시
    polygon_coords = [(0, 0), (0, 1), (1, 1), (1, 0)]
    polygon = Polygon(polygon_coords)
    
    # 다각형의 둘레 계산
    perimeter = polygon.length
    
    print(f"다각형의 둘레: {perimeter}")

     

    [2D feature- 장축,단축]

    제가 정의한 장축과 단축이란, 닭의 윗면에서 무게중심을 지나면서 그릴 수 있는 가장 긴/짧은 선분 입니다.

    장축과 단축의 길이는 다음과 같은 방식으로 계산하였습니다.

     

     

    • 2D mask 이미지에 openCV findContours(), moments() 함수를 이용하여 경계선과 무게중심점을 계산하고 draw해줍니다.
    • 무게중심점을 지나는 임의의 선분 l을 그려줍니다.
    • 임의의 선분 l을 1도씩 회전하면서 선분과 경계선이 교차하는 두 점(u1,v1), (u2,v2)을 획득합니다.
      (전체 이미지 array에서 pixel value가 127이면서 255인 곳이 선분과 경계선의 교차점입니다)
    • 픽셀좌표계에서 획득된 360쌍의 교차점 (u1,v1), (u2,v2)를 3D 월드 좌표계로 변환한 뒤, 두 점 사이의 유클리드 거리를 계산하면 거리가 가장 긴 선분이 장축, 가장 짧은 선분이 단축이 됩니다.

     

    [3D feature- 표면적]

    앞서 RGB 이미지에서 육계 영역을 분할하고, 분할된 mask 영역을 depth 정보와 매칭시켜 3D point cloud를 획득하였습니다.

    이렇게 얻어진 3D point cloud로 육계의 표면적을 계산할 수 있는데요. 3D point cloud에서 표면적을 계산하기에 앞서, 각 point가 속한 표면의 방향을 알기위해 point의 법선벡터를 계산하는것이 필수적입니다. 법선벡터를 계산하는 방법은 다음과 같습니다.

    1. 구하고자 하는 점(P1)과 가장 가까운 두 점(P2,P3)을 찾는다.
    2. P1으로부터 나머지 두 점(P2,P3)을 잇는 두 벡터를 구한다.
    3. 두 벡터 간 직교하는 벡터를 구한다.
    4. 직교 벡터를 단위화 한다.

     

    위 공식을 point cloud 내 모든 point에 적용하고 시각화하면 다음과 같습니다.

    3D point cloud로부터 생성된 법선벡터

     

    앞서 언급했듯이 저는 표면의 방향을 알기위해 법선벡터를 계산하였습니다. 하지만 각 점에 생성된 법선벡터의 방향이 일관되지 않게 생성되는 문제가 발생하였습니다. 제가 사용한 데이터는 샘플링 등의 후처리 과정을 거치지 않은 원본 point cloud 데이터이기 때문에 점들의 밀도가 일관되지 않습니다. 이렇게 균일하지 않은 샘플링 밀도를 가진 point들 사이에서는 법선 추정이 일관되게 계산되지 않을 수 있습니다. 저는 이를 해결하고자 최소 스패닝 트리를 사용하여 법선 방향을 전파하는 방법을 사용해보았습니다. 

    결과적으로 방향이 일관되지 않던 법선벡터들이 모두 일관된 방향을 갖게 되었습니다.

    최소 스패닝 트리 방식을 사용한 법선벡터 방향 통일

     

    마지막으로 제가 구하고자 한 육계의 겉표면(등 부분)의 표면을 형성하고자 일관화된 법선벡터의 방향을 reverse하였습니다.

    법선벡터 reverse

     

    마지막으로 point cloud와 각 점의 법선벡터를 이용하여 surface를 형성했습니다. open3d 라이브러리에서 지원하는 surface 형성 알고리즘(ball_pivoting, poisson) 2가지를 이용하여 각각 surface를 형성하고 데이터를 살펴본 결과, ball_pivoting 알고리즘으로 생성된 surface가 데이터의 편차가 상대적으로 적어서 해당 알고리즘을 사용하기로 결정하였습니다.

     

    Linear Regression Network 모델링 및 평가


    [feature별 체중과의 상관관계 분석]

    앞선 과정을 통해 추출된 2D, 3D feature들과 체중 사이의 상관관계를 분석하였습니다.

    feature-weight 데이터 분포(상관관계)

     

    분석결과 2D 면적, 2D 둘레, 2D 장축, 3D 표면적은 체중과 linear한 분포를 따랐지만, 2D 단축은 그렇지 못했습니다.

    각 feature와 체중 사이의 corr_matrix를 그려보면 아래와 같습니다.

    feature-weight corr_matrix

    이를통해 체중과 상관관계가 없다고 판단되는 2D 단축은 회귀 네트워크 학습에 배제하였습니다.

     

    [회귀모형 수식화]

    앞서 feature-체중 데이터 분포를 살펴보던 와중에 2D area는 1차식으로 회귀분석하면 되지만, 2D 둘레, 2D 장축과 같은 분포를 띄는 데이터는 1차식보다 2차식으로 회귀하는게 더 잘 예측할 수 있지 않을까? 라는 생각이 들었습니다.

    따라서 1차식 회귀모형과 2차식 회귀모형을 각각 수식화해보았고, 수식은 다음과 같습니다.

     

     

    위 수식에 따라 만들어진 회귀모형으로 육계의 체중을 예측하고 실제체중과 비교하여 오차를 계산해보면 다음과 같습니다.

    • model 1: 2D(면적)
    • model 2: 2D(면적,둘레)
    • model 3: 2D(면적,둘레,장축)
    • model 4: 2D(면적,둘레,장축), 3D(표면적)

    조건에서 4가지 모델을 비교한 결과

    Multivariate linear best model(일령,면적) error avg  +13.5% 

    Multivariate polynomial best model(면적) error avg  +9.8%

    결과적으로 polynomial regression 모형이 정확도 90.2%로 더 정확한 예측결과를 보였습니다.

     

    여기까지 3D Computer Vision기반 육계 체중측정 자동화 시스템 개발과정이었습니다.