ProcessImage.tsx 8.39 KB
Newer Older
Matija Obreza's avatar
Matija Obreza committed
1
import * as React from 'react';
Matija Obreza's avatar
Matija Obreza committed
2
import { withStyles } from '@material-ui/core/styles';
Matija Obreza's avatar
Matija Obreza committed
3
import { count } from '@gringlobal/counter/counter';
4
import { logElapsed, colorMainsClassifier, filterBlur } from '@gringlobal/counter/filters';
Matija Obreza's avatar
Matija Obreza committed
5

Matija Obreza's avatar
Matija Obreza committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const styles = {
  canvases: {
    'flex-flow': 'row wrap',
    'display': 'flex',
  },
  canvasBox: {
    backgroundRepeat: 'no-repeat',
    backgroundSize: 'contain',
    margin: '5px',
    border: 'solid 1px green',
  },
  originalContainer: {
    position: 'relative' as 'relative',
  },
  original: {
    width: '100%',
    position: 'relative' as 'relative',
Matija Obreza's avatar
Matija Obreza committed
23
    // visibility: 'hidden' as 'hidden',
Matija Obreza's avatar
Matija Obreza committed
24
25
26
27
  },
  resultOverlay: {
    width: '100%',
    minHeight: '20px',
28
    // position: 'absolute' as 'absolute',
Matija Obreza's avatar
Matija Obreza committed
29
    border: 'solid 1px red',
30
    backgroundColor: 'lime',
Matija Obreza's avatar
Matija Obreza committed
31
32
    top: -1,
    left: -1,
Matija Obreza's avatar
Matija Obreza committed
33
34
35
36
37
38
39
  },
  canvas: {
    maxHeight: '200px',
    minWidth: '100px',
    minHeight: '100px',
  },
  originalGraphics: {
Matija Obreza's avatar
Matija Obreza committed
40
    // width: '100%',
Matija Obreza's avatar
Matija Obreza committed
41
42
  },
};
Matija Obreza's avatar
Matija Obreza committed
43

44
45
const L = console.log;

Matija Obreza's avatar
Matija Obreza committed
46
47
48
class ProcessImage extends React.Component<any> {

  // private MAX_PROCESSING_WIDTH: number = 300;
49
50
  private logger: any;
  private loggerDate: number = Date.now();
Matija Obreza's avatar
Matija Obreza committed
51
52
53
54
55
56
57
  private original: any;
  private originalVideo: any;
  private resultOverlay: any;
  private canvasSource: any;

  public constructor(props) {
    super(props);
58
    this.logger = React.createRef();
Matija Obreza's avatar
Matija Obreza committed
59
60
61
62
63
    this.original = React.createRef();
    this.originalVideo = React.createRef();
    this.resultOverlay = React.createRef();
    this.canvasSource = React.createRef();
  }
Matija Obreza's avatar
Matija Obreza committed
64

Matija Obreza's avatar
Matija Obreza committed
65
66
  public state = {
    count: 0,
Matija Obreza's avatar
Matija Obreza committed
67
    video: false,
Matija Obreza's avatar
Matija Obreza committed
68
69
  };

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  public componentDidMount() {
    console.log('Component did mount', this.logger);
    if (this.logger.current && this.logger.current.appendChild) {
      console.log = (text, ...args) => {
        const time = Date.now();
        L(`+${time - this.loggerDate} ${text}`, ...args);
        const msg = document.createElement('pre');
        msg.innerHTML = `+${time - this.loggerDate} ${text}`; // \n${args.map((arg) => `${JSON.stringify(arg, null, 2).substring(0, 300)}\n\n`)}`;
        this.logger.current.appendChild(msg);
        this.loggerDate = time;
      }
    }
  }

  public componentWillUnmount() {
    console.log = L;
    L('Reset console.log');
  }

Matija Obreza's avatar
Matija Obreza committed
89
90
  private resizeCanvases = () => {
    const source = this.state.video ? this.originalVideo.current : this.original.current;
Matija Obreza's avatar
Matija Obreza committed
91
    console.log(`Source ${this.state.video ? 'Video' : 'Image'} size ${this.state.video ? source.videoWidth : source.width}x${this.state.video ? source.videoHeight : source.height}`);
Matija Obreza's avatar
Matija Obreza committed
92
93
94
95
96
    // canvas.width = video.videoWidth;
    const ratio = this.state.video ? source.videoWidth / source.videoHeight : source.width / source.height;
    // original.height = original.width / ratio;
    // this.resultOverlay.current.style.width = this.state.video ? source.videoWidth : source.width;
    // this.resultOverlay.current.style.height = this.state.video ? source.videoHeight : source.height;
Matija Obreza's avatar
Matija Obreza committed
97
    this.canvasSource.current.width = this.resultOverlay.current.width = Math.min(640, this.state.video ? source.videoWidth : source.width);
Matija Obreza's avatar
Matija Obreza committed
98
99
100
101
102
103
104
105
106
    this.canvasSource.current.height = this.resultOverlay.current.height = this.resultOverlay.current.width / ratio;
    // for (const canvas2 of canvases) {
    //   canvas2.width = canvas.width;
    //   canvas2.height = canvas.height;
    // }
    this.captureImage();
  }

  private captureImage = () => {
107
108
109
    if (this.logger.current) {
      this.logger.current.innerHTML = '';
    }
Matija Obreza's avatar
Matija Obreza committed
110
111
    const source = this.state.video ? this.originalVideo.current : this.original.current;
    const contextSource = this.canvasSource.current.getContext('2d');
Matija Obreza's avatar
Matija Obreza committed
112
    contextSource.imageSmoothingEnabled = false;
Matija Obreza's avatar
Matija Obreza committed
113
114
115
    contextSource.drawImage(source, 0, 0, this.canvasSource.current.width, this.canvasSource.current.height);
    const image = contextSource.getImageData(0, 0, this.canvasSource.current.width, this.canvasSource.current.height);
    console.log(`Image data ${image.width}x${image.height}`);
Matija Obreza's avatar
Matija Obreza committed
116
117
118
119
    let startTime = Date.now();
    // const filtered = filterThinEdges(filterSum(filterSobel(filterSmooth(image))));
    // let filtered = filterBW(image);
    // startTime = logElapsed(startTime, 'filterBw');
Matija Obreza's avatar
Matija Obreza committed
120
121
122
123
    // let filtered = filterSharpenWithMask(image);
    // startTime = logElapsed(startTime, 'filterSharpen');
    let filtered = filterBlur(image);
    startTime = logElapsed(startTime, 'filterBlur');
124
125
126
127
128
129
130
131
132
133
134
135
    filtered = colorMainsClassifier(filtered, 2);
    startTime = logElapsed(startTime, 'colorMainsClassifier');
    // filtered = colorClassifier(filtered, 4);
    // startTime = logElapsed(startTime, 'colorClassifier');
    // filtered = filterSobel(filtered);
    // startTime = logElapsed(startTime, 'filterSobel');
    // filtered = filterTakeHighest(filtered);
    // startTime = logElapsed(startTime, 'filterSum');
    // filtered = filterSharpenWithMask(filtered, 2);
    // startTime = logElapsed(startTime, 'filterSharpenWithMask');
    // filtered = filterOutline(filtered);
    // startTime = logElapsed(startTime, 'filterOutline');
Matija Obreza's avatar
Matija Obreza committed
136
137
138
    // filtered = filterBW(filtered);
    // startTime = logElapsed(startTime, 'filterBW');
    // filtered = filterThreshold(filtered, 50);
Matija Obreza's avatar
Matija Obreza committed
139
140
141
142
143
144
    // startTime = logElapsed(startTime, 'filterThreshold');
    // filtered = filterThinEdges(filtered);
    // startTime = logElapsed(startTime, 'filterThinEdges');
    const contextResult = this.resultOverlay.current.getContext('2d');
    contextResult.putImageData(filtered, 0, 0);
    contextResult.imageSmoothingEnabled = false;
Matija Obreza's avatar
Matija Obreza committed
145
146
147
148

    if (this.state.video) {
      setTimeout(() => { this.captureImage(); }, 500);
    }
Matija Obreza's avatar
Matija Obreza committed
149
150
  }

Matija Obreza's avatar
Matija Obreza committed
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
  private toggleCamera = () => {
    console.log('Toggling camera');

    // const supportedConstraints = navigator.mediaDevices.getSupportedConstraints();
    // let constraintStr: string = '';
    // for (const constraint in supportedConstraints) {
    //   if (supportedConstraints.hasOwnProperty(constraint)) {
    //     constraintStr += constraint + '\n';
    //   }
    // }
    // window.alert(`Media constraints:\n${constraintStr}`);

    // this.captureImage();
    const constraints = {
      video: {
        facingMode: 'environment',
        width: { min: 400, ideal: 800, max: 2000 },
        height: { min: 400, ideal: 600, max: 2000 },
      },
    };

    // if (this.originalVideo.current && ! this.originalVideo.current.srcObject) {
    // Get access to the camera!
    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
      // Not adding `{ audio: true }` since we only want video now
      navigator.mediaDevices.getUserMedia(constraints).then((stream) => {
        this.originalVideo.current.srcObject = stream;
        this.originalVideo.current.play();
      }).catch((err) => {
        window.alert('Error' + JSON.stringify(err));
        console.log('An error occurred: ', err);
      });
    }
    // }

    this.setState({ count: count(this.state.count), video: !this.state.video });
  };

  private fileChanged = (ev) => {
    const files = ev.target.files;
    // FileReader support
    if (FileReader && files && files.length) {
      const fr = new FileReader();
      fr.onload = () => {
        console.log('Original', this.original.current);
        this.original.current.src = fr.result;
      };
      fr.readAsDataURL(files[0]);
    }
  };

Matija Obreza's avatar
Matija Obreza committed
202
  public render(): React.ReactNode {
Matija Obreza's avatar
Matija Obreza committed
203
    const { classes } = this.props;
Matija Obreza's avatar
Matija Obreza committed
204
205
    return (
      <div>
Matija Obreza's avatar
Matija Obreza committed
206
        { ! this.state.video && <div>
Matija Obreza's avatar
Matija Obreza committed
207
          <form>
Matija Obreza's avatar
Matija Obreza committed
208
            <input type="file" onChange={ this.fileChanged } id="myfile" />
Matija Obreza's avatar
Matija Obreza committed
209
210
            <input type="reset" value="Clear" />
          </form>
Matija Obreza's avatar
Matija Obreza committed
211
        </div> }
Matija Obreza's avatar
Matija Obreza committed
212
        <h1>Count: { this.state.count }</h1>
Matija Obreza's avatar
Matija Obreza committed
213
        <div className={ classes.originalContainer }>
214
          <img ref={ this.original } onLoad={ this.resizeCanvases } className={ classes.original } src="examples/G25012 seed.jpg" style={ { display: this.state.video ? 'none' : '' } } />
Matija Obreza's avatar
Matija Obreza committed
215
216
217
218
          <video ref={ this.originalVideo } className={ classes.original } onPlaying={ this.resizeCanvases } style={ { display: this.state.video ? '' : 'none' } } ></video>
          <canvas ref={ this.resultOverlay } className={ classes.resultOverlay }></canvas>
        </div>
        <button onClick={ this.toggleCamera }>Camera</button>
219
220
        <h1>Log</h1>
        <div ref={ this.logger }></div>
Matija Obreza's avatar
Matija Obreza committed
221
        <h1>Debugger</h1>
Matija Obreza's avatar
Matija Obreza committed
222
223
        <div id="canvases" className={ classes.canvases } />
        <canvas ref={ this.canvasSource } className={ classes.originalGraphics }></canvas>
Matija Obreza's avatar
Matija Obreza committed
224
225
226
227
228
      </div>
    );
  }
}

Matija Obreza's avatar
Matija Obreza committed
229
export default withStyles(styles)(ProcessImage);