3

I have some code that prints out a list of coordinates (stored in points

f=open('139cm_2000_frame27.json') 
data=json.load(f) 
shapes=data["shapes"] 
for i in shapes: 
    print(i['label'])   # prints the label first
    for c in i['points']:
        d=np.array(c)
        print(d)       # an array containing coordinates in the form (x,y) 

d, the coordinates, are the points of n number of 10 sided polygons. So coordinates 0-9 are the coordinates of the first polygon, coordinates 10-19 are the second polygon...

There could be any number of polygons in the json file but they will each, always, have 10 coordinates.

I need to find a way of using those coordinates to 'draw'/'recreate' these polygons in a 128x128 array.

I have tried

from skimage.draw import polygon
   img = np.zeros((128, 128), dtype=np.uint8)
   r = np.array([#the x coordinates of d])
   c = np.array([#the y coordinates of d])
   rr, cc = polygon(r, c)
   img[rr, cc] = 1 #unsure about the 1
   img

but I do not know how to 1) get sets of 10 coordinates and 2) read the xs into r and the ys into c

Thank you so much!

An example of the input json:

{
  "version": "4.6.0",
  "flags": {},
  "shapes": [
    {
      "label": "blob",
      "points": [
        [
          61.42857142857143,
          20.285714285714285
        ],
        [
          59.10047478151446,
          18.879430437885873
        ],
        [
          58.04359793578868,
          16.37330203102605
        ],
        [
          58.661631924538575,
          13.724584936383643
        ],
        [
          60.71850877026435,
          11.94499905752918
        ],
        [
          63.42857142857143,
          11.714285714285715
        ],
        [
          65.75666807562841,
          13.120569562114127
        ],
        [
          66.81354492135418,
          15.62669796897395
        ],
        [
          66.19551093260428,
          18.275415063616357
        ],
        [
          64.13863408687851,
          20.05500094247082
        ]
      ],
      "group_id": null,
      "shape_type": "polygon",
      "flags": {}
    },
    {
      "label": "blob",
      "points": [
        [
          88.71428571428572,
          82.42857142857143
        ],
        [
          85.63470409582908,
          81.33512050565437
......
Jeru Luke
  • 20,118
  • 13
  • 80
  • 87

1 Answers1

2

From software engineering point of view, it is recomended to break your code into simple separate parts (i.e. make it modular).

First you will need a function for reading the input json and parsing it. I called it read_input in the code below. The format of the parsed data depends on the application.
I chose to return a list of pairs of ndarrays. Each element in the list represents one polygon. Each polygon contains 2 ndarrays: 1 for the x coordinates, and 1 for the y coordinates. I chose this representation because it is convenient for drawing the polygons (see below).

Second you will need a function for drawing the polygons (draw_polygons). It will contain an iteration over the polygon list, and call a lower level function for drawing 1 polygon (draw_one_polygon), again for modular reasons.

See the code below:

import json
import numpy as np
from skimage.draw import polygon

def read_input(filename: str):
    polygons = []
    with open(filename) as f:
        data = json.load(f)
        shapes = data["shapes"]
        for i in shapes:
            cur_poly_points = i["points"]
            tmp = list(zip(*cur_poly_points))
            # NOTE: The following line assumes that the point coordinates are given as (x,y). 
            #       Change the order of the indices if needed.
            polygons.append((np.array(tmp[1]), np.array(tmp[0])))
    return polygons

def draw_one_polygon(img, one_poly):
    r = one_poly[0];
    c = one_poly[1];
    rr, cc = polygon(r, c)
    img[rr,cc] = 1

def draw_polygons(img, polygons):
    for poly in polygons:
        draw_one_polygon(img, poly)

filename = '139cm_2000_frame27.json'
polygons = read_input(filename)
img = np.zeros((128, 128), dtype=np.uint8)
draw_polygons(img, polygons)
print(img)

Note: in your actual code you should verify that the coordinates do not exceed the image dimension.

Documentation and example: skimage.draw.polygon

If you are not familiar with this notation: *cur_poly_points, see here: How to unzip a list of tuples into individual lists?.

wohlstad
  • 12,661
  • 10
  • 26
  • 39
  • What if I were to cycle through files? so 139cm_2000_frame27.json then 139cm_2000_frame28.json then 139cm_2000_frame29.json iteratively – Joseph Darton May 09 '22 at 14:31
  • Then add a new function like `handle_files`. It will read the files one by one in a loop, and for each of them call `handle_one_file`, which will execute code like in the main script above (call `read_input`, etc...). – wohlstad May 09 '22 at 14:33
  • I meant that `handle_files` will handle the files one by one (in a loop), but not actually read them directly. The call to `read_input`, which actually read the file, should be in `handle_one_file` only. `handle_one_file` is the "replacement" of the code currently in the main script above, but with the filename as a parameter. – wohlstad May 09 '22 at 14:42
  • Thank you so much! I managed to get it working to loop through. It is erroring for polygons that are on the edge of the 128 by 128 grid. Do you know how I might fix this? @wohlstad. The error message is as such: IndexError: index 128 is out of bounds for axis 0 with size 128 – Joseph Darton May 09 '22 at 19:21
  • You can either increase the grid size, or clip the polygons. To clip the polygons you can to iterate on all the points before drawing each polygon, and update all coordinate (x or y) to be maximum 127. – wohlstad May 09 '22 at 19:35
  • And `f` shall be open for all time...suggest adding a `with` statement to open the file to sidestep any unforeseen complications – Charlie G Aug 29 '22 at 04:29
  • @CharlieG good point. I updated the code. – wohlstad Aug 29 '22 at 04:33