Skip to content

Commit

Permalink
feat: Merge pull request #93 from UniversalDataTool/pose-estimation
Browse files Browse the repository at this point in the history
Pose / Keypoint Annotation Interface
  • Loading branch information
seveibar authored Sep 15, 2020
2 parents d9e5a65 + f230c82 commit 772db6c
Show file tree
Hide file tree
Showing 18 changed files with 435 additions and 18 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
"babel-loader": "^8.0.5",
"babel-preset-react-app": "^7.0.0",
"gh-pages": "^2.0.1",
"prettier": "^2.0.5",
"prettier": "^2.1.1",
"raw.macro": "^0.3.0",
"react-github-btn": "^1.1.1",
"react-scripts": "^3.4.1"
Expand Down
4 changes: 4 additions & 0 deletions src/Annotator/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
MainLayoutState,
Action,
} from "../MainLayout/types"
import type { KeypointsDefinition } from "../ImageCanvas/region-tools"
import SettingsProvider from "../SettingsProvider"

import combineReducers from "./reducers/combine-reducers.js"
Expand Down Expand Up @@ -41,6 +42,7 @@ type Props = {
videoSrc?: string,
keyframes?: Object,
videoName?: string,
keypointDefinitions: KeypointsDefinition,
fullImageSegmentationMode?: boolean,
autoSegmentationOptions?:
| {| type: "simple" |}
Expand Down Expand Up @@ -77,6 +79,7 @@ export const Annotator = ({
onExit,
onNextImage,
onPrevImage,
keypointDefinitions,
autoSegmentationOptions = { type: "autoseg" },
}: Props) => {
if (typeof selectedImage === "string") {
Expand Down Expand Up @@ -112,6 +115,7 @@ export const Annotator = ({
enabledTools,
history: [],
videoName,
keypointDefinitions,
...(annotationType === "image"
? {
selectedImage,
Expand Down
4 changes: 2 additions & 2 deletions src/Annotator/index.story.js
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ storiesOf("Annotator", module)
videoSrc="https://s3.amazonaws.com/asset.workaround.online/SampleVideo_1280x720_1mb.mp4"
videoTime={1000}
keyframes={{
"0": {
0: {
regions: [
{
type: "point",
Expand All @@ -465,7 +465,7 @@ storiesOf("Annotator", module)
},
],
},
"3333": {
3333: {
regions: [
{
type: "point",
Expand Down
76 changes: 76 additions & 0 deletions src/Annotator/poses.story.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// @flow

import React, { useState } from "react"

import { storiesOf } from "@storybook/react"
import { action as actionAddon } from "@storybook/addon-actions"
import dancingManImage from "../ImageCanvas/dancing-man.story.jpg"
import Annotator from "./"

const middlewares = [
(store) => (next) => (action) => {
actionAddon(action.type)(action)
return next(action)
},
]

storiesOf("Annotator (Poses)", module).add("Basic", () => (
<Annotator
onExit={actionAddon("onExit")}
middlewares={middlewares}
labelImages
enabledTools={["create-keypoints"]}
keypointDefinitions={{
human: {
connections: [
["head", "sternum"],
["sternum", "leftElbow"],
["sternum", "rightElbow"],
],
landmarks: {
head: {
label: "Head",
color: "#f00",
defaultPosition: [0, -0.05],
},
sternum: {
label: "Torso",
color: "#0f0",
defaultPosition: [0, 0],
},
leftElbow: {
label: "Left Elbow",
color: "#00f",
defaultPosition: [-0.05, 0],
},
rightElbow: {
label: "Right Elbow",
color: "#00f",
defaultPosition: [0.05, 0],
},
},
},
}}
images={[
{
src: dancingManImage,
name: "Dancing Man",
regions: [
{
type: "keypoints",
id: "keypoints1",
keypointsDefinitionId: "human",
highlighted: true,
points: {
head: { x: 0.54, y: 0.2 },
sternum: { x: 0.57, y: 0.3 },
leftElbow: { x: 0.4, y: 0.39 },
rightElbow: { x: 0.7, y: 0.32 },
},
visible: true,
},
],
},
]}
/>
))
73 changes: 73 additions & 0 deletions src/Annotator/reducers/general-reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import colors from "../../colors"
import fixTwisted from "./fix-twisted"
import convertExpandingLineToPolygon from "./convert-expanding-line-to-polygon"
import clamp from "clamp"
import getLandmarksWithTransform from "../../utils/get-landmarks-with-transform"

const getRandomId = () => Math.random().toString().split(".")[1]

Expand Down Expand Up @@ -206,6 +207,16 @@ export default (state: MainLayoutState, action: Action) => {
pointIndex,
})
}
case "BEGIN_MOVE_KEYPOINT": {
const { region, keypointId } = action
state = closeEditors(state)
state = saveToHistory(state, "Move Keypoint")
return setIn(state, ["mode"], {
mode: "MOVE_KEYPOINT",
regionId: region.id,
keypointId,
})
}
case "ADD_POLYGON_POINT": {
const { polygon, point, pointIndex } = action
const regionIndex = getRegionIndex(polygon)
Expand Down Expand Up @@ -240,6 +251,22 @@ export default (state: MainLayoutState, action: Action) => {
[x, y]
)
}
case "MOVE_KEYPOINT": {
const { keypointId, regionId } = state.mode
const [region, regionIndex] = getRegion(regionId)
if (regionIndex === null) return state
return setIn(
state,
[
...pathToActiveImage,
"regions",
regionIndex,
"points",
keypointId,
],
{ ...(region: any).points[keypointId], x, y }
)
}
case "MOVE_REGION": {
const { regionId } = state.mode
if (regionId === "$$allowed_area") {
Expand Down Expand Up @@ -312,6 +339,20 @@ export default (state: MainLayoutState, action: Action) => {
h: dh,
})
}
case "RESIZE_KEYPOINTS": {
const { regionId, landmarks, centerX, centerY } = state.mode
const distFromCenter = Math.sqrt(
(centerX - x) ** 2 + (centerY - y) ** 2
)
const scale = distFromCenter / 0.15
return modifyRegion(regionId, {
points: getLandmarksWithTransform({
landmarks,
center: { x: centerX, y: centerY },
scale,
}),
})
}
case "DRAW_POLYGON": {
const { regionId } = state.mode
const [region, regionIndex] = getRegion(regionId)
Expand Down Expand Up @@ -541,6 +582,34 @@ export default (state: MainLayoutState, action: Action) => {
})
break
}
case "create-keypoints": {
state = saveToHistory(state, "Create Keypoints")
const [
[keypointsDefinitionId, { landmarks, connections }],
] = (Object.entries(state.keypointDefinitions): any)

newRegion = {
type: "keypoints",
keypointsDefinitionId,
points: getLandmarksWithTransform({
landmarks,
center: { x, y },
scale: 1,
}),
highlighted: true,
editingLabels: false,
id: getRandomId(),
}
state = setIn(state, ["mode"], {
mode: "RESIZE_KEYPOINTS",
landmarks,
centerX: x,
centerY: y,
regionId: newRegion.id,
isNew: true,
})
break
}
default:
break
}
Expand Down Expand Up @@ -581,9 +650,13 @@ export default (state: MainLayoutState, action: Action) => {
}
}
case "MOVE_REGION":
case "RESIZE_KEYPOINTS":
case "MOVE_POLYGON_POINT": {
return { ...state, mode: null }
}
case "MOVE_KEYPOINT": {
return { ...state, mode: null }
}
case "CREATE_POINT_LINE": {
return state
}
Expand Down
4 changes: 2 additions & 2 deletions src/Annotator/video.story.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ storiesOf("Annotator(video)", module).add("Video Annotator", () => {
regionClsList: ["valid", "invalid"],
enabledTools: ["select", "create-box", "create-polygon", "create-point"],
keyframes: {
"0": {
0: {
regions: [
{
id: "910517662556203",
Expand All @@ -25,7 +25,7 @@ storiesOf("Annotator(video)", module).add("Video Annotator", () => {
},
],
},
"2656": {
2656: {
regions: [
{
id: "910517662556203",
Expand Down
Binary file added src/ImageCanvas/dancing-man.story.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 14 additions & 1 deletion src/ImageCanvas/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ import React, {
import type { Node } from "react"
import { Matrix } from "transformation-matrix-js"
import Crosshairs from "../Crosshairs"
import type { Region, Point, Polygon, Box } from "./region-tools.js"
import type {
Region,
Point,
Polygon,
Box,
Keypoints,
KeypointsDefinition,
} from "./region-tools.js"
import { makeStyles } from "@material-ui/core/styles"
import styles from "./styles"
import PreventScrollToParents from "../PreventScrollToParents"
Expand All @@ -36,6 +43,7 @@ type Props = {
imageSrc?: string,
videoSrc?: string,
videoTime?: number,
keypointDefinitions?: KeypointDefinitions,
onMouseMove?: ({ x: number, y: number }) => any,
onMouseDown?: ({ x: number, y: number }) => any,
onMouseUp?: ({ x: number, y: number }) => any,
Expand Down Expand Up @@ -65,6 +73,7 @@ type Props = {
onDeleteRegion: (Region) => any,
onBeginBoxTransform: (Box, [number, number]) => any,
onBeginMovePolygonPoint: (Polygon, index: number) => any,
onBeginMoveKeypoint: (Keypoints, index: number) => any,
onAddPolygonPoint: (Polygon, point: [number, number], index: number) => any,
onSelectRegion: (Region) => any,
onBeginMovePoint: (Point) => any,
Expand Down Expand Up @@ -120,6 +129,7 @@ export const ImageCanvas = ({
onBeginBoxTransform,
onBeginMovePolygonPoint,
onAddPolygonPoint,
onBeginMoveKeypoint,
onSelectRegion,
onBeginMovePoint,
onDeleteRegion,
Expand All @@ -128,6 +138,7 @@ export const ImageCanvas = ({
onRegionClassAdded,
zoomOnAllowedArea = true,
modifyingAllowedArea = false,
keypointDefinitions,
}: Props) => {
const classes = useStyles()

Expand Down Expand Up @@ -356,6 +367,7 @@ export const ImageCanvas = ({
mat={mat}
onBeginBoxTransform={onBeginBoxTransform}
onBeginMovePolygonPoint={onBeginMovePolygonPoint}
onBeginMoveKeypoint={onBeginMoveKeypoint}
onAddPolygonPoint={onAddPolygonPoint}
showHighlightBox={showHighlightBox}
/>
Expand Down Expand Up @@ -440,6 +452,7 @@ export const ImageCanvas = ({
/>
<RegionShapes
mat={mat}
keypointDefinitions={keypointDefinitions}
imagePosition={imagePosition}
regions={regions}
fullSegmentationMode={fullImageSegmentationMode}
Expand Down
Loading

0 comments on commit 772db6c

Please sign in to comment.