Skip to content

Commit ff20e29

Browse files
committed
initial pose estimation drawing in ImageCanvas
1 parent d9e5a65 commit ff20e29

File tree

5 files changed

+151
-6
lines changed

5 files changed

+151
-6
lines changed
126 KB
Loading

src/ImageCanvas/index.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ import React, {
1010
import type { Node } from "react"
1111
import { Matrix } from "transformation-matrix-js"
1212
import Crosshairs from "../Crosshairs"
13-
import type { Region, Point, Polygon, Box } from "./region-tools.js"
13+
import type {
14+
Region,
15+
Point,
16+
Polygon,
17+
Box,
18+
KeypointsDefinition,
19+
} from "./region-tools.js"
1420
import { makeStyles } from "@material-ui/core/styles"
1521
import styles from "./styles"
1622
import PreventScrollToParents from "../PreventScrollToParents"
@@ -36,6 +42,7 @@ type Props = {
3642
imageSrc?: string,
3743
videoSrc?: string,
3844
videoTime?: number,
45+
keypointDefinitions?: KeypointDefinitions,
3946
onMouseMove?: ({ x: number, y: number }) => any,
4047
onMouseDown?: ({ x: number, y: number }) => any,
4148
onMouseUp?: ({ x: number, y: number }) => any,
@@ -128,6 +135,7 @@ export const ImageCanvas = ({
128135
onRegionClassAdded,
129136
zoomOnAllowedArea = true,
130137
modifyingAllowedArea = false,
138+
keypointDefinitions,
131139
}: Props) => {
132140
const classes = useStyles()
133141

@@ -440,6 +448,7 @@ export const ImageCanvas = ({
440448
/>
441449
<RegionShapes
442450
mat={mat}
451+
keypointDefinitions={keypointDefinitions}
443452
imagePosition={imagePosition}
444453
regions={regions}
445454
fullSegmentationMode={fullImageSegmentationMode}

src/ImageCanvas/index.story.js

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// @flow
2-
31
import React from "react"
42

53
import { storiesOf } from "@storybook/react"
@@ -8,6 +6,7 @@ import { action } from "@storybook/addon-actions"
86
import ImageCanvas from "./"
97
import exampleMask from "./mouse_mask.story.png"
108
import exampleImage from "./seves_desk.story.jpg"
9+
import dancingManImage from "./dancing-man.story.jpg"
1110

1211
export const testRegions = [
1312
{
@@ -158,3 +157,56 @@ storiesOf("ImageCanvas", module)
158157
{...events}
159158
/>
160159
))
160+
.add("Poses", () => (
161+
<ImageCanvas
162+
keypointDefinitions={{
163+
human: {
164+
connections: [
165+
["head", "torso"],
166+
["torso", "leftElbow"],
167+
["torso", "rightElbow"],
168+
],
169+
landmarks: {
170+
head: {
171+
label: "Head",
172+
color: "#f00",
173+
defaultPosition: [0, -0.05],
174+
},
175+
torso: {
176+
label: "Torso",
177+
color: "#0f0",
178+
defaultPosition: [0, 0],
179+
},
180+
leftElbow: {
181+
label: "Left Elbow",
182+
color: "#00f",
183+
defaultPosition: [-0.05, 0],
184+
},
185+
rightElbow: {
186+
label: "Right Elbow",
187+
color: "#00f",
188+
defaultPosition: [0.05, 0],
189+
},
190+
},
191+
},
192+
}}
193+
regions={[
194+
{
195+
type: "keypoints",
196+
id: "keypoints1",
197+
keypointDefinitionId: "human",
198+
highlighted: true,
199+
points: {
200+
head: [0.5, 0.4],
201+
torso: [0.5, 0.5],
202+
leftElbow: [0.4, 0.5],
203+
rightElbow: [0.6, 0.5],
204+
},
205+
visible: true,
206+
},
207+
]}
208+
imageSrc={dancingManImage}
209+
showTags
210+
{...events}
211+
/>
212+
))

src/ImageCanvas/region-tools.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export type Box = {|
4141
w: number,
4242
h: number,
4343
|}
44+
4445
export type Polygon = {|
4546
...$Exact<BaseRegion>,
4647
type: "polygon",
@@ -53,7 +54,38 @@ export type ExpandingLine = {|
5354
points: Array<{ x: number, y: number, angle: number, width: number }>,
5455
|}
5556

56-
export type Region = Point | PixelRegion | Box | Polygon | ExpandingLine
57+
export type Keypoint = {|
58+
label: string,
59+
defaultPosition: [number, number],
60+
|}
61+
62+
export type KeypointId = string
63+
64+
export type KeypointsDefinition = {|
65+
[id: string]: {
66+
connections: Array<[KeypointId, KeypointId]>,
67+
landmarks: {
68+
[KeypointId]: Keypoint,
69+
},
70+
},
71+
|}
72+
73+
export type Keypoints = {|
74+
...$Exact<BaseRegion>,
75+
type: "keypoints",
76+
keypointsDefinitionId: string,
77+
points: {
78+
[string]: [number, number],
79+
},
80+
|}
81+
82+
export type Region =
83+
| Point
84+
| PixelRegion
85+
| Box
86+
| Polygon
87+
| ExpandingLine
88+
| Keypoints
5789

5890
export const getEnclosingBox = (region: Region) => {
5991
switch (region.type) {

src/RegionShapes/index.js

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,55 @@ const RegionComponents = {
4646
/>
4747
)
4848
}),
49+
keypoints: ({ region, iw, ih, keypointDefinitions }) => {
50+
const { points, keypointDefinitionId } = region
51+
if (!keypointDefinitions[keypointDefinitionId]) {
52+
throw new Error(
53+
`No definition for keypoint configuration "${keypointDefinitionId}"`
54+
)
55+
}
56+
const { landmarks, connections } = keypointDefinitions[keypointDefinitionId]
57+
return (
58+
<g>
59+
{Object.entries(points).map(([keypointId, [x, y]], i) => (
60+
<g key={i} transform={`translate(${x * iw} ${y * ih})`}>
61+
<path
62+
d={"M0 8L8 0L0 -8L-8 0Z"}
63+
strokeWidth={2}
64+
stroke={landmarks[keypointId].color}
65+
fill="transparent"
66+
/>
67+
</g>
68+
))}
69+
{connections.map(([kp1Id, kp2Id]) => {
70+
const kp1 = points[kp1Id]
71+
const kp2 = points[kp2Id]
72+
const midPoint = [(kp1[0] + kp2[0]) / 2, (kp1[1] + kp2[1]) / 2]
73+
74+
return (
75+
<g key={`${kp1}.${kp2}`}>
76+
<line
77+
x1={kp1[0] * iw}
78+
y1={kp1[1] * ih}
79+
x2={midPoint[0] * iw}
80+
y2={midPoint[1] * ih}
81+
strokeWidth={2}
82+
stroke={landmarks[kp1Id].color}
83+
/>
84+
<line
85+
x1={kp2[0] * iw}
86+
y1={kp2[1] * ih}
87+
x2={midPoint[0] * iw}
88+
y2={midPoint[1] * ih}
89+
strokeWidth={2}
90+
stroke={landmarks[kp2Id].color}
91+
/>
92+
</g>
93+
)
94+
})}
95+
</g>
96+
)
97+
},
4998
"expanding-line": memo(({ region, iw, ih }) => {
5099
let { expandingWidth = 0.005, points } = region
51100
expandingWidth = points.slice(-1)[0].width || expandingWidth
@@ -114,7 +163,7 @@ const RegionComponents = {
114163
}
115164

116165
export const WrappedRegionList = memo(
117-
({ regions, iw, ih, fullSegmentationMode }) => {
166+
({ regions, keypointDefinitions, iw, ih, fullSegmentationMode }) => {
118167
return regions
119168
.filter((r) => r.visible !== false)
120169
.map((r) => {
@@ -125,7 +174,8 @@ export const WrappedRegionList = memo(
125174
region={r}
126175
iw={iw}
127176
ih={ih}
128-
fullgeSegmentationMode={fullSegmentationMode}
177+
keypointDefinitions={keypointDefinitions}
178+
fullSegmentationMode={fullSegmentationMode}
129179
/>
130180
)
131181
})
@@ -137,6 +187,7 @@ export const RegionShapes = ({
137187
mat,
138188
imagePosition,
139189
regions = [],
190+
keypointDefinitions,
140191
fullSegmentationMode,
141192
}) => {
142193
const iw = imagePosition.bottomRight.x - imagePosition.topLeft.x
@@ -161,6 +212,7 @@ export const RegionShapes = ({
161212
regions={regions}
162213
iw={iw}
163214
ih={ih}
215+
keypointDefinitions={keypointDefinitions}
164216
fullSegmentationMode={fullSegmentationMode}
165217
/>
166218
</svg>

0 commit comments

Comments
 (0)