I am new to plotly. I want to draw some bounding boxes interactively on an image and get their coordinates to a list (top-left, bottom-right corners). This should be done in google colab , so CV2 did not work. This link gives an example of interactively select (drag and draw) an area of an image while this link can be used to extract coordinates on a plot using plotly. I still could not figure out how to combine these 2 examples together and return the bounding box coordinates. I have added these code snippets below.
To draw the bounding boxes on image:-
!wget https://gamingnewsanalyst.com/wp-content/uploads/2020/03/Crysis-3-Free-Download-800x450.jpg
import plotly.express as px
import cv2
img = cv2.cvtColor(cv2.imread('/content/Crysis-3-Free-Download-800x450.jpg'),cv2.COLOR_BGR2RGB)
fig = px.imshow(img)
fig.update_layout(
dragmode='drawrect',
newshape=dict(line_color='cyan'))
fig.show()
To get the coordinates of mouse click point:-
import plotly.graph_objects as go
from google.colab import output
output.enable_custom_widget_manager()
import numpy as np
np.random.seed(1)
x = np.random.rand(100)
y = np.random.rand(100)
f = go.FigureWidget([go.Scatter(x=x, y=y, mode='markers')])
scatter = f.data[0]
colors = ['#a3a7e4'] * 100
scatter.marker.color = colors
scatter.marker.size = [10] * 100
f.layout.hovermode = 'closest'
# create our callback function
def update_point(trace, points, selector):
c = list(scatter.marker.color)
s = list(scatter.marker.size)
for i in points.point_inds:
c[i] = '#bae2be'
s[i] = 20
print(points)
with f.batch_update():
scatter.marker.color = c
scatter.marker.size = s
scatter.on_click(update_point)
f
When I click on a point this code will given below output
Points(point_inds=[6],
xs=[0.1862602113776709],
ys=[0.015821242846556283],
trace_name='trace 0',
trace_index=0)
My expected output should be the drawn bounding boxes' coordinates.
[[100,100],[500,400]] ## [[x0,y0],[x1,y1]]
[[200,130],[400,300]]
Any help is much appreciated. Thanks in advance.
After some search found this example which tells how to do this. I modified it and partially inserted inside a class as follows to satisfy my full requirement.
import plotly.express as px
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from jupyter_dash import JupyterDash
import cv2
import numpy as np
coords = []
depths = []
app = JupyterDash(__name__)
@app.callback(
Output("bbox-data", "children"),
Input("middle-sai", "relayoutData"),
prevent_initial_call=True,
)
def on_new_annotation(relayout_data):
global coords,depths
if "shapes" in relayout_data:
x0 = int(relayout_data["shapes"][-1]['x0'])
y0 = int(relayout_data["shapes"][-1]['y0'])
x1 = int(relayout_data["shapes"][-1]['x1'])
y1 = int(relayout_data["shapes"][-1]['y1'])
coords_dict = {'x0':x0,'y0':y0,'x1':x1,'y1':y1}
coords.append([[y0,x0],[y1,x1]])
depths.append(None)
return html.Div([html.Div(str(coords_dict)),html.Div(dcc.RadioItems(['shallow', 'deep'],inline=True,id = "depth-sel"))],style={"color": "white"})
else:
return dash.no_update
@app.callback(
Output('all-bboxes','children'),
Input("depth-sel","value"),
)
def display_final_list(depth_val):
global coords,depths
if (depth_val == 'deep'):
depths[-1] = 1
elif (depth_val == 'shallow'):
depths[-1] = 0
flist = ''
for i in range(len(coords)):
flist += str(coords[i])
if (depths[i]==1):
flist += " deep "
elif (depths[i]== 0):
flist += " shallow "
else:
flist += " " + str(depths[i]) + " "
return flist
class test_show():
def __init__(self):
global coords,depths
coords = []
depths = []
self.img = cv2.cvtColor(cv2.imread('/content/Crysis-3-Free-Download-800x450.jpg'),cv2.COLOR_BGR2RGB)
fig = px.imshow(self.img)
fig.update_layout(
autosize=False,
# width=500,
height=400,
dragmode='drawrect',
newshape=dict(line_color='cyan'))
app.layout = html.Div(
[
dcc.Graph(id="middle-sai", figure=fig),
html.Pre(id="bbox-data",style={"color": "white"}),
html.Div(id='all-bboxes',style={"color": "white"}),
]
)
def show_image(self):
app.run_server(debug=False,mode='inline')
t = test_show()
t.show_image()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.