remi icon indicating copy to clipboard operation
remi copied to clipboard

Canvas Drawing

Open Bootstrap360 opened this issue 4 years ago • 7 comments

I wish to transmit an image from the server to the front end and then draw a circle on the image where a user clicks on it.

My current solution is using a callback and to redraw the image on the server and re-transmit the image. This is very slow. Is there a better solution?

Bootstrap360 avatar Jul 20 '20 21:07 Bootstrap360

There are different possible solutions. Two possible solutions are:

  1. Use Svg widgets to show the image and add other svg objects to draw geometrics;
  2. Draw on the image with opencv and trigger an image refresh;

The best solution depends on the kind of project. What you want to do exactly?

dddomodossola avatar Jul 21 '20 07:07 dddomodossola

Thank you for responding so quickly.

I want to display many images in a grid from a remote server to a consumer and draw circles on the all the images from where the user clicked. Here is a demo of what I have so far. I have been able to speed it up by using high JPEG compression but I suspect it will slow down much farther when I start to display many more images. Sample.zip

I have already implemented back-end rendering using OpenCV and refresh but I would prefer to do it on the front end for lower latency. I might be rendering tens of images.

Could you provide more details or point to an example of how I could do your first suggestion? I was not able to find an example of how to show the image inside a svg widget and then draw on top.

Thank you.

Bootstrap360 avatar Jul 23 '20 19:07 Bootstrap360

Here is a really simple example made with the editor:

# -*- coding: utf-8 -*-

from remi.gui import *
from remi import gui
from remi import start, App


class untitled(App):
    def __init__(self, *args, **kwargs):
        #DON'T MAKE CHANGES HERE, THIS METHOD GETS OVERWRITTEN WHEN SAVING IN THE EDITOR
        if not 'editing_mode' in kwargs.keys():
            super(untitled, self).__init__(*args, static_file_path={'my_res':'./res/'})

    def idle(self):
        #idle function called every update cycle
        pass
    
    def main(self):
        return untitled.construct_ui(self)
        
    @staticmethod
    def construct_ui(self):
        #DON'T MAKE CHANGES HERE, THIS METHOD GETS OVERWRITTEN WHEN SAVING IN THE EDITOR
        vbox0 = VBox()
        vbox0.attr_class = "VBox"
        vbox0.attr_editor_newclass = False
        vbox0.css_align_items = "center"
        vbox0.css_display = "flex"
        vbox0.css_flex_direction = "column"
        vbox0.css_height = "540.0px"
        vbox0.css_justify_content = "space-around"
        vbox0.css_left = "20px"
        vbox0.css_position = "absolute"
        vbox0.css_top = "20px"
        vbox0.css_width = "645.0px"
        vbox0.variable_name = "vbox0"
        svg0 = Svg()
        svg0.attr_class = "Svg"
        svg0.attr_editor_newclass = False
        svg0.css_height = "450px"
        svg0.css_order = "124983688"
        svg0.css_position = "static"
        svg0.css_top = "20px"
        svg0.css_width = "450px"
        svg0.variable_name = "svg0"
        svgimage0 = gui.SvgImage('https://interactive-examples.mdn.mozilla.net/media/examples/grapefruit-slice-332-332.jpg')
        svgimage0.onmousedown.do(self.on_mousedown_svgimage)
        svgimage0.attr_class = "SvgImage"
        svgimage0.attr_editor_newclass = True
        svgimage0.attr_height = 225.0
        svgimage0.attr_width = 420.0
        svgimage0.attr_x = 15.0
        svgimage0.attr_y = 15.0
        
        svgimage0.variable_name = "svgimage0"
        svg0.append(svgimage0,'svgimage0')
        vbox0.append(svg0,'svg0')
        self.svg0 = svg0

        self.vbox0 = vbox0
        return self.vbox0

    def on_mousedown_svgimage(self, emitter, x, y):
        circle = gui.SvgCircle(x, y, 20)
        circle.set_fill('transparent')
        circle.set_stroke(1, 'black')
        self.svg0.append( circle )
    


#Configuration
configuration = {'config_multiple_instance': True, 'config_address': '0.0.0.0', 'config_start_browser': True, 'config_enable_file_cache': True, 'config_project_name': 'untitled', 'config_resourcepath': './res/', 'config_port': 8081}

if __name__ == "__main__":
    # start(MyApp,address='127.0.0.1', port=8081, multiple_instance=False,enable_file_cache=True, update_interval=0.1, start_browser=True)
    start(untitled, address=configuration['config_address'], port=configuration['config_port'], 
                        multiple_instance=configuration['config_multiple_instance'], 
                        enable_file_cache=configuration['config_enable_file_cache'],
                        start_browser=configuration['config_start_browser'])

dddomodossola avatar Jul 23 '20 21:07 dddomodossola

Thank you @dddomodossola,

I have set the SvgImage object css_width and css_height to be 100% rather than in pixels. How can I get the current widget's height in pixels if the css is defined in percentage?

The function width_in_pixels() and height_in_pixels() are the parts that I am missing.

def on_mousedown(self, emitter, x, y):

    x_percentage = x / emitter.width_in_pixels()
    y_percentage = y / emitter.height_in_pixels()

Bootstrap360 avatar Oct 26 '20 03:10 Bootstrap360

There are different possible solutions. Two possible solutions are:

  1. Use Svg widgets to show the image and add other svg objects to draw geometrics;
  2. Draw on the image with opencv and trigger an image refresh;

The best solution depends on the kind of project. What you want to do exactly?

Hi,i wish to dispaly my camera which is being processed by opencv but i don‘t know how to do it with remi.Could you provide more details or point to an example of how I could do your first suggestion?Thank you.

vaope avatar Mar 07 '22 10:03 vaope

You can use the Editor. It contains opencv video widget. Take a look at this https://www.youtube.com/watch?v=WqwWrETtLfU In this example it is used an opencv image widget. You should instead use the Video.

dddomodossola avatar Mar 07 '22 11:03 dddomodossola

You can use the Editor. It contains opencv video widget.

Thank you,it help me a lot.

vaope avatar Mar 07 '22 13:03 vaope