Курсовая работа по дисциплине «Разработка информационно-управляющих систем» на тему: «Разработка программы для анализа датасета FLIC и получения информации о расположении и размерностях изображенных людей»

У нас на сайте представлено огромное количество информации, которая сможет помочь Вам в написании необходимой учебной работы. 

Но если вдруг:

Вам нужна качественная учебная работа (контрольная, реферат, курсовая, дипломная, отчет по практике, перевод, эссе, РГР, ВКР, диссертация, шпоры...) с проверкой на плагиат (с высоким % оригинальности) выполненная в самые короткие сроки, с гарантией и бесплатными доработками до самой сдачи/защиты - ОБРАЩАЙТЕСЬ!

Курсовая работа по дисциплине «Разработка информационно-управляющих систем» на тему: «Разработка программы для анализа датасета FLIC и получения информации о расположении и размерностях изображенных людей»

Содержание

 

 

1      Постановка задачи

2      Датасет

3      Анализ данных

5      Заключение

Приложения

Приложение А – Пример программного кода. Класс Pose.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1      Постановка задачи

 

Существует большое количество датасетов предоставляющих информацию о позе людей на изображениях. Обычно они представляют собой набор точек, соответствующий ключевым местам на теле человека (обычно это точки перегиба – суставы и глаза). Такие датасеты используются для обучения нейронных сетей, с задачей распознавания позы.

Однако, подобные датасеты могут нести в себе больше информации. Так по ним можно определить расположение тела в пространстве, и найти примерные его размеры.

Таким образом, задача формулируется как, получение данных о положении и размерностях человеческого тела по информации из датасета для задачи определения позы.

 

 

2    Датасет

 

 

Для задачи pose estimation существуют несколько известных открытых датасета, которые исследователи часто используют в своих научных работах. Например, Leeds Sports Pose Dataset (LSP). Этот датасет состоит из фотографий людей, занимающихся спортом.

 

Рисунок 1. Датасет LSP

 

Но в качестве источника данных для этой работы был выбран датасет Frames Labeled In Cinema (FLIC). Он представляет собой 50000 аннотированных кадров из различных фильмов. Для каждой картинки указаны координаты 11 суставов (ключевых точек).

 

Рисунок 2. Датасет FLIC

 

Данные в этом датасете хранятся в виде MAT файла, отдельно от самих изображений. В MAT файле записаны координаты 11 точек, в одинаковом порядке и имя файла изображения, соответствующего точкам.

 

 

3    Анализ данных

 

На первом этапе были выделены 4 компонента тела человека, для получения по каждому из них базовой информации. А именно

·        Лицо – определяется тремя точками. Два глаза и нос.

·        Тело – определяется четырьмя точками. Две точки плечи и две точки таз.

·        Левая/правая рука – определяются тремя точками. Плечевая, локтевая и кистевая (соответственно для правой и левой.)

Далее вычисляются основные параметры: длина рук, длина плеч, длина таза, площадь проекции тела, площадь проекции лица, угол наклона глаз, плеч, таза, рук, угол сгиба в локте, отношение длины плеч к длине таза, отношение длин боков, Угол между носом и глазами и т.д.

Затем по первоначальным измерениям рассчитываются измерения более высоко уровня. Например, точка проекции центра лица на линию плеч, сонаправленость рук и их направление, поворот лицом или спиной и т.д.

После этого, выполняется нормирование размерностей по принципу minMax. Для вычисления минимума и максимума нормализации использовались статистические данные датасета, с условием отсечения 10% крайних и выбивающихся наборов.

Зная коэффициент для каждой отдельной части тела, можно оценить их удалённость от камеры и использовать длины разных частей для совместных вычислений.

Таким образом вычисляется: общая близость фигуры, наклон тела, наклон головы, поворот тела, поворот головы, наклон головы вверх/вниз, положение рук (на поясе, соединены) и т.д.

Финальным шагом является представление полученных вычислений в понятной человеку форме текста.

 

Например, для Рисунка 3 выводом будет является:

·        Близость: Общий план

·        Тело: Прямо. Повёрнуто вправо

·        Руки: Направленны вниз. Сильно разведены 

·        Голова: Повёрнута вправо. Смотрит вперёд. Наклон влево

 

Рисунок 3. Пример изображения.

 

 

 

 

4      

 

 

5    Заключение

 

В ходе выполнения курсовой работы был получен опыт работы с датасетами, получением и анализом данных.

В результате был реализована программа позволяющая вычислить расположение основных частей тела человека на изображении и приблизительно найти их размерности. Однако, точность вычислений сильно зависит от сложности ракурса, и в некоторых случаях результат получается некорректным.

 Можно сделать вывод, что часть изображений из датасета FLIC с простыми ракурсоми могут быть проанализированы и полученная информация будет достоверна.

 

Рисунок 4. Пример сложного ракурса.

Приложения

Приложение А – Пример программного кода. Класс Pose.

 

import Arm

import Body

import Face

import Calc as calc

import numpy as np

class Pose:

    def __init__(self, dots, index):

        self.bodyIndex = 0

        self.faceIndex = 0

        self.lArmIndex = 0

        self.rArmIndex = 0

        self.shoulderIndex = 0

        self.pelvisIndex = 0

        self.index = index

        self.headRotateFlag = 0

        self.leftArm = Arm.Arm(dots[0], dots[1], dots[2])

        self.rightArm = Arm.Arm(dots[3], dots[4], dots[5])

        self.body = Body.Body(dots[0], dots[6], dots[7], dots[3])

        self.face = Face.Face(dots[8], dots[9], dots[10])

        self.forward = self.forwardCheck()

        self.faceToShoulderNormalPoint = self.calcFaceToShoulderNormal()

        self.headRotation = self.calcHeadRotation()

        self.correctness = None

        self.bodyTilt = None

        self.headTilt = self.calcEyesToShoulderAngle()

        self.upDownFace = self.calcFaceUpDown()

        self.calcMainSize()

        self.handsState = self.calcHandState()

        self.proximity = self.calcProx()

        self.bodyRotation = self.calcBodyPos()

        self.headPos = self.calcHeadPos()

    def __str__(self):

        return "\n N \t{} \n" \

               " Левая рука: \t {} \n Правая рука: \t{} \n Тело: \t{} \n Лицо: \t{} \n Поза: \t{}" \

            .format(self.index,

                    self.leftArm, self.rightArm, self.body, self.face, self.printPose())

    def printPose(self):

        return '\n' \

               ' Лицом вперёд: {} \n' \

               ' Наклон верх/вниз (значение от 0 до 1, где 0 ВНИЗ, 1 ВВЕРХ) : {} \n' \

               ' Поворот головы ( - , если ВЛЕВО, + если ВПРАВО, от 1 до 0, 1 ПРЯМО): {} \n' \

               ' Наклон головы право/лево: {} \n' \

               ' Близость: {} \n' \

               ' Тело: {} \n' \

               ' Руки: {} \n' \

               ' Голова: {} \n' \

               ' Вероятность повёрнутой головы: {} \n' \

               ' body index: {} \n' \

               ' face Index: {} \n' \

               ' L Arm Index: {} \n' \

               ' R Arm Index: {} \n' \

            .format(self.forward, self.upDownFace, self.headRotation, self.headTilt, self.proximity,

                    self.bodyRotation, self.handsState, self.headPos, self.headRotateFlag, self.bodyIndex,

                    self.faceIndex, self.lArmIndex, self.rArmIndex)

    def forwardCheck(self):

        if self.body.leftShoulderPoint[0] < self.body.rightShoulderPoint[0]:

            return False

        else:

            return True

    def calcFaceUpDown(self):

        """

        Расчёт наклона головы сверху вниз, сырой

        :return: значение от 0 до 1, где 0 ВНИЗ, 1 ВВЕРХ

        Также в случае критически острого угла УВЕЛИЧ вероятность ПОВОРОТА головы

        """

        res = calc.minMaxNormalize(30, 120, self.face.noseToEyesAngle)

        # print("UpDown : ", res)

        if res < 0:

            self.headRotateFlag += 1

            res = 0.01

            # TODO если угол оч большой

        if res > 1:

            pass

        return res

    def calcFaceToShoulderNormal(self):

        x1 = self.body.leftShoulderPoint[0]

        y1 = self.body.leftShoulderPoint[1]

        x2 = self.body.rightShoulderPoint[0]

        y2 = self.body.rightShoulderPoint[1]

        x3 = self.face.faceCenterPoint[0]

        y3 = self.face.faceCenterPoint[1]

        k = ((y2 - y1) * (x3 - x1) - (x2 - x1) * (y3 - y1)) / ((y2 - y1) ** 2 + (x2 - x1) ** 2)

        x4 = x3 - k * (y2 - y1)

        y4 = y3 + k * (x2 - x1)

        dot = [x4, y4]

        return dot

    def calcHeadRotation(self):

        """

        Выч. поворот головы без учёта остальных факторов

        :return: отрицательное, если ВЛЕВО, положительное если ВПРАВО, модуль от 1 до 0, чем меньше, тем сильнее поворот

        """

        fromLeftShoulderToNormal = calc.vectorLength(self.faceToShoulderNormalPoint, self.body.leftShoulderPoint)

        fromRightShoulderToNormal = calc.vectorLength(self.faceToShoulderNormalPoint, self.body.rightShoulderPoint)

        # если точка внутри плеч

        if (fromLeftShoulderToNormal + fromRightShoulderToNormal) <= self.body.fullShoulderLength + 0.00001:

            if fromLeftShoulderToNormal < fromRightShoulderToNormal:

                return (fromLeftShoulderToNormal / fromRightShoulderToNormal) * -1

            else:

                return fromRightShoulderToNormal / fromLeftShoulderToNormal

        # если вне TODO нужно это учитывать для других измерений

        else:

            if fromLeftShoulderToNormal < fromRightShoulderToNormal:

                return ((fromLeftShoulderToNormal / fromRightShoulderToNormal) * -1) / 10

            else:

                return (fromRightShoulderToNormal / fromLeftShoulderToNormal) / 10

    def calcMainSize(self):

        bodyArea = self.body.bodyArea

        faceArea = self.face.faceArea

        lArmLength = self.leftArm.fullLength

        rArmLength = self.rightArm.fullLength

        pelvisLength = self.body.fullPelvisLength

        shoulderLength = self.body.fullShoulderLength

        # print(bodyArea)

        # print(faceArea)

        # print(lArmLength)

        # print(rArmLength)

        # print(pelvisLength)

        # print(shoulderLength)

        self.bodyIndex = calc.minMaxNormalize(150, 13000, bodyArea)

        self.faceIndex = calc.minMaxNormalize(4, 350, faceArea)

        self.lArmIndex = calc.minMaxNormalize(40, 260, lArmLength)

        self.rArmIndex = calc.minMaxNormalize(40, 260, rArmLength)

        self.shoulderIndex = calc.minMaxNormalize(30, 210, shoulderLength)

        self.pelvisIndex = calc.minMaxNormalize(25, 200, pelvisLength)

        # print("body ", bodyIndex)

        # print("face ", faceIndex)

        # print("l_arm ", lArmIndex)

        # print("r_arm ", rArmIndex)

        # print("shoulder ", shoulderIndex)

        # print("pelvis ", pelvisIndex)

    def calcEyesToShoulderAngle(self):

        # TODO учитывать направление

        shoulderAngle = self.body.shoulderAngle

        eyesAngle = self.face.eyeAngleToX

        return calc.angleDif(shoulderAngle, eyesAngle)

    def calcHandState(self):

        res = ""

        handsUnderPelvis = False

        if self.leftArm.wristPoint[1] > self.body.leftPelvisPoint[1] and self.rightArm.wristPoint[1] > \

                self.body.rightPelvisPoint[1]:

            handsUnderPelvis = True

        LLenhgthNorm = self.leftArm.fullLength / self.lArmIndex

        RLenhgthNorm = self.rightArm.fullLength / self.rArmIndex

        wristDistNorm = calc.vectorLength(self.leftArm.wristPoint, self.rightArm.wristPoint) / np.mean(

            [self.lArmIndex, self.rArmIndex])

        lelbAngNorm = self.leftArm.elbowAngle

        relbAngNorm = self.rightArm.elbowAngle

        lDirection = self.leftArm.direction

        rDirection = self.rightArm.direction

        pelvisNorm = self.body.fullPelvisLength / np.mean([self.lArmIndex, self.rArmIndex])

        pelvisAngNorm = self.body.pelvisAngle

        wristLineAngNorm = calc.angleToX(self.leftArm.wristPoint, self.rightArm.wristPoint)

        wristSide = np.mean([calc.vectorLength(self.leftArm.wristPoint, self.body.leftPelvisPoint), \

                             calc.vectorLength(self.rightArm.wristPoint, self.body.rightPelvisPoint)]) / np.mean(

            [self.lArmIndex, self.rArmIndex])

        wristSideAng = calc.angleDif(wristLineAngNorm, pelvisAngNorm)

        if not self.forward:

            lelbAngNorm *= -1

            relbAngNorm *= -1

        if lDirection == rDirection:

            res += "Руки направленны "

            if lDirection == "up":

                res += "вверх, "

            else:

                res += "вниз, "

            if wristDistNorm < 160:

                if wristDistNorm < 125:

                    res += "очень "

                res += "близко, "

            if wristDistNorm > 350:

                if wristDistNorm > 500:

                    res += "сильно "

                res += "разведены, "

            if lelbAngNorm > 0 and relbAngNorm > 0:

                res += ""

            if wristSideAng < 7 and wristSide < 40 and abs(pelvisNorm - wristDistNorm) < 80:

                if not handsUnderPelvis:

                    res += "(вбоки) "

                else:

                    res += "(в карманах) "

            else:

                if wristDistNorm < 140 and (abs(lelbAngNorm - relbAngNorm) < 40):

                    res += "(соеденены) "

            if lelbAngNorm < 0 and relbAngNorm < 0:

                res += "и направлены в разные стороны "

        return res

    def calcProx(self):

        if np.mean([self.bodyIndex, self.lArmIndex, self.rArmIndex]) > 0.9:

            return "Крупный план"

        if np.mean([self.bodyIndex, self.lArmIndex, self.rArmIndex]) > 0.5:

            return "Общий план близко"

        if np.mean([self.bodyIndex, self.lArmIndex, self.rArmIndex]) > 0.2:

            return "Общий план"

        if np.mean([self.bodyIndex, self.lArmIndex, self.rArmIndex]) < 0.2:

            return "Далеко"

    def calcBodyPos(self):

        res = ""

        if abs(self.body.pelvisAngle) < 4 and abs(self.body.shoulderPelvisAngel) < 3:

            res += "Прямо"

        if abs(self.body.pelvisAngle) < 50 and abs(self.body.shoulderPelvisAngel) < 9:

            if self.headRotation < 0 and abs(self.headRotation) < 0.6:

                res += "ПОВОРОТ ЛЕВО "

            if self.headRotation > 0 and abs(self.headRotation) < 0.6:

                res += "ПОВОРОТ ПРАВО "

        if abs(self.body.pelvisAngle) > 3 and abs(self.body.pelvisAngle) < 50 and abs(

                self.body.shoulderPelvisAngel) < 3:

            res += "Поворот в "

            if self.body.leftSideToRightSideRatio <= 1:

                res += "лево "

            else:

                res += "право "

        if abs(self.body.shoulderPelvisAngel) > 5:

            res += "Наклон "

            if self.body.leftSideToRightSideRatio <= 1:

                res += "влево "

            else:

                res += "вправо "

        return res

    def calcHeadPos(self):

        res = ""

        if abs(self.headRotation) > 0.85:

            res += "Прямо. "

        else:

            if self.headRotation < 0:

                res += "Повёрнута влево. "

            else:

                res += "Повёрнута вправо. "

        if self.upDownFace > 0.75:

            res += "Поднята вверх. "

        else:

            if self.upDownFace < 0.35:

                res += "Опущена вниз. "

            else:

                res += "Смотрит вперёд. "

        if self.headTilt > 5 and self.forward:

            if self.face.eyeAngleToX > 0:

                res += "Наклон влево "

            else:

                res += "Наклон вправо "

        else:

            if self.face.eyeAngleToX < 0:

                res += "Наклон вправо "

            else:

                res += "Наклон влево "

        return res