Skip to content

Commit 6d6a65b

Browse files
authored
feat: Merge pull request #66 from waoai/feat/autoseg
New Autosegmentation Engine
2 parents 54ebf6b + 2b876ea commit 6d6a65b

File tree

3 files changed

+55
-100
lines changed

3 files changed

+55
-100
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"@material-ui/core": "^4.6.0",
99
"@material-ui/icons": "^4.9.1",
1010
"@semantic-release/git": "^9.0.0",
11+
"autoseg": "^0.0.8",
1112
"color-alpha": "^1.0.4",
1213
"get-image-data": "^3.0.1",
1314
"material-survey": "^1.0.34",

src/ImageMask/index.js

Lines changed: 49 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,44 @@ import React, { useState, useEffect, useMemo, useRef } from "react"
44
import { colorInts } from "../colors"
55
import { useDebounce } from "react-use"
66
import loadImage from "./load-image"
7+
import autoseg from "autoseg/webworker"
78

8-
import MMGC_INIT from "mmgc1-cpp"
9+
function convertToUDTRegions(regions) {
10+
return regions
11+
.map((r) => {
12+
switch (r.type) {
13+
case "point": {
14+
return {
15+
regionType: "point",
16+
classification: r.cls,
17+
x: r.x,
18+
y: r.y,
19+
}
20+
}
21+
case "polygon": {
22+
return {
23+
regionType: "polygon",
24+
classification: r.cls,
25+
points: r.points.map(([x, y]) => ({ x, y })),
26+
}
27+
}
28+
case "box": {
29+
return {
30+
regionType: "bounding-box",
31+
classification: r.cls,
32+
centerX: r.x + r.w / 2,
33+
centerY: r.y + r.h / 2,
34+
width: r.w,
35+
height: r.h,
36+
}
37+
}
38+
default: {
39+
return null
40+
}
41+
}
42+
})
43+
.filter(Boolean)
44+
}
945

1046
export const ImageMask = ({
1147
regions,
@@ -16,18 +52,20 @@ export const ImageMask = ({
1652
hide = false,
1753
autoSegmentationOptions = { type: "simple" },
1854
}) => {
19-
if (!window.mmgc) window.mmgc = MMGC_INIT()
20-
const mmgc = window.mmgc
55+
// if (!window.mmgc) window.mmgc = MMGC_INIT()
56+
// const mmgc = window.mmgc
2157
const [canvasRef, setCanvasRef] = useState(null)
2258

23-
const superPixelsGenerated = useRef(false)
2459
const [sampleImageData, setSampleImageData] = useState()
2560

2661
useEffect(() => {
2762
if (!imageSrc) return
2863

2964
loadImage(imageSrc).then((imageData) => {
30-
superPixelsGenerated.current = false
65+
autoseg.setConfig({
66+
classNames: regionClsList,
67+
})
68+
autoseg.loadImage(imageData)
3169
setSampleImageData(imageData)
3270
})
3371
}, [imageSrc])
@@ -38,103 +76,14 @@ export const ImageMask = ({
3876
if (!canvasRef) return
3977
if (!sampleImageData) return
4078
if (regions.filter((cp) => cp.cls).length < 2) return
41-
if (!mmgc.setImageSize) return
42-
const context = canvasRef.getContext("2d")
43-
44-
if (!superPixelsGenerated.current) {
45-
superPixelsGenerated.current = "processing"
46-
mmgc.setSimpleMode(autoSegmentationOptions.type === "simple")
47-
mmgc.setMaxClusters(1000)
48-
mmgc.setImageSize(sampleImageData.width, sampleImageData.height)
49-
mmgc.setClassColor(0, 0)
50-
for (let i = 0; i < colorInts.length; i++) {
51-
mmgc.setClassColor(i + 1, colorInts[i])
52-
}
53-
const imageAddress = mmgc.getImageAddr()
54-
mmgc.HEAPU8.set(sampleImageData.data, imageAddress)
55-
mmgc.computeSuperPixels()
56-
superPixelsGenerated.current = "done"
57-
}
58-
if (superPixelsGenerated.current !== "done") return
59-
60-
// mmgc.setVerboseMode(true)
61-
if (
62-
!["bg", "background", "nothing"].includes(
63-
regionClsList[0].toLowerCase()
64-
)
65-
) {
66-
console.log(
67-
`first region cls must be "bg" or "background" or "nothing"`
68-
)
69-
return
70-
}
71-
mmgc.clearClassElements()
72-
const classPoints = regions
73-
.filter((r) => r.type === "point")
74-
.filter((r) => r.cls)
75-
for (const classPoint of classPoints) {
76-
if (classPoint.x < 0 || classPoint.x >= 1) continue
77-
if (classPoint.y < 0 || classPoint.y >= 1) continue
78-
const clsIndex = regionClsList.indexOf(classPoint.cls)
79-
if (clsIndex > colorInts.length) {
80-
console.log("Too many classes to draw on mask!")
81-
continue
82-
}
83-
84-
mmgc.addClassPoint(
85-
clsIndex,
86-
Math.floor(classPoint.y * sampleImageData.height),
87-
Math.floor(classPoint.x * sampleImageData.width)
88-
)
89-
}
90-
const classPolygons = regions
91-
.map((r) => {
92-
if (r.type !== "box") return r
93-
return {
94-
...r,
95-
type: "polygon",
96-
points: [
97-
[r.x, r.y],
98-
[r.x + r.w, r.y],
99-
[r.x + r.w, r.y + r.h],
100-
[r.x, r.y + r.h],
101-
],
102-
}
103-
})
104-
.filter((r) => r.type === "polygon")
105-
.filter((r) => r.cls)
106-
for (const polygon of classPolygons) {
107-
const { points } = polygon
108-
const clsIndex = regionClsList.indexOf(polygon.cls)
109-
const pi = mmgc.addPolygon(clsIndex)
110-
const pointPairs = points.map((p, i) => [
111-
p,
112-
points[(i + 1) % points.length],
113-
])
114-
for (const [p1, p2] of pointPairs) {
115-
const ri1 = Math.round(p1[1] * sampleImageData.height)
116-
const ci1 = Math.round(p1[0] * sampleImageData.width)
117-
const ri2 = Math.round(p2[1] * sampleImageData.height)
118-
const ci2 = Math.round(p2[0] * sampleImageData.width)
119-
mmgc.addLineToPolygon(pi, ri1, ci1, ri2, ci2)
120-
}
121-
}
12279

123-
mmgc.computeMasks()
124-
const maskAddress = mmgc.getColoredMask()
125-
const cppImDataUint8 = new Uint8ClampedArray(
126-
mmgc.HEAPU8.buffer,
127-
maskAddress,
128-
sampleImageData.data.length
129-
)
130-
const maskImageData = new ImageData(
131-
cppImDataUint8,
132-
sampleImageData.width,
133-
sampleImageData.height
134-
)
80+
const udtRegions = convertToUDTRegions(regions)
13581

136-
context.clearRect(0, 0, sampleImageData.width, sampleImageData.height)
137-
context.putImageData(maskImageData, 0, 0)
82+
autoseg.getMask(udtRegions).then((maskImageData) => {
83+
const context = canvasRef.getContext("2d")
84+
context.clearRect(0, 0, maskImageData.width, maskImageData.height)
85+
context.putImageData(maskImageData, 0, 0)
86+
})
13887
},
13988
1000,
14089
[canvasRef, sampleImageData, regions, hide]

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3270,6 +3270,11 @@ autoprefixer@^9.7.2:
32703270
postcss "^7.0.27"
32713271
postcss-value-parser "^4.0.3"
32723272

3273+
autoseg@^0.0.8:
3274+
version "0.0.8"
3275+
resolved "https://registry.yarnpkg.com/autoseg/-/autoseg-0.0.8.tgz#30e900afd41db964c5cdaf93f322211548444620"
3276+
integrity sha512-Kf6qQXiaxe+J1DrNP4dfWH92tRZ9MMwaO06TtzfKxBR/wtlC745aTP3YmKAP/a2ikpIfPKz9Hf6yR2Y7SeVagg==
3277+
32733278
aws-sign2@~0.7.0:
32743279
version "0.7.0"
32753280
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"

0 commit comments

Comments
 (0)