Git Product home page Git Product logo

dash-canvas's Introduction

dash-canvas

dash-canvas is a package for image processing with Dash. It provides a Dash component for annotating images, as well as utility functions for using such annotations for various image processing tasks.

Try out the gallery of examples and read the docs to learn how to use dash-canvas.

Segmentation app

Get started with:

  1. Install dash_canvas: pip install dash-canvas (you will also need dash-core-components to run the apps).
  2. Run python app_seg.py (for interactive segmentation) or python correct_segmentation.py (for correcting a pre-existing segmentation)
  3. Visit http://localhost:8050 in your web browser

dash-canvas's People

Contributors

emmanuelle avatar jackparmer avatar marc-andre-rivet avatar nicolaskruchten avatar rpkyle avatar shammamah-zz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dash-canvas's Issues

PNG not saving properly

Here's the output of the so-called PNG

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta charset="UTF-8">
        <title>Dash</title>
        <link rel="icon" type="image/x-icon" href="/_favicon.ico">
        <link rel="stylesheet" href="https://codepen.io/chriddyp/pen/bWLwgP.css">
    </head>
    <body>
        
<div id="react-entry-point">
    <div class="_dash-loading">
        Loading...
    </div>
</div>

        <footer>
            <script id="_dash-config" type="application/json">{"url_base_pathname": null, "requests_pathname_prefix": "/"}</script>
            <script src="https://unpkg.com/[email protected]/dist/react.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/react-dom.min.js"></script>
<script src="https://unpkg.com/[email protected]/dash_html_components/dash_html_components.min.js"></script>
<script src="/_dash-component-suites/dash_canvas/dash_canvas.min.js?v=0.0.4&m=1547416398"></script>
<script src="https://cdn.plot.ly/plotly-1.42.2.min.js"></script>
<script src="https://unpkg.com/[email protected]/dash_core_components/dash_core_components.min.js"></script>
<script src="https://unpkg.com/[email protected]/dash_renderer/dash_renderer.min.js"></script>
        </footer>
    </body>
</html>

Reproduce result by clicking on Download Data below
screenshot 2019-02-15 14 50 16

Structure of dash-canvas, integration with the dash ecosystem

At the moment, dash-canvas is a crude wrapper around react-sketch. Its main feature is the ability to draw on an image and to retrieve the location of annotations for futher image processing operations. The javascript React component is minimal, exposing an image_content property for the background image and a json_data property for storing (among other things) the geometry of annotations.

Thanks to callbacks and python helper functions (exposed in image_processing_utils.py or plot_utils.py, pare_json.py etc.) it is possible to use annotations as

  • markers for segmentation algorithms (as in app.py)
  • starting from a labeled image (after a first segmentation), selection of objects to be merged, or objects to be separated in several objects (as in correct_segmentation.py)

These two parts (the minimal component and the set of python utils + apps) are in the same github repo for now. Should they be separated in two different python packages for more modularity? Could be dash-canvas and dash-canvas-utils. in the long term, the DashCanvas component could also be part of dash-core-components but I guess it's too early to decide.

I also wonder whether it would of interest to have dash-canvas as a trace of a dcc.Graph component? It could be interesting for example to re-use the mode bar (with the zoom in/ zoom out buttons, etc.).

Unable to customize height for Empty canvas

Problem description

Without loading an image, height of empty canvas is always 200px and cannot be customized.

Package version:

dash                 1.8.0  
dash-canvas          0.1.0  
dash-core-components 1.7.0  
dash-html-components 1.0.2  
dash-renderer        1.2.3  
dash-table           4.6.0  

Screen Shot 2020-02-11 at 3 51 43 PM

import dash
import dash_html_components as html
from dash_canvas import DashCanvas
from dash_canvas.utils import array_to_data_url, parse_jsonstring

app = dash.Dash(__name__)

canvas_width = 600 
canvas_height = 300 

app.layout = html.Div([
    html.H6('Draw on image and press Save to show annotations geometry'),
    html.Div([
    DashCanvas(id='canvas',
               lineWidth=2,
               width=500,
               height=300,
               hide_buttons=["zoom", "pan", "line", "pencil", "rectangle", "undo", "select"],
               lineColor='black',
               goButtonTitle='Sign'
               ),
    ], className="five columns"),
    html.Div([
    html.Img(id='my-image', width=300),
    ], className="five columns"),
    ])


@app.callback(Output('my-image', 'src'),
              [Input('canvas', 'json_data')])
def update_data(string):
    if string:
        mask = parse_jsonstring(string, (canvas_height, canvas_width))
    else:
        raise PreventUpdate
    return array_to_data_url((255 * mask).astype(np.uint8))


if __name__ == '__main__':
    app.run_server(debug=True)

Setting json_data does not render the rectangle in the canvas

Hello all!

I am creating an annotation using dash_canvas. I am storing my annotations (the json_data generated by the canvas) in a database, so that later someone could verify them using the dash it self.

So i need to be able to get the data from the database and render the rectangle on the, to this end i have created a callback function with @board.callback(Output('editable', 'json_data'), [Input('url', 'pathname')])

This somehow does not render the rectangle in the image. Anyone has any pointers where i could go with this?

Query about pull requests

Greetings, We ( group of 11 members ) have a software development lab in which we require to work as a team and contribute to a live open source project. We need to report instructor with our progress every week, so if our codes clear your tests will you accept our pull requests ?

Switching between images to annotate

From @mprostock:

My main question, which I can't seem to figure out: How do you envision
switching between images to annotate, what is the correct process for
that? In all use cases I know, this is one of the main processes:
annotate -> next image -> annotate ->next image etc. All of the portal
use-cases only demonstrate usage with a single image though.

By design, dash-canvas ALWAYS triggers the canvas.json-data callback if
anything is changed. So using the "go_button" (renamed to "next")
within the component practically makes it impossible to trigger image
changes. The following things I have tried:

  • change the "image_content" property after using the callback: Doesn't
    work, because it triggers a circular callback (changing image_content
    retriggers the callback...)

  • reinstantiate the entire component (putting the entire dash_canvas
    component into an output of type Output('canvas-div', 'children'). This
    should work from my perspective (though it is very inefficient), but it
    always only works for the first few images and then starts the above
    cycle of circular callbacks somehow on its own (so something again
    triggers the json callback apparently, reproducible but not consistent!)

  • try to make use of the new dash.callback_context object, which should
    have the actual cause of the callback within its 'triggered' list, but
    apparently the only property in dash-canvas is the entire json of
    changes, so the context is useless in this case.

What am I missing? Is there a way, short of NOT using the dash_canvas
internal buttons (which seems kind of beside the point and I also can't
find a way to hide the go-button, it seems mandatory?)

One additional observation: The json-data always includes the actual
image itself in base64 encoding. Considering that in all "normal"
usecases, the image will be provided by the backend anyways, this is
really inefficient and wasteful for the amount of data permanently send
between backend and client, it would be better to just include the
annotations. I imagine that the react component, which was designed to
sketch, does that by default, but for the annotation usecase that is
really unneccessary, maybe it could be made optional?

Switching between Dash application tabs clears the annotations on a canvas

I have created two Dash tabs for my application and each tab has a canvas with a background image. When I annotate one canvas by drawing, for example, rectangles, and then switch to the other tab and back to the initial one, the rectangles disappear but the background image remains in the canvas. How should I go about this issue?

Implement plotly backend or new Class wrapping plotly

Since plotly.js will soon have drawing capabilities we should implement either a new Canvas class with a high-level API for a plotly.js figure + annotations, or reuse the existing DashCanvas class with a plotly backend.

What can be done out of the box with plotly.js + dcc.Graph

  • define a figure with a given image either as layout image, or trace, and parameters for the newshape layout attribute as well as dragmode (which can be changed from the modebar)
  • define adcc.Storeto store the geometry of annotations and update it with a callback listening torelayoutData`
  • modify newshape parameters with other Dash components such as slider etc. However doing this will require to replot the whole figure. This problem can be mitigated by using clientside callbacks.

What we can do on top on dcc.Graph:

  • add a dcc.Store to save the geometry of annotations, which will be updated on relayout (this could also be part of a Python "combination class" with an internal callback but probably better to implement everything in JS). This store should we read and write, ie it should be possible to load annotations programmatically. The structure of this object would be a list of objects, ie using the same syntax as plotly.
  • have another dcc.Store where to store newshape parameters, which could trigger relayout events for the figure without replotting the whole figure. Same syntax as plotly.
  • have an image parameter which can be an array in the case where the figure attribute is not given, then it is built automatically

Other thoughts:

  • hiding buttons from the modebar can be done in the config attribute
  • future directions: add slider to slice through 3D volume, interaction with datashader.

Can dash_canvas draw an arrow?

When figuring out the special zone, like lesions on a X-ray picture, an arrow is often used, however, currently I find arrow is not available. It will be greatly appreciated if arrow is allowed to draw. Thank you.

Callback error when annotation surpasses the border of canvas

  • When pencil draws from middle toward upper border, portion which surpasses the border appears on the other side.
  • When pencil passes beyond lower or right boundary of canvas body, callback error is raised. I believe this is related with how parse_json handles binary masks and relative indices of path, I tried to edit
    mask_tmp[inds[0], inds[1]] = 1
    from where error happens but I'm not able to lock it down.

app

Sample code:

import dash
import dash_html_components as html
from dash_canvas import DashCanvas
from dash_canvas.utils import array_to_data_url, parse_jsonstring
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
import numpy as np

app = dash.Dash(__name__)

canvas_width = 500
canvas_height = 200

app.layout = html.Div([
    html.H6('Draw on image and press Save to show annotations geometry'),
    html.Div([
    DashCanvas(id='canvas',
               lineWidth=2,
               width=500,
               height=200,
               hide_buttons=["zoom", "pan", "line", "pencil", "rectangle", "undo", "select"],
               lineColor='black',
               goButtonTitle='Sign'
               ),
    ], className="five columns"),
    html.Div([
    html.Img(id='my-image', width=300),
    ], className="five columns"),
    ])


@app.callback(Output('my-image', 'src'),
              [Input('canvas', 'json_data')])
def update_data(string):
    if string:
        mask = parse_jsonstring(string, (canvas_height, canvas_width))
    else:
        raise PreventUpdate
    return array_to_data_url((255 * mask).astype(np.uint8))


if __name__ == '__main__':
    app.run_server(debug=True)

setting a value for 'tool' parameter does not set that tool by default

dash_canvas.DashCanvas(
                    id='canvas',
                    width=800,
                    height=445,
                    tool='rectangle',
                    lineWidth=2,
                    filename=filename,
                    hide_buttons=['pencil', 'line', 'pan', 'select', 'zoom'],
                    goButtonTitle='Get coordinates'
                ),

Setting the tool parameter equal to 'rectangle' is supposed to set the tool to rectangle by default when the app is opened, but instead, the 'pan' tool is selected.

Dash-canvas (R) and filter_null

Hello all,

I was trying to translate an applet from Python to R, but encountered a problem. The snippet I used was from the tutorial at: https://dashr.plotly.com/dash-canvas

And it was this:

app <- Dash$new()

app$layout(
  htmlDiv(
    list(
      htmlH5("Press down the left mouse button and draw inside the canvas"),
      dashCanvas(id = 'canvas_101')
      
      )
    )
  )


app$run_server()

Which returns:

Error in filter_null(component$props) : 
  could not find function "filter_null"

Looking at the changelog https://github.com/plotly/dashR/blob/master/CHANGELOG.md, this function has been excised

I found the function to be:

filter_null <- function(x) {
  if (length(x) == 0 || !is.list(x)) return(x)
  x[!vapply(x, is.null, logical(1))]
}

And everything works normally afterwards.

Width property of the Canvas as % instead of px

This is a very promising tool for integrating with Dash. I would like to modify the width property of the canvas to fill the parent Div. The width property of the canvas however, only provides for an integer input. Can we specify width as %?

width="100%"

Not an expert in the 'js' side of things but I am wondering if this could be done directly in the current python api?

MAINT: Increase number of tests

What could be tested:

  • launch app with DashCanvas: ok
  • check props after initialization (should be ok, sometimes tool is weird)
    If we can mimick clicking:
  • zoom and check zoom factor (somehow)
  • click on tool and check tool prop
    -test upload of image
    Can we mimick annotation geometry??

Zoomed image moves away upon Save

Dear @emmanuelle,

Thanks for the great prototype!

I'm trying out https://dash-canvas-separate.herokuapp.com/ and I want to separate the two elements near the bottom right corner. I'm actually not sure whether they're already separated or not.

I'm taking the following sequence of actions:

  • Zoom;
  • Pan;
  • Pencil:
    draw_separator
  • Save... which results in the following view:
    after_save

It would be more natural for me to keep the same view, where the red line I drew disappears and the new estimated border appears.

Best,
Marianne

Adding background image with set opacity / Having two overlapping background images

I'm trying to use Dash canvas to do some radiographic film analysis. I first create a Dash canvas with the film image as a background. I then typically draw a line with the line tool and extract the profile from the background image along that line.

I would like to overlap two similar images with, for example, half opacity for each, as one single background and when I draw the line and extract the profile, I would get two profiles. This is useful for comparing profiles from two films while ensuring positional matching (by overlapping them and adjusting the position of one relative to the other).

Could this be an implemented feature? Should I try combining the two images outside of the canvas and then using the combined data as background? This wouldn't allow me to move them relative to each other inside the canvas, unfortunately.

Interactive image processing?

Hi,

I (quickly) went through the docs but besides this mention:

image

I could not really see a way to actually update the background image interactively. Say for example I want to dynamically change its saturation according to a slider value, it does not seem possible?

Cheers,

Thomas

change canvas width to allow for mobile responsiveness

Currently the width of the canvas is determined by setting the width parameter in the canvas object eg:

dash_canvas.DashCanvas(
          width=800
       )

It would be nice to allow this to be changed via styling of the parent div. I think if the width is not specified it should match that of the parent div, and change as the parent div does. If the width is specified, then it should also change by the same ratio as the parent if the screen is squeezed/expanded.

Quick CSS clean up Dash Canvas toolbar

I love the utility of the Dash Canvas toolbar, but the icons look a bit oversized and uncentered to me:

image

I know plotly.js will likely fully replace dash-canvas in a few months (plotly/plotly.js#4374), so not worth spending too much time on this, but I think it could be improved with a few CSS overrides.

I adjusted the CSS in the console and came up with this, which I think is an improvement and matches the plotly.js modebar better:

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.