Skip to content

Commit

Permalink
meet CityScope API, post only to grid field
Browse files Browse the repository at this point in the history
  • Loading branch information
RELNO committed Jun 27, 2020
1 parent 9cdf080 commit de797b3
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 370 deletions.
34 changes: 30 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ $ git clone https://github.com/CityScope/CS_CityScoPy.git
$ cd CS_CityScoPy
```

- install packages. To produce a list of needed packages, use `pipreqs`, follow instructions https://github.com/bndr/pipreqs. Or, simply run the app and install packages as they appear in errors.
- install packages. To produce a list of needed packages, use `pipreqs`, follow instructions https://github.com/bndr/pipreqs. Or, simply run the app and install packages as they appear as missing.
- tweak `__settings__.json` to fit your cityIO table setup. Read [cityIO documentation](https://github.com/cityscope/cs_cityio_backend/wiki) for proper data structure
- setup a path to your settings file
- in `run.py` setup a path to your settings file

```
cityscopy_settings_path = "__path__/__settings__.json"
CITYSCOPY_SETTINGS_PATH = "__path__/__settings__.json"
```

- initiate the `Cityscopy` class (see `run.py` example)

```
cityscopy = Cityscopy(cityscopy_settings_path)
cityscopy = Cityscopy(CITYSCOPY_SETTINGS_PATH)
```

- use one or more of the main methods. 'Blocking' means the method will run forever (while true loop). Advanced users can parallel blocking methods using multithreading.
Expand Down Expand Up @@ -72,10 +72,36 @@ Scanner will detect colors in arrays of 2d-pixel arrays. Than, these color array
Tool will start scanning using whatever keystone data was stored in `keystone.txt`
make corrections to the key stone using the sliders or keyboard using `1,2,3,4` to select a corner and `[w,a,s,d]` to move `[up,left,down,right]` the selected corner. Press `k` to save change to file and `ctrl-c` twice [in the terminal window] to exit program

#### output

the app will attempt sending the resulted scan to cityIO server. If successful, the following JSON format data will appear on the cityIO endpoint defined in `settings.json`

```
{
"grid": [
[1, 0],
[1, 0],
[0, 0],
[4, 0],
[-1, -1],
[-1, -1], // no type was found will return -1 as type and -1 as rotation
...
],
...
other cityIO data
...
}
```

### `Cityscopy.udp_listener()`

##### emulates local UDP server listener

simple helper method to emulate what a local UDP client might see if `cityscopy` would send scan over localhost

## Errors

OS, Python versions, openCV and peripheral devices such as webcams can sometimes cause issues. If you found and issue, please report it as a Github issue. Here're some encountered issues and their solutions:
Expand Down
46 changes: 16 additions & 30 deletions cityscopy.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def __init__(self, path):
# load info from json file
self.SETTINGS_PATH = path
# get the table settings. This is used bu many metohds
self.table_settings = self.parse_json_file('table')
self.table_settings = self.parse_json_file('cityscopy')
print('getting settings for CityScopy...')

# init corners variables
Expand Down Expand Up @@ -135,12 +135,12 @@ def scanner_function(self, multiprocess_shared_dict):
# get init keystones
self.init_keystone = self.get_init_keystone()
# define the table params
grid_dimensions_x = self.table_settings['header']['spatial']['nrows']
grid_dimensions_y = self.table_settings['header']['spatial']['ncols']
grid_dimensions_x = self.table_settings['nrows']
grid_dimensions_y = self.table_settings['ncols']
array_of_tags_from_json = self.np_string_tags(
self.table_settings['objects']['cityscopy']['tags'])
self.table_settings['tags'])

array_of_maps_form_json = self.table_settings['header']['mapping']['type']
array_of_maps_form_json = self.table_settings['type']

# init type list array
TYPES_LIST = []
Expand All @@ -149,7 +149,7 @@ def scanner_function(self, multiprocess_shared_dict):
OLD_CELL_COLORS_ARRAY = []

# serial num of camera, to switch between cameras
camPos = self.table_settings['objects']['cityscopy']['camId']
camPos = self.table_settings['camId']
# try from a device 1 in list, not default webcam
video_capture = cv2.VideoCapture(camPos)
time.sleep(1)
Expand Down Expand Up @@ -206,7 +206,7 @@ def scanner_function(self, multiprocess_shared_dict):
# else if camera capture is ok
else:
# mirror camera
if self.table_settings['objects']['cityscopy']['mirror_cam'] is True:
if self.table_settings['mirror_cam'] is True:
this_frame = cv2.flip(this_frame, 1)
# warp the video based on keystone info
keystoned_video = cv2.warpPerspective(
Expand Down Expand Up @@ -251,7 +251,7 @@ def scanner_function(self, multiprocess_shared_dict):
thisColor = DICTIONARY_COLORS[scannerCol]

# ? only draw vis if settings has 1 in gui
if self.table_settings['objects']['cityscopy']['gui'] is True:
if self.table_settings['gui'] is True:
# draw rects with frame colored by range result
cv2.rectangle(keystoned_video,
(x+scanner_reduction,
Expand Down Expand Up @@ -282,7 +282,7 @@ def scanner_function(self, multiprocess_shared_dict):
# else don't do it
pass

if self.table_settings['objects']['cityscopy']['gui'] is True:
if self.table_settings['gui'] is True:
# draw arrow to interaction area
self.ui_selected_corner(
video_resolution_x, video_resolution_y, keystoned_video)
Expand Down Expand Up @@ -356,7 +356,7 @@ def get_scanner_pixel_coordinates(self, grid_dimensions_x, grid_dimensions_y, vi
pixel_coordinates_list = []

# define a cell gap for grided cases [plexi table setup]
cells_gap = self.table_settings['objects']['cityscopy']['cell_gap']
cells_gap = self.table_settings['cell_gap']

# create the 4x4 sub grid cells
for y in range(0, grid_dimensions_y):
Expand Down Expand Up @@ -389,8 +389,8 @@ def np_string_tags(self, json_data):

# 2nd proccess to
def create_data_json(self, multiprocess_shared_dict):
self.table_settings = self.parse_json_file('table')
SEND_INTERVAL = self.table_settings['objects']['cityscopy']['interval']
self.table_settings = self.parse_json_file('cityscopy')
SEND_INTERVAL = self.table_settings['interval']
# initial dummy value for old grid
old_scan_results = [-1]
SEND_INTERVAL = timedelta(milliseconds=SEND_INTERVAL)
Expand All @@ -400,7 +400,7 @@ def create_data_json(self, multiprocess_shared_dict):
from_last_sent = datetime.now() - last_sent
if (scan_results != old_scan_results) and from_last_sent > SEND_INTERVAL:
try:
if self.table_settings['objects']['cityscopy']['cityio'] is True:
if self.table_settings['cityio'] is True:
self.send_json_to_cityIO(json.dumps(scan_results))
else:
self.send_json_to_UDP(scan_results)
Expand All @@ -421,7 +421,7 @@ def send_json_to_cityIO(self, cityIO_json):
'''
# defining the api-endpoint
API_ENDPOINT = "https://cityio.media.mit.edu/api/table/update/" + \
self.table_settings['header']['name'] + "/grid/"
self.table_settings['cityscope_project_name'] + "/grid/"
# sending post request and saving response as response object
req = requests.post(url=API_ENDPOINT, data=cityIO_json)
if req.status_code != 200:
Expand All @@ -430,20 +430,6 @@ def send_json_to_cityIO(self, cityIO_json):

##################################################

def init_table(self):
json_struct = self.table_settings
cityIO_json = json.dumps(json_struct)
# defining the api-endpoint
API_ENDPOINT = "https://cityio.media.mit.edu/api/table/update/" + \
self.table_settings['header']['name']
# sending post request and saving response as response object
req = requests.post(url=API_ENDPOINT, data=cityIO_json)
if req.status_code != 200:
print("cityIO might be down. so sad.")
print("init table on cityIO", req)

##################################################

def send_json_to_UDP(self, scan_results):
# defining the udp endpoint
UDP_IP = "127.0.0.1"
Expand Down Expand Up @@ -703,7 +689,7 @@ def keystone(self):
print('keystone path:', self.KEYSTONE_PATH)

# serial num of camera, to switch between cameras
camPos = self.table_settings['objects']['cityscopy']['camId']
camPos = self.table_settings['camId']
# try from a device 1 in list, not default webcam
WEBCAM = cv2.VideoCapture(camPos)
time.sleep(1)
Expand All @@ -730,7 +716,7 @@ def selectFourPoints():
cv2.setMouseCallback('canvas', save_this_point)
# read the WEBCAM frames
_, self.FRAME = WEBCAM.read()
if self.table_settings['objects']['cityscopy']['mirror_cam'] is True:
if self.table_settings['mirror_cam'] is True:
self.FRAME = cv2.flip(self.FRAME, 1)
# draw mouse pos
cv2.circle(self.FRAME, self.MOUSE_POSITION, 10, (0, 0, 255), 1)
Expand Down
4 changes: 2 additions & 2 deletions keystone.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
6.060000000000000000e+02 3.470000000000000000e+02
9.380000000000000000e+02 3.400000000000000000e+02
5.890000000000000000e+02 3.060000000000000000e+02
9.380000000000000000e+02 3.230000000000000000e+02
6.020000000000000000e+02 6.890000000000000000e+02
9.640000000000000000e+02 6.730000000000000000e+02
7 changes: 2 additions & 5 deletions run.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,12 @@
'''
)

cityscopy_settings_path = "settings/cityscopy.json"
CITYSCOPY_SETTINGS_PATH = "settings/cityscopy.json"
# init cityscopy class
cityscopy = Cityscopy(cityscopy_settings_path)
cityscopy = Cityscopy(CITYSCOPY_SETTINGS_PATH)
# run CityScopy main methods

# keystone the scanned area
# cityscopy.keystone()
# create new table instance on cityIO
cityscopy.init_table()
# scan the grid and send to cityIO
cityscopy.scan()
# start local UDP comms
Expand Down
47 changes: 0 additions & 47 deletions settings/cityscope_hanoi.json

This file was deleted.

62 changes: 19 additions & 43 deletions settings/cityscopy.json
Original file line number Diff line number Diff line change
@@ -1,46 +1,22 @@
{
"table": {
"header": {
"name": "cityscopy",
"spatial": {
"nrows": 10,
"ncols": 10,
"physical_longitude": 0,
"physical_latitude": 0,
"longitude": 0,
"latitude": 0,
"cellSize": 500,
"rotation": 0,
"projection": 3395
},
"owner": {
"name": "Ariel Noyman",
"title": "",
"institute": "City Science MIT Media Lab"
},
"block": ["type", "rotation"],
"mapping": {
"type": ["0", "1", "2", "3"],
"rotation": ["0", "1", "2", "3"]
}
},
"grid": [],
"objects": {
"cityscopy": {
"scan": false,
"camId": 0,
"interval": 250,
"gui": true,
"cityio": true,
"tags": [
"0000000000000000",
"1111111111111111",
"1111111100000000",
"1000000000000000"
],
"cell_gap": 0,
"mirror_cam": false
}
}
"cityscopy": {
"cityscope_project_name": "cityscopy",
"type": ["0", "1", "2", "3", "4", "5"],
"rotation": ["0", "1", "2", "3"],
"nrows": 10,
"ncols": 10,
"scan": false,
"camId": 0,
"interval": 250,
"gui": true,
"cityio": true,
"tags": [
"0000000000000000",
"1111111111111111",
"1111111100000000",
"1000000000000000"
],
"cell_gap": 0,
"mirror_cam": false
}
}
47 changes: 0 additions & 47 deletions settings/csepel.json

This file was deleted.

Loading

0 comments on commit de797b3

Please sign in to comment.