remi
remi copied to clipboard
Canvas Drawing
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?
There are different possible solutions. Two possible solutions are:
- Use Svg widgets to show the image and add other svg objects to draw geometrics;
- 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?
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.
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'])
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()
There are different possible solutions. Two possible solutions are:
- Use Svg widgets to show the image and add other svg objects to draw geometrics;
- 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.
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.
You can use the Editor. It contains opencv video widget.
Thank you,it help me a lot.