Skip to content

Commit c36ce81

Browse files
committed
Made cpp code work in browser 🎉
1 parent 16a028b commit c36ce81

File tree

8 files changed

+4728
-1007
lines changed

8 files changed

+4728
-1007
lines changed

package-lock.json

Lines changed: 4622 additions & 951 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"@semantic-release/git": "^9.0.0",
1111
"get-image-data": "^3.0.1",
1212
"material-survey": "^1.0.34",
13-
"mmgc1-cpp": "^1.0.0",
13+
"mmgc1-cpp": "^1.0.2",
1414
"moment": "^2.23.0",
1515
"react-full-screen": "^0.2.4",
1616
"react-hotkeys": "^2.0.0",
@@ -71,7 +71,6 @@
7171
"babel-preset-react-app": "^7.0.0",
7272
"gh-pages": "^2.0.1",
7373
"prettier": "^2.0.5",
74-
"raw.macro": "^0.3.0",
7574
"react-github-btn": "^1.1.1",
7675
"react-scripts": "^2.1.8"
7776
},

src/FullImageSegmentationAnnotator/index.js

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,13 @@
22
import React from "react"
33
import Annotator from "../Annotator"
44

5-
const [width, height] = [200, 200]
6-
7-
// TODO remove this !!!!
8-
const uint8Array = new Uint8ClampedArray(4 * width * height)
95

10-
for (let ri = 0; ri < width; ri++) {
11-
for (let ci = 0; ci < height; ci++) {
12-
uint8Array[(ri * width + ci) * 4 + 0] = Math.floor(Math.random() * 256)
13-
uint8Array[(ri * width + ci) * 4 + 1] = Math.floor(Math.random() * 256)
14-
uint8Array[(ri * width + ci) * 4 + 2] = Math.floor(Math.random() * 256)
15-
uint8Array[(ri * width + ci) * 4 + 3] = 255
16-
}
17-
}
18-
19-
const imageData = new ImageData(uint8Array, width, height)
20-
// TODO remove this !!!!
6+
const [width, height] = [200, 200]
217

228
export default ({ onExit, images }) => {
239
return (
2410
<Annotator
11+
regionClsList={["cat", "dog"]}
2512
images={images}
2613
onExit={onExit}
2714
fullImageSegmentationMode={true}

src/FullImageSegmentationAnnotator/index.story.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ storiesOf("FullImageSegmentationAnnotator", module).add("Basic", () => (
1414
images={[
1515
{
1616
name: "Seve's Desk",
17-
src: exampleImage,
17+
src: "https://a.allegroimg.com/s128/113a6e/09d2c0ed4f278610e555c95b1d50/Rama-BIANCHI-OLTRE-XR4-DISC-carbon-Vision-ACR-51cm-Dedykowany-a-do-kolarstwo-szosowe",
1818
},
1919
]}
2020
onExit={action("onExit")}

src/ImageCanvas/index.js

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @flow weak
22

3-
import React, { useRef, useState, useLayoutEffect } from "react"
3+
import React, { useRef, useState, useLayoutEffect, useMemo } from "react"
44
import type { Node } from "react"
55
import { Matrix } from "transformation-matrix-js"
66
import Crosshairs from "../Crosshairs"
@@ -44,8 +44,6 @@ type Props = {
4444
allowedArea?: { x: number, y: number, w: number, h: number },
4545
RegionEditLabel?: Node,
4646
videoPlaying?: boolean,
47-
mask?: ImageData,
48-
maskVersion?: any,
4947
fullImageSegmentationMode?: boolean,
5048

5149
onChangeRegion: (Region) => any,
@@ -90,8 +88,6 @@ export const ImageCanvas = ({
9088
allowedArea,
9189
RegionEditLabel = null,
9290
videoPlaying = false,
93-
mask,
94-
maskVersion,
9591
fullImageSegmentationMode,
9692
onImageOrVideoLoaded,
9793
onChangeRegion,
@@ -388,6 +384,12 @@ export const ImageCanvas = ({
388384
topLeft: mat.clone().inverse().applyToPoint(0, 0),
389385
bottomRight: mat.clone().inverse().applyToPoint(iw, ih),
390386
}
387+
388+
const classPoints = useMemo(() => {
389+
console.log("TODO this shouldn't be called on mouse moves")
390+
return regions.filter(region => region.type === "point")
391+
}
392+
,[regions])
391393

392394
return (
393395
<div
@@ -480,14 +482,13 @@ export const ImageCanvas = ({
480482
{...mouseEvents}
481483
>
482484
<>
483-
{mask && (
484-
<ImageMask
485-
maskVersion={maskVersion}
486-
videoPlaying={videoPlaying}
487-
imagePosition={imagePosition}
488-
imageData={mask}
489-
/>
490-
)}
485+
{fullImageSegmentationMode && <ImageMask
486+
imagePosition={imagePosition}
487+
regionClsList={regionClsList}
488+
imageSrc={imageSrc}
489+
classPoints={classPoints
490+
}
491+
/>}
491492
<canvas className={classes.canvas} ref={canvasEl} />
492493
<VideoOrImageCanvasBackground
493494
videoPlaying={videoPlaying}

src/ImageMask/index.js

Lines changed: 82 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,98 @@
11
// @flow
22

3-
import React, { useState, useEffect, useMemo } from "react"
3+
import React, { useState, useEffect, useMemo, useRef } from "react"
44

55
import mmgc from "mmgc1-cpp"
66

7+
console.log(mmgc)
8+
79
export default ({
810
classPoints,
9-
imageData,
11+
regionClsList,
12+
imageSrc,
1013
imagePosition,
11-
videoPlaying,
12-
maskVersion,
13-
pointerEvents = "none",
1414
opacity = 0.5,
1515
zIndex = 999,
1616
position = "absolute",
1717
}) => {
1818
const [canvasRef, setCanvasRef] = useState(null)
19+
20+
const lastTimeMMGCRun = useRef(Date.now());
21+
const superPixelsGenerated = useRef(false)
22+
const [sampleImageData, setSampleImageData] = useState()
23+
24+
useEffect(() => {
25+
if (!imageSrc) return;
26+
const canvas = document.querySelector("canvas");
27+
const ctx = canvas.getContext("2d");
28+
29+
const image = new Image();
30+
image.src = imageSrc;
31+
image.onload = () => {
32+
ctx.width = image.naturalWidth
33+
ctx.height = image.naturalHeight
34+
ctx.drawImage(image, 0, 0);
35+
const imageData = ctx.getImageData(0, 0, image.naturalWidth, image.naturalHeight)
36+
superPixelsGenerated.current = false;
37+
setSampleImageData(imageData)
38+
}
39+
}, [imageSrc])
40+
1941

2042
useEffect(() => {
2143
if (!canvasRef) return
44+
if (!sampleImageData) return
45+
if (!mmgc.setImage) return
46+
if (Date.now() < lastTimeMMGCRun.current + 5000) return
2247
const context = canvasRef.getContext("2d")
23-
context.putImageData(imageData, 0, 0)
24-
}, [canvasRef, imageData, maskVersion])
48+
49+
console.log("got the sample image data and ready to mmgc!")
50+
51+
if (!superPixelsGenerated.current) {
52+
console.log("generating super pixels...")
53+
mmgc.setImage(sampleImageData.data, sampleImageData.width, sampleImageData.height);
54+
mmgc.computeSuperPixels()
55+
superPixelsGenerated.current = true
56+
}
57+
58+
// mmgc.setClassColor(0, 0xffffffff)
59+
// mmgc.setClassColor(1, 0x00000000)
60+
console.log("generating mask...")
61+
mmgc.clearClassPoints()
62+
for (const classPoint of classPoints) {
63+
if (!classPoint.cls) continue
64+
if (classPoint.x < 0) continue
65+
///etc...
66+
console.log(
67+
regionClsList.indexOf(classPoint.cls), Math.floor(
68+
classPoint.y * sampleImageData.height
69+
), Math.floor(classPoint.x * sampleImageData.width
70+
)
71+
)
72+
mmgc.addClassPoint(regionClsList.indexOf(classPoint.cls), Math.floor(
73+
classPoint.y * sampleImageData.height
74+
), Math.floor(classPoint.x * sampleImageData.width
75+
))
76+
}
77+
// mmgc.addClassPoint(0, 100, 125)
78+
// mmgc.addClassPoint(1, 10, 10)
79+
// mmgc.addClassPoint(1, 240, 300)
80+
mmgc.computeMasks()
81+
const maskAddress = mmgc.getColoredMask()
82+
const cppImDataUint8 = new Uint8ClampedArray(
83+
mmgc.HEAPU8.buffer,
84+
maskAddress,
85+
sampleImageData.width * sampleImageData.height * 4
86+
)
87+
88+
const maskImageData = new ImageData(cppImDataUint8, sampleImageData.width, sampleImageData.height)
89+
90+
// for (const i = 0; i < cppImDataUint8.length;i++){
91+
// sampleImageData.data[i] = cppImDataUint8[i]
92+
// }
93+
context.clearRect(0,0,sampleImageData.width, sampleImageData.height)
94+
context.putImageData(maskImageData, 0, 0)
95+
}, [canvasRef, sampleImageData, JSON.stringify(classPoints.map(c => [c.x, c.y, c.cls]))])
2596

2697
const style = useMemo(() => {
2798
let width = imagePosition.bottomRight.x - imagePosition.topLeft.x
@@ -34,7 +105,7 @@ export default ({
34105
zIndex,
35106
position,
36107
opacity,
37-
pointerEvents,
108+
pointerEvents: "none",
38109
}
39110
}, [
40111
imagePosition.topLeft.x,
@@ -44,14 +115,13 @@ export default ({
44115
zIndex,
45116
position,
46117
opacity,
47-
pointerEvents,
48118
])
49-
119+
50120
return (
51121
<canvas
52122
style={style}
53-
width={imageData.width}
54-
height={imageData.height}
123+
width={sampleImageData ? sampleImageData.width : 0}
124+
height={sampleImageData ? sampleImageData.height : 0}
55125
ref={setCanvasRef}
56126
/>
57127
)

src/ImageMask/index.story.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ for (let ri = 0; ri < width; ri++) {
2323
const imageData = new ImageData(uint8Array, width, width)
2424

2525
storiesOf("ImageMask", module)
26-
.add("Basic", () => <ImageMask imageData={imageData} />)
26+
.add("Basic", () => <ImageMask imagePosition={{topLeft: {x: 0, y: 0}}} />)
2727
.add("Changing", () => {
2828
const [version, incVersion] = useReducer((state) => state + 1, 0)
2929

yarn.lock

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3551,7 +3551,7 @@ babel-plugin-macros@^2.0.0:
35513551
cosmiconfig "^5.2.0"
35523552
resolve "^1.10.0"
35533553

3554-
babel-plugin-macros@^2.1.0, babel-plugin-macros@^2.7.0:
3554+
babel-plugin-macros@^2.7.0:
35553555
version "2.8.0"
35563556
resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138"
35573557
integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==
@@ -10820,10 +10820,10 @@ mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@
1082010820
dependencies:
1082110821
minimist "0.0.8"
1082210822

10823-
mmgc1-cpp@^1.0.0:
10824-
version "1.0.0"
10825-
resolved "https://registry.yarnpkg.com/mmgc1-cpp/-/mmgc1-cpp-1.0.0.tgz#59b4532c82958733049e818c6831c7f7aa7cc1b7"
10826-
integrity sha512-QqIkVp428kdTeV0X8nnAVFWq6sutTZrb/hG0eMDQNv4m3cLkMoHBmAe7x8V8/m/NOT5ujMRKC8zMjZz3odqJvQ==
10823+
mmgc1-cpp@^1.0.2:
10824+
version "1.0.2"
10825+
resolved "https://registry.yarnpkg.com/mmgc1-cpp/-/mmgc1-cpp-1.0.2.tgz#6bf7d8c322a094181f1258ad98a5d3cc2355afa9"
10826+
integrity sha512-UQ0xUJx0L4LVy5H6tQwDLswiLrMXnsrUAo1Fd2sFHlBuNwW+x5xV+ZA+MW3yAoRXJcut5bXJ5MsVOd7dzr5ucA==
1082710827

1082810828
moment@^2.23.0:
1082910829
version "2.24.0"
@@ -13127,13 +13127,6 @@ raw-loader@^3.1.0:
1312713127
loader-utils "^1.1.0"
1312813128
schema-utils "^2.0.1"
1312913129

13130-
raw.macro@^0.3.0:
13131-
version "0.3.0"
13132-
resolved "https://registry.yarnpkg.com/raw.macro/-/raw.macro-0.3.0.tgz#b62391c5c7a77fd5673b688ac031ba0c5cbff1dc"
13133-
integrity sha512-VGX8RNUyZ7cZDa4dM8tvysaqryMSQRPbZqmTKKIur2uaGbpmG9Jj9CAY3ndpO8J3RMu0zf2K0JvIwbYMS29TOQ==
13134-
dependencies:
13135-
babel-plugin-macros "^2.1.0"
13136-
1313713130
rc@^1.0.1, rc@^1.1.6, rc@^1.2.7, rc@^1.2.8:
1313813131
version "1.2.8"
1313913132
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"

0 commit comments

Comments
 (0)