Closed hello-fri-end closed 2 years ago
Hey @hello-fri-end !
I'm not near my personal computer so can't test :/ but this is odd. I've actually never tried passing the image dimensions as height and width, but you should not have to because I resize the image to fill the entire canvas.
Have a nice day, Fanilo
Hey @hello-fri-end !
I'm not near my personal computer so can't test :/ but this is odd. I've actually never tried passing the image dimensions as height and width, but you should not have to because I resize the image to fill the entire canvas.
- What happens if you remove the height/width arguments?
Here's the entire code:
canvas_result = st_canvas(
stroke_color='#fff',
stroke_width=stroke_width,
background_color='#000',
background_image=image.copy(),
height = image.size[1],
width = image.size[0],
update_streamlit=realtime_update,
drawing_mode = drawing_mode,
key = "canvas",
)
if st.button("INPAINT"):
image = np.array(image, dtype = 'uint8')
mask = np.array(canvas_result.image_data, dtype = 'uint8')
mask = cv2.cvtColor(mask[:, :, :3], cv2.COLOR_RGB2GRAY)
st.image(mask)
res1 = cv2.inpaint(src = image, inpaintMask = mask, inpaintRadius = inpaintRadius, flags = cv2.INPAINT_TELEA)
res2 = cv2.inpaint(src = image, inpaintMask = mask, inpaintRadius = inpaintRadius, flags = cv2.INPAINT_NS)`
When I remove the height/width arguments, the function cv2.inpaint
complains that the mask
& image
are not of the same size and the canvas size looks smaller.
- Did I maybe wrongly mixed width and height too, what happens if you invert the 2 dimensions?
No, on inverting the image looks weirdly stretched.
Moreover, when height/width parameters are removed & I print the shape of mask, it comes out as (400,600)
Moreover, when height/width parameters are removed & I print the shape of mask, it comes out as (400,600)
Yeah those are the dimensions of the canvas by default, and the mask you get out from the canvas are sized by canvas size so you'll need to reshape.
As the title says st_canvas displays a cropped background image even though the height and width of the canvas are set acc. to the image dimensions.
Ah I get it now :/ the canvas is cropped by the size of the Streamlit column. The canvas is not responsive so if the canvas width is larger than the container, the canvas will be cropped by the container. If you put your app in wide mode and your picture is not 2160px wide, you won't have the crop problem.
My only good suggestion is to actually downsize the image for now :/
Ah I get it now :/ the canvas is cropped by the size of the Streamlit column
That's strange since st.image
displays the full image :/
My only good suggestion is to actually downsize the image for now :/
Yup! That seems like my only option right now. Thanks :)
st.image
resizes to the size of the column, but not my HTML canvas component because I've hardcoded the dimensions and it's not responsive for now, the joy of implementing canvas by hand :/ ...
Hope you get away with downsizing a bit!
Closing in favor of #39
Hi everyone,
I found a stupid way to achieve responsive canvas size. I use streamlit_javascript component to read window.innerWidth and pass it to canvas. But it still has some problems, just for reference. Here's my code snippet.
import streamlit as st
from streamlit_javascript import st_javascript
import pandas as pd
from PIL import Image
from streamlit_drawable_canvas import st_canvas
st.set_page_config(layout='wide')
# Specify canvas parameters in application
drawing_mode = st.sidebar.selectbox(
"Drawing tool:", ("polygon", "freedraw", "line", "rect", "circle", "transform", "point")
)
stroke_width = st.sidebar.slider("Stroke width: ", 1, 25, 3)
if drawing_mode == 'point':
point_display_radius = st.sidebar.slider("Point display radius: ", 1, 25, 3)
stroke_color = st.sidebar.color_picker("Stroke color hex: ")
bg_color = st.sidebar.color_picker("Background color hex: ", "#eee")
bg_image = st.sidebar.file_uploader("Background image:", type=["png", "jpg"])
realtime_update = st.sidebar.checkbox("Update in realtime", True)
if bg_image:
img = Image.open(bg_image)
w, h = img.size
else:
w, h = 100, 100
st.subheader("Javascript API call")
option = st.radio('', ['Default Width', 'Update Canvas Width'])
if option == 'Default Width':
inner_width = 100
elif option == 'Update Canvas Width':
inner_width = st_javascript("""await fetch("http://localhost:8501/").then(function(response) {
return window.innerWidth;
}) """)
st.markdown(f"Inner width was: {inner_width}")
canvas_width = inner_width
canvas_height = h * (canvas_width / w)
# Create a canvas component
canvas_result = st_canvas(
fill_color="rgba(255, 165, 0, 0.3)", # Fixed fill color with some opacity
stroke_width=stroke_width,
stroke_color=stroke_color,
background_color=bg_color,
background_image=Image.open(bg_image) if bg_image else None,
update_streamlit=realtime_update,
height=canvas_height,
width=canvas_width,
drawing_mode=drawing_mode,
point_display_radius=point_display_radius if drawing_mode == 'point' else 0,
)
# Do something interesting with the image data and paths
if canvas_result.image_data is not None:
st.image(canvas_result.image_data, width=inner_width)
if canvas_result.json_data is not None:
objects = pd.json_normalize(canvas_result.json_data["objects"]) # need to convert obj to str because PyArrow
for col in objects.select_dtypes(include=['object']).columns:
objects[col] = objects[col].astype("str")
st.dataframe(objects)
Oh that's super nice, thanks for sharing :)
How to make a high-resolution background scroll horizontally across a canvas. Because I want to get the actual coordinates of the rectangle on the original image
Hi! Thanks for the super cool package. As the title says
st_canvas
displays a cropped background image even though theheight
andwidth
of the canvas are set acc. to the image dimensions.Here's my code:
Am I doing something wrong?