Skip to content
This repository was archived by the owner on Feb 10, 2025. It is now read-only.

Commit 81ce2d8

Browse files
authored
Merge pull request #17 from emmanuelle/rectangle
Added rectangle tool, and small modifications to image_with_contour
2 parents 2380786 + 357c3b1 commit 81ce2d8

File tree

8 files changed

+82
-37
lines changed

8 files changed

+82
-37
lines changed

dash_canvas/DashCanvas.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@ class DashCanvas(Component):
1010
1111
Keyword arguments:
1212
- id (string; optional): The ID used to identify this component in Dash callbacks
13-
- label (string; optional): A label that will be printed when this component is rendered.
1413
- image_content (string; optional): Image data string, formatted as png or jpg data string. Can be
1514
generated by utils.io_utils.array_to_data_string.
1615
- zoom (number; optional): Zoom factor
1716
- width (number; optional): Width of the canvas
1817
- height (number; optional): Height of the canvas
1918
- scale (number; optional): Scaling ratio between canvas width and image width
2019
- tool (string; optional): Selection of drawing tool, among ["pencil", "pan", "circle",
21-
"select", "line"].
20+
"rectangle", "select", "line"].
2221
- lineWidth (number; optional): Width of drawing line (in pencil mode)
2322
- lineColor (string; optional): Color of drawing line (in pencil mode). Can be a text string,
2423
like 'yellow', 'red', or a color triplet like 'rgb(255, 0, 0)'.
@@ -31,17 +30,17 @@ class DashCanvas(Component):
3130
annotations. Use utils.parse_json.parse_jsonstring to parse
3231
this string.
3332
- hide_buttons (list; optional): Names of buttons to hide. Names are "zoom", "pan", "line", "pencil",
34-
"undo", "select".
33+
"rectangle", "undo", "select".
3534
3635
Available events: """
3736
@_explicitize_args
38-
def __init__(self, id=Component.UNDEFINED, label=Component.UNDEFINED, image_content=Component.UNDEFINED, zoom=Component.UNDEFINED, width=Component.UNDEFINED, height=Component.UNDEFINED, scale=Component.UNDEFINED, tool=Component.UNDEFINED, lineWidth=Component.UNDEFINED, lineColor=Component.UNDEFINED, goButtonTitle=Component.UNDEFINED, filename=Component.UNDEFINED, trigger=Component.UNDEFINED, json_data=Component.UNDEFINED, hide_buttons=Component.UNDEFINED, **kwargs):
39-
self._prop_names = ['id', 'label', 'image_content', 'zoom', 'width', 'height', 'scale', 'tool', 'lineWidth', 'lineColor', 'goButtonTitle', 'filename', 'trigger', 'json_data', 'hide_buttons']
37+
def __init__(self, id=Component.UNDEFINED, image_content=Component.UNDEFINED, zoom=Component.UNDEFINED, width=Component.UNDEFINED, height=Component.UNDEFINED, scale=Component.UNDEFINED, tool=Component.UNDEFINED, lineWidth=Component.UNDEFINED, lineColor=Component.UNDEFINED, goButtonTitle=Component.UNDEFINED, filename=Component.UNDEFINED, trigger=Component.UNDEFINED, json_data=Component.UNDEFINED, hide_buttons=Component.UNDEFINED, **kwargs):
38+
self._prop_names = ['id', 'image_content', 'zoom', 'width', 'height', 'scale', 'tool', 'lineWidth', 'lineColor', 'goButtonTitle', 'filename', 'trigger', 'json_data', 'hide_buttons']
4039
self._type = 'DashCanvas'
4140
self._namespace = 'dash_canvas'
4241
self._valid_wildcard_attributes = []
4342
self.available_events = []
44-
self.available_properties = ['id', 'label', 'image_content', 'zoom', 'width', 'height', 'scale', 'tool', 'lineWidth', 'lineColor', 'goButtonTitle', 'filename', 'trigger', 'json_data', 'hide_buttons']
43+
self.available_properties = ['id', 'image_content', 'zoom', 'width', 'height', 'scale', 'tool', 'lineWidth', 'lineColor', 'goButtonTitle', 'filename', 'trigger', 'json_data', 'hide_buttons']
4544
self.available_wildcard_properties = []
4645

4746
_explicit_args = kwargs.pop('_explicit_args')

dash_canvas/dash_canvas.dev.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dash_canvas/dash_canvas.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dash_canvas/metadata.json

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@
6464
"params": [],
6565
"returns": null
6666
},
67+
{
68+
"name": "_rectangletool",
69+
"docblock": null,
70+
"modifiers": [],
71+
"params": [],
72+
"returns": null
73+
},
6774
{
6875
"name": "_selecttool",
6976
"docblock": null,
@@ -80,17 +87,6 @@
8087
"required": false,
8188
"description": "The ID used to identify this component in Dash callbacks"
8289
},
83-
"label": {
84-
"type": {
85-
"name": "string"
86-
},
87-
"required": false,
88-
"description": "A label that will be printed when this component is rendered.",
89-
"defaultValue": {
90-
"value": "''",
91-
"computed": false
92-
}
93-
},
9490
"image_content": {
9591
"type": {
9692
"name": "string"
@@ -151,7 +147,7 @@
151147
"name": "string"
152148
},
153149
"required": false,
154-
"description": "Selection of drawing tool, among [\"pencil\", \"pan\", \"circle\",\n\"select\", \"line\"].",
150+
"description": "Selection of drawing tool, among [\"pencil\", \"pan\", \"circle\",\n\"rectangle\", \"select\", \"line\"].",
155151
"defaultValue": {
156152
"value": "\"pencil\"",
157153
"computed": false
@@ -231,7 +227,7 @@
231227
}
232228
},
233229
"required": false,
234-
"description": "Names of buttons to hide. Names are \"zoom\", \"pan\", \"line\", \"pencil\",\n\"undo\", \"select\".",
230+
"description": "Names of buttons to hide. Names are \"zoom\", \"pan\", \"line\", \"pencil\",\n\"rectangle\", \"undo\", \"select\".",
235231
"defaultValue": {
236232
"value": "[]",
237233
"computed": false

dash_canvas/utils/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
superpixel_color_segmentation,
66
modify_segmentation)
77
from .registration import register_tiles, autocrop
8-
from .parse_json import parse_jsonstring, parse_jsonstring_line, parse_jsonfile
8+
from .parse_json import (parse_jsonstring, parse_jsonstring_line,
9+
parse_jsonstring_rectangle, parse_jsonfile)
910
from .io_utils import array_to_data_url, image_string_to_PILImage
1011
from .plot_utils import image_with_contour
1112
from .exposure import brightness_adjust, contrast_adjust
@@ -20,6 +21,7 @@
2021
'parse_jsonfile',
2122
'parse_jsonstring',
2223
'parse_jsonstring_line',
24+
'parse_jsonstring_rectangle',
2325
'random_forest_segmentation',
2426
'random_walker_segmentation',
2527
'register_tiles',

dash_canvas/utils/parse_json.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,35 @@ def parse_jsonstring_line(string):
113113
return (np.array(props)).astype(np.int)
114114

115115

116+
def parse_jsonstring_rectangle(string):
117+
"""
118+
Return geometry of rectangle objects.
119+
120+
Parameters
121+
----------
122+
123+
data : str
124+
JSON string of data
125+
126+
"""
127+
try:
128+
data = json.loads(string)
129+
except:
130+
return None
131+
scale = 1
132+
props = []
133+
for obj in data['objects']:
134+
if obj['type'] == 'image':
135+
scale = obj['scaleX']
136+
elif obj['type'] == 'rect':
137+
scale_factor = obj['scaleX'] / scale
138+
props.append([scale_factor * obj['width'],
139+
scale_factor * obj['height'],
140+
scale_factor * obj['left'],
141+
scale_factor * obj['top']])
142+
return (np.array(props)).astype(np.int)
143+
144+
116145
def parse_jsonfile(filename, shape=None):
117146
with open(filename, 'r') as fp:
118147
string = json.load(fp)

dash_canvas/utils/plot_utils.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
import PIL
33
import numpy as np
44
from skimage import color, img_as_ubyte
5+
from plotly import colors
56

6-
7-
def image_with_contour(img, labels, shape=None):
7+
def image_with_contour(img, labels, mode='lines', shape=None):
88
"""
99
Figure with contour plot of labels superimposed on background image.
1010
@@ -28,11 +28,19 @@ def image_with_contour(img, labels, shape=None):
2828
img = img_as_ubyte(color.gray2rgb(img))
2929
img = PIL.Image.fromarray(img)
3030
labels = labels.astype(np.float)
31+
custom_viridis = colors.PLOTLY_SCALES['Viridis']
32+
custom_viridis.insert(0, [0, '#FFFFFF'])
33+
custom_viridis[1][0] = 1.e-4
3134
# Contour plot of segmentation
35+
print('mode is', mode)
36+
opacity = 0.4 if mode is None else 1
3237
cont = go.Contour(z=labels[::-1],
33-
contours=dict(coloring='lines'),
34-
line=dict(width=3),
38+
contours=dict(start=0, end=labels.max() + 1, size=1,
39+
coloring=mode),
40+
line=dict(width=1),
3541
showscale=False,
42+
colorscale=custom_viridis,
43+
opacity=opacity,
3644
)
3745
# Layout
3846
layout= go.Layout(
@@ -59,8 +67,8 @@ def image_with_contour(img, labels, shape=None):
5967
showline=False,
6068
scaleanchor="x",
6169
ticks='',
62-
showticklabels=False,
63-
))
70+
showticklabels=False,),
71+
margin=dict(b=5, t=20))
6472
fig = go.Figure(data=[cont], layout=layout)
6573
return fig
6674

src/lib/components/DashCanvas.react.js

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import React, {Component} from 'react';
22
import PropTypes from 'prop-types';
33
import {SketchField, Tools} from 'react-sketch';
44
import {ZoomMinusIcon, ZoomPlusIcon, EditIcon, PanIcon,
5-
ArrowLeftIcon, PlotLineIcon, TagOutlineIcon} from 'plotly-icons';
5+
ArrowLeftIcon, PlotLineIcon, SquareIcon, TagOutlineIcon}
6+
from 'plotly-icons';
67

78

89
const styles = {
@@ -156,6 +157,12 @@ export default class DashCanvas extends Component {
156157
};
157158

158159

160+
_rectangletool(){
161+
this.props.setProps({tool: "rectangle"});
162+
};
163+
164+
165+
159166
_selecttool(){
160167
this.props.setProps({tool: "select"});
161168
};
@@ -170,13 +177,15 @@ export default class DashCanvas extends Component {
170177
toolsArray["line"] = Tools.Line;
171178
toolsArray["circle"] = Tools.Circle;
172179
toolsArray["select"] = Tools.Select;
180+
toolsArray["rectangle"] = Tools.Rectangle;
173181
const hide_buttons = this.props.hide_buttons;
174182
const show_line = !(hide_buttons.includes("line"));
175183
const show_pan = !(hide_buttons.includes("pan"));
176184
const show_zoom = !(hide_buttons.includes("zoom"));
177185
const show_pencil = !(hide_buttons.includes("pencil"));
178186
const show_undo = !(hide_buttons.includes("undo"));
179187
const show_select = !(hide_buttons.includes("select"));
188+
const show_rectangle = !(hide_buttons.includes("rectangle"));
180189
var width_defined = this.props.width > 0;
181190
var width = width_defined ? this.props.width : null;
182191
return (
@@ -218,6 +227,13 @@ export default class DashCanvas extends Component {
218227
<PlotLineIcon/>
219228
</button>
220229
}
230+
{show_rectangle &&
231+
<button style={styles.button}
232+
title="Rectangle tool"
233+
onClick={(e) => this._rectangletool()}>
234+
<SquareIcon/>
235+
</button>
236+
}
221237
{show_pan &&
222238
<button style={styles.button}
223239
title="Pan"
@@ -253,7 +269,7 @@ export default class DashCanvas extends Component {
253269

254270
}
255271

256-
DashCanvas.defaultProps = {filename:'', label:'',
272+
DashCanvas.defaultProps = {filename:'',
257273
json_data:'', image_content:'', trigger:0,
258274
width:500, height:500, scale:1, lineWidth:10,
259275
lineColor:'red', tool:"pencil", zoom:1,
@@ -265,11 +281,6 @@ DashCanvas.propTypes = {
265281
*/
266282
id: PropTypes.string,
267283

268-
/**
269-
* A label that will be printed when this component is rendered.
270-
*/
271-
label: PropTypes.string.isRequired,
272-
273284
/**
274285
* Image data string, formatted as png or jpg data string. Can be
275286
* generated by utils.io_utils.array_to_data_string.
@@ -299,7 +310,7 @@ DashCanvas.propTypes = {
299310

300311
/**
301312
* Selection of drawing tool, among ["pencil", "pan", "circle",
302-
* "select", "line"].
313+
* "rectangle", "select", "line"].
303314
*/
304315
tool: PropTypes.string,
305316

@@ -342,7 +353,7 @@ DashCanvas.propTypes = {
342353

343354
/**
344355
* Names of buttons to hide. Names are "zoom", "pan", "line", "pencil",
345-
* "undo", "select".
356+
* "rectangle", "undo", "select".
346357
*/
347358
hide_buttons: PropTypes.arrayOf(PropTypes.string),
348359

0 commit comments

Comments
 (0)