How to print data when a Selectable GraphicsItem is clicked? - python

I have a JSON file which contains coordinate list and some other information.
My JSON structure look like this;
"annotations": [
{
"type": "Box",
"color": "red",
"box_top": 406.0,
"box_left": 656.0,
"box_height": 73.0,
"box_width": 40.0
}
],
"annotations": [
{
"type": "Box",
"color": "green",
"box_top": 450.0,
"box_left": 700.0,
"box_height": 95.0,
"box_width": 47.0
}
]
By taking the box values (box_top,box_left,box_height,box_width) I have drawn Rectangle using QGraphicsView and QGraphicsScene. The code is given below;
def load_image(self,image_item):
self.scene = QGraphicsScene(self.centralWidget) # Created a QGraphicsScene
self.pic = QPixmap(str(image_item.text())) # Loaded Image
self.brush = QBrush()
self.pen = QPen(Qt.red)
self.pen.setWidth(2)
self.pixItem = QGraphicsPixmapItem(self.pic)
self.load_view = self.scene.addItem(self.pixItem) # Image Added to Scene
# Opening JSON and fetching data
# …
for rect in json_file['annotations']:
# Taken type and color and stored in variable
self.box_type = rect['type']
self.box_color = rect['color']
# Taken box_top,box_left,box_height,box_width values
self.rect_item = self.scene.addRect(rect['box_top'],rect['box_left'],rect['box_width'],rect['box_length'],self.pen,self.brush) # x,y,w,h
self.rect_item.setFlag(QGraphicsItem.ItemIsSelectable) #Item is Selectable
#self.rect_item.setFlag(QGraphicsItem.ItemIsMovable) # Item is Movable
self.fit_view = self.gView.setScene(self.scene)
self.gView.fitInView(self.pixItem,Qt.KeepAspectRatio)
self.gView.setRenderHint(QPainter.Antialiasing)
self.gView.show()
Now What I want is when I click one box (say which has color red) from the GraphicsScene, I want to print its corresponding type and color. In a simple way, I want to print all data related to that box. A sample images also attached for reference. Note : Image is the output of this program.
Thank you.

Use the code provided in the other answer I gave you (the second and last method are probably better) and get the data you need from the item. The "type" is the object class, the color is the pen() color.

Related

Multiple color bounding-boxes for different category objects

I am implementing "BBAVectors-Oriented-Object-Detection" https://github.com/yijingru/BBAVectors-Oriented-Object-Detection model. After testing the model, all the detected objects are shown with same colour bounding-boxes.
Following is the link to the test.py code https://github.com/yijingru/BBAVectors-Oriented-Object-Detection/blob/master/test.py. I figured out the following line of code changes the bounding boxes colour.
ori_image = cv2.drawContours(ori_image, [np.int0(box)], -1, (255,0,255),1,1)
However, it only takes a single colour at a time.
In addition, in another file "dataset_dota.py" of "BBAVectors-Oriented-Object-Detection" https://github.com/yijingru/BBAVectors-Oriented-Object-Detection/blob/master/datasets/dataset_dota.py I found the assigned colours to each objects category.
class DOTA(BaseDataset):
def __init__(self, data_dir, phase, input_h=None, input_w=None, down_ratio=None):
super(DOTA, self).__init__(data_dir, phase, input_h, input_w, down_ratio)
self.category = ['plane',
'baseball-diamond',
'bridge',
'ground-track-field',
'small-vehicle',
'large-vehicle',
'ship',
'tennis-court',
'basketball-court',
'storage-tank',
'soccer-ball-field',
'roundabout',
'harbor',
'swimming-pool',
'helicopter'
]
self.color_pans = [(204,78,210),
(0,192,255),
(0,131,0),
(240,176,0),
(254,100,38),
(0,0,255),
(182,117,46),
(185,60,129),
(204,153,255),
(80,208,146),
(0,0,204),
(17,90,197),
(0,255,255),
(102,255,102),
(255,255,0)]
self.num_classes = len(self.category)
self.cat_ids = {cat:i for i,cat in enumerate(self.category)}
self.img_ids = self.load_img_ids()
self.image_path = os.path.join(data_dir, 'images')
self.label_path = os.path.join(data_dir, 'labelTxt')
I am fresher in Python and Opencv. I will be thankful if someone can help me to link these files and show the detected objects in different colour bounding boxes or another method to show the different object categories in different colour bounding boxes. Thank you
In the current version the detected objects are shown as follows:
detected samples
Here is a snippet :
# Initialize the DOTA Class
dota_object = DOTA(data_dir, phase)
# Get color
object = 'plane'
id = dota_object.category.index(object)
color = dota_object.color_pans[id]
# Display the image
ori_image = cv2.drawContours(ori_image, [np.int0(box)], -1, color,1,1)
Replace the variables with the ones in your code (ori_image,dota_object,data_dir,phase)

Tkinter update canvas colors for a number of objects

could anyone help me with this: I have a list of dictionaries, where I stock the information for future Tkinter rectangles. Once the rectangles are created, i'm trying to make them change color depending on changing "x" value, but it only works for the last created object and not for the rest of them here is a code:
from tkinter import *
a = {
"y":2,
"len" : 4
}
b = {
"y":5,
"len" : 7
}
c = {
"y":6,
"len" : 8
}
d = {
"y":2,
"len" : 4
}
e = {
"y":4,
"len" : 12
}
f = {
"y":3,
"len" : 10
}
g = {
"y":7,
"len" : 10
}
groupe = [a,d, b, c, g, e, f]
xt1 = 800
xt2= 800
yt1=720
yt2=0
master = Tk()
root = Canvas(master, width=800, height=720)
root.pack()
#Moving RedLine
def deplacer():
global xt1, yt1, xt2, yt2
xt1-=5
xt2-=5
root.coords(laser_print, xt1, yt1, xt2,yt2)
root.after(50,deplacer)
return
#drawing blocks
graf_dist = 0
dist_betw=0
untouched = "blue"
being_touched = "red"
touched= "gray"
block_color=untouched
for ensemble in groupe:
graf_dist+=60
dist_betw+=10
xo=graf_dist+dist_betw
yo=int(ensemble['y']*50)
xl=xo+60
yl=int(ensemble['len']*50)
if xo<=xt1 and xl>xt1:
block_color=being_touched
elif xo<xt1 and xl<=xt1:
block_color=untouched
drawing_block = root.create_rectangle(xo, yo, xl, yl, fill=block_color, tag="blocks")
#draw horizontal redline
laser_print=root.create_line(xt1, yt1, xt2, yt2, fill="red")
#updating the color of the rectangles
def update_color():
x_block=xt1+1
untouched = "blue"
being_touched = "red"
touched= "gray"
block_color=untouched
if xo<=x_block and xl>x_block:
block_color=being_touched
elif xo<x_block and xl<=x_block:
block_color=untouched
root.itemconfig(drawing_block, fill=block_color)
root.after(50,update_color)
update_color()
deplacer()
mainloop()
Ok, first of all, you draw seven blocks, but they are all assigned to drawing_block. When you refer to drawing_block in update_color(), this is of course the last block.
First thing you need to do is having separate objects for each block, for example, by storing them in a list:
drawing_blocks = []
for ensemble in groups:
...
drawing_blocks.append(root.create_rectangle(xo, yo, xl, yl, fill=block_color, tag="blocks"))
Then you need to change the update_color() function to test whether the laser passes each of the separate blocks and then change the color of that specific block.

Markers appear on folium map when clicking on button

I am implementing a map in folium taking the information from a dataframe df. I contains the longitude, latitude, name and region information.
Using a GeoJson file I have taken here: https://github.com/martinjc/UK-GeoJSON, I am able to define the regions in UK, highlight them when hovering with the mouse pointer and show some information. I would like to create a popup for each region with a button. If the button is clicked all the entries in the df which are in that region appear like markers. Is it possible? The code I am using right now is below:
...operations on df and definition of the map m...
width = 10
heigth = 4
resolution = 75
def style_function(feature):
return {
'fillColor': '#ffaf00',
'color': 'grey',
'weight': 1.5,
'dashArray': '5, 5'
}
def highlight_function(feature):
return {
'fillColor': '#ffaf00',
'color': 'black',
'weight': 3,
'dashArray': '5, 5'
}
c = folium.GeoJson(geojsonFile,
name = 'Highlight',
overlay=True,
style_function = style_function,
highlight_function = highlight_function)
html = '{}<br> Info: {} <br> <buttononclick="window.location.reload()">Reload</button>'.format
frame = IFrame(html(name, info), width=(width*resolution)+20, height=(height*resolution)+20)
popup_text = folium.Popup(iframe, max_width=2650)
c.add_child(folium.Popup(popup_text))
c.add_to(m)
I can add the button in the popup; what I am trying to do is to define a function like:
def testFunction(df, region):
markerCluster = folium.plugins.MarkerCluster().add_to(map)
for index, row in df.iterrows():
if row['region'] == region:
folium.Marker([row['lat'], row['lon']], popup='some text').add_to(markerCluster)
that will be run when the button is clicked. The final effect I am looking for should be: open the map, click on the selected region, click the button, the markers on the region appear. But I haven't found any solution yet (I have tried with Flask without success).

Create a TextBox in Plotly Python

Can I somehow make a report in Plotly where the left side will be a text, which changes on a slider pick, and the right side is my chart? The way without using dash and too much javascript is preferred.
It should look like this:
For people still looking for an answer:
Some plotly.graph_objects basics first:
Plotly figure is made up of 3 parts: Data (trace to be plotted), Layout (on which data is to be plotted), Frame (Data + Layout to be used for looping)
To answer your question to include text on the left side you will have to write the text as a annotation (layout). To include two charts on right use subplots (data). To update them with slider pick you will have to update them with Frame. Each frame will have Data+Layout which corresponds to that slider position.
Generic code flow:
Let's assume:
Dataframe df has 4 columns X,Y1,Y2,Dates
Your slider represents different dates
#Import plotly graph object
import plotly.graph_objects as go
#Getting different dates
dates = df['Dates'].unique().tolist()
#Plotting first instance
data=[]
#Fig 1
data_dict1 = {{
"x": list(df["X"]),
"y": list(df["Y1"]),
"type":"scatter"},
"ncol":2,"nrow":1 #Subplot location
}
#Fig 2
data_dict2 = {
"x": list(df["X"]),
"y": list(df["Y2"]),
"type":"scatter",
"ncol":2,"nrow":2 #Subplot location
}
data = [data_dict1,data_dict2] #combining both plots
#Layout and slider
layout = {
"sliders" : [{
#Enter required slider layout
,"steps": [] #should include this line in slider
}],
"annotations":[ {
#Input required annotations
}]
} # layout ends
#making Frames
frames =[]
for date in dates:
frame = {"data": [], "name": str(date),"layout":{"annotations":[]}} # Saving each data frame
dataset = df[df[Dates]==date] #subsetting data for a date
# Create charts for this subset data
#Fig 1
data_dict1 = {{
"x": list(dataset["X"]),
"y": list(dataset["Y1"]),
"type":"scatter"},
"ncol":2,"nrow":1 #Subplot location
}
#Fig 2
data_dict2 = {
"x": list(dataset["X"]),
"y": list(dataset["Y2"]),
"type":"scatter",
"ncol":2,"nrow":2 #Subplot location
}
#Adding this data to frame
frame["data"] = [data_dict1,data_dict2]
# Creating lines to be displayed using annotations
annote1 = {
#Add data for line 1
}
annote2 = {
#Add data for line 2
}
annote3 = {
#Add data for line 3
}
annote4 = {
#Add data for line 4
}
#Adding all annotations lines to frame
frame["layout"]["annotations"] = [annote1,annote2,annote3,annote4]
#Combinig all frames
frames.append(frame)
#Updating slider step
slider_step = {
"label": date,
"method": "update"}
#Adding step to layout slider
layout["sliders"][0]["steps"].append(slider_step)
#Combine everything
fig = go.Figure(data =data,layout = layout, frames =frames)
#View in browser
plot(fig, auto_open=True)
Hope the logic flow is clear!

Blender: How to resize selected part of uv image in python?

I'm trying to select a part of my uv image. At blender, everything looks well, tipping "s" + "mouse resize".
BUT I need to do this at .py archive.
Using the script bpy.ops.transform.resize(...), however, another thing happens! Object associated to image resize, not the uv image :(
How I could do, at python, the resizing of uv image part?
My script untill now:
def create_score():
#adding empty object
bpy.ops.object.empty_add()
empty_obj = bpy.context.object
empty_obj.name = "score"
#adding score plane
bpy.ops.mesh.primitive_plane_add(radius=1, location=(0.5,6.7,0))
bpy.ops.transform.resize(value=(-8, -8, -8), constraint_axis=(True, False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)
#adding score object1
bpy.ops.mesh.primitive_plane_add(radius=0.5, location=(-6, 7.2, 0.1))
obtext1 = bpy.context.object
obtext1.name = "Score1"
obtext1.select = True
bpy.ops.object.editmode_toggle()
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D':
area.spaces[0].viewport_shade = 'TEXTURED'
area.type = 'IMAGE_EDITOR'
#adding image I want resize
bpy.ops.image.open(filepath="//../../textures/arialbd.tga", directory="/home/camila/Documents/cinemaxd/PlayerXD/textures/", files=[{"name":"arialbd.tga", "name":"arialbd.tga"}], relative_path=True)
bpy.data.screens['UV Editing'].areas[1].spaces[0].image = bpy.data.images['arialbd.tga']
bpy.ops.uv.unwrap()
#selecting all image
bpy.ops.uv.select_all(action='TOGGLE')
--
This
# store original area type
originalArea = bpy.context.area.type
# change current area to image editor
bpy.context.area.type = 'IMAGE_EDITOR'
#insert UV specific transforms here
#return to previouswindow for good measure ( and cleanliness )
bpy.context.area.type = originalArea
Do not helped too :/

Categories

Resources