1

I am loading python dictionary with multiple polygons. Polygon points are obtained from mouse click on different position of image. The script displays image to user for selection of different points of polygons. The user will click on different position by mouse right click. When the user clicks left mouse button, a polygon is created and added to dictionary Dict_Polygons with a label. The list list_of_points is cleared as new points for new polygon will be added to this list. The issue is that Dict_Polygon is not loaded with items. Here is the complete code.

import math
import pickle
from Tkinter import *
import Image, ImageTk, ImageDraw
import numpy as np

coord=[]  # for saving coord of each click position
Dict_Polygon={}   # Dictionary for saving polygon
list_of_points=[]
flag=True
label=0

def draw_lines(event):
    mouse_xy = (event.x, event.y)
    func_Draw_lines(mouse_xy)

def func_Draw_lines(mouse_xy):
    func_Draw_Dot(mouse_xy)
    center_x, center_y = mouse_xy
    if canvas.old_coords:
            x1, y1 = canvas.old_coords
            canvas.create_line(center_x, center_y, x1, y1)

    # add clicked positions to list
    if flag==True:
        list_of_points.append(mouse_xy)
        canvas.old_coords = center_x, center_y

def func_Draw_Dot(coord):
     x_coord, y_coord=coord
  #draw dot over position which is clicked
     x1, y1 = (x_coord - 1), (y_coord - 1)
     x2, y2 = (x_coord + 1), (y_coord + 1)
     canvas.create_oval(x1, y1, x2, y2, fill='green', outline='green', width=5)

# This function will be called when the user wants to specify class, so a polygon will be drawn. 
def func_draw_polygon(event):

    numberofPoint=len(list_of_points)
    if numberofPoint>2:
        print ("test")
        canvas.create_polygon(list_of_points, fill='', outline='green', width=2)
        Dict_Polygon[label]=list_of_points
        list_of_points[:]=[]
       # del list_of_points[:] # clear list elements to add new polygon points
        canvas.old_coords=None
        global label
        label=label+1

        print (Dict_Polygon.items())
    else:
        print('Select minemum 3 points')

# Main function
if __name__ == '__main__':

    root = Tk()
    # Input image
    img = Image.open("e.png")         

# Draw canvas for iput image to pop up image for clicks
    filename = ImageTk.PhotoImage(img)
    canvas = Canvas(root,height=img.size[0],width=img.size[0])
    canvas.image = filename
    canvas.create_image(0,0,anchor='nw',image=filename)
    canvas.pack()
    canvas.old_coords = None
# bind function to canvas to generate event
    canvas.bind("<Button 3>", draw_lines)
    canvas.bind("<Button 1>", func_draw_polygon)

    root.mainloop()
john
  • 101
  • 1
  • 14
  • 1
    First you need to fix your imports and indention. You are importing tkinter twice and trying to import Image and ImageTK twice without even referencing PIL. – Mike - SMT Jun 27 '18 at 13:02
  • 2
    You add `list_of_points` to the dictionary, and then delete all of the items in that list. Why do you expect the data to be there after you delete it? – Bryan Oakley Jun 27 '18 at 13:09
  • Mike-SMT I updated the code. Thank You. – john Jun 27 '18 at 13:12
  • Bryan Oakley I want to add the list_of_points to dictionary and want to add new points to list_of_points, so I cleared it. How to deal with this. My output should be a dictionary having multiple list_of_points. – john Jun 27 '18 at 13:13
  • 1
    Your imports are still wrong. From the code you have presented the only imports you need are `import Tkinter as tk` and `from PIL import Image, ImageTk`. – Mike - SMT Jun 27 '18 at 13:13
  • I did from Tkinter import * for accessing canvas. Kindly have a look at the code. It seems OK for me as per your suggestions. – john Jun 27 '18 at 13:18
  • John. You do `import Tkinter as tk` and then you do `tk.Canvas()` or any other method like `tk.Frame()` or `tk.Label()`. – Mike - SMT Jun 27 '18 at 13:19
  • if/else is OK, I tested it. – john Jun 27 '18 at 13:21
  • I did it by print statments. You can also test the code. – john Jun 27 '18 at 13:23
  • I have been testing the code. I have also been correcting portions of the code. – Mike - SMT Jun 27 '18 at 13:23
  • I think I have worked out some of the bugs. Tell me is the polygons being created meant to always link to the last polygon? – Mike - SMT Jun 27 '18 at 13:26
  • What Bryan Oakley is pointing at is that you save a reference to the list `list_of_points` in your dictionary instead of the content of the list at that time. Therefore, what's in the dictionary changes when you change the contents of `list_of_points`. The easiest fix is to use `Dict_Polygon[label]=list_of_points.copy()` to store a copy of the list at that time instead of a reference to the list. – fhdrsdg Jun 27 '18 at 13:28
  • Oh wait, `list.copy()` doesn't seem to exist in Python 2.x. See [this answer](https://stackoverflow.com/a/2612815/3714930) for other options to achieve the same result. – fhdrsdg Jun 27 '18 at 13:35
  • yes I got the error " Dict_Polygon[label]=list_of_points.copy() AttributeError: 'list' object has no attribute 'copy'" – john Jun 27 '18 at 13:37
  • import copy new_list = copy.copy(old_list) worked for me. – john Jun 27 '18 at 13:41

1 Answers1

0

The issue with the code is "I added list_of_points to the dictionary, and then delete all of the items in that list. So empty dictionary is the output. To deal with copying list to dictionary, I follow this solution

import copy
new_list = copy.copy(old_list)
john
  • 101
  • 1
  • 14
  • So I am wondering still what you were trying to accomplish? Was the point to save all the polygons and then load them at a later date? – Mike - SMT Jun 27 '18 at 14:01
  • Yes, This is what I want. Save polygons to dictionary. Now, doing deletion of specific polygon from this dictionary. – john Jun 27 '18 at 14:13
  • Ok that makes more sense now. I was under the impression you were having issues with the polygon creation itself. My misunderstanding. I still believe you should review how you write your imports. As most of your imports have no point in the code you presented. – Mike - SMT Jun 27 '18 at 14:14
  • Thank you, yes, I will take care of imports. – john Jun 27 '18 at 14:35