Skip to content

Commit

Permalink
Back end
Browse files Browse the repository at this point in the history
  • Loading branch information
vargheserg committed Apr 26, 2020
1 parent 1f21704 commit fa6c12b
Show file tree
Hide file tree
Showing 18 changed files with 257 additions and 2 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.vscode
venv
solargeo.json
bfg-1.13.0.jar
*\google_creds.json
*\keys.json
4 changes: 4 additions & 0 deletions Aptfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
libsm6
libxrender1
libfontconfig1
libice6
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: gunicorn api:app
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
# EarthXHackothon
Hackathon Repo
# envohacks
Empty file added __init__.py
Empty file.
Binary file added __pycache__/get_map.cpython-38.pyc
Binary file not shown.
Binary file added __pycache__/get_prediction.cpython-38.pyc
Binary file not shown.
Binary file added __pycache__/get_size.cpython-38.pyc
Binary file not shown.
51 changes: 51 additions & 0 deletions api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from flask import Flask, request, jsonify
from detector import rooftop_detection as rd
from flask_cors import CORS

import os
app = Flask(__name__)
CORS(app)

@app.route('/')
def home():
return '<h1>Deployed to Wherever! </h1>'
#Environment variables: os.environ['varName']

@app.route('/process', methods=['GET'])
def stuff():
lat = float(request.args.get('lat'))
lon = float(request.args.get('lon'))
sol = float(request.args.get('solar'))
response = rd.get_roof_data(lat,lon)
image = response['image']
#response.pop('image', None)
coeffecient = {
"prism": 0.75,
"flat": 1,
"slantedprism": 0.6,
"pyramid": 0.5,
"complex": 0.4
}
response["adjusted"]=coeffecient[response["name"]] * sol
return jsonify(response)


if __name__ == "__main__":
app.run()

# Sample request
# {
# "methods": "GET",
# "solar": "3.121",
# "lat": "7.721321321313",
# "lon": "7.721321321313",
# }


# Sample response
# {
# "category": "slantedprism",
# "image": image,
# "calculatedArea":"something something m^2",
# "powerRating":"something something kWh/ m^2",
# }
Binary file added detector/__pycache__/get_map.cpython-38.pyc
Binary file not shown.
Binary file not shown.
Binary file added detector/__pycache__/get_size.cpython-38.pyc
Binary file not shown.
Binary file not shown.
30 changes: 30 additions & 0 deletions detector/get_map.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import requests, urllib, json

with open('keys.json', 'r') as f:
keys = json.load(f)

maps_static_key = keys["maps-static"]

imagewidth = 400
imageheight = 400
scale = 2

def get_map(zoom, latitude, longitude):
url = "https://maps.googleapis.com/maps/api/staticmap?"
center = str(latitude) + "," + str(longitude)

urlparams = urllib.parse.urlencode({'center': center,
'zoom': str(zoom),
'size': str(imagewidth) + 'x' + str(imageheight),
'maptype': 'satellite',
'sensor': 'false',
'scale': str(scale),
'key': maps_static_key})
print(url + urlparams)
r = requests.get(url + urlparams)

if not (r.status_code==404 or r.status_code==403):
return r.content
else:
return 0

76 changes: 76 additions & 0 deletions detector/get_prediction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import os, json, math
from google.cloud import automl_v1beta1
from google.cloud.automl_v1beta1.proto import service_pb2

from detector import get_map as gm

os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = "google_creds.json"

with open('keys.json', 'r') as f:
keys = json.load(f)

ml_project_id = keys["ml-project-id"]
ml_model_id = keys["ml-model-id"]


# 'content' is base-64-encoded image data.
def get_prediction(content, project_id, model_id):
prediction_client = automl_v1beta1.PredictionServiceClient()

name = 'projects/{}/locations/us-central1/models/{}'.format(project_id, model_id)
payload = {'image': {'image_bytes': content }}
params = {}
request = prediction_client.predict(name, payload, params)
return request # waits till request is returned

def calculateDistance(x1,y1,x2,y2):
dist = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
return dist

def make_recursive_prediction(zoom, latitude, longitude):
# Gets image of map from lat and long
img = gm.get_map(zoom, latitude, longitude)

if (zoom > 18):
# Try running the following code without errors
try:
# make a prediction on the image
prediction = get_prediction(img, ml_project_id, ml_model_id)

center = ((gm.imagewidth*gm.scale)/2,(gm.imageheight*gm.scale)/2)
dists = []

# iterate through each detection and calculate their distance to the center
for i in range (0, len(prediction.payload)):
detection = prediction.payload[i]
box = detection.image_object_detection.bounding_box.normalized_vertices
x1 = box[0].x*gm.imageheight*gm.scale
y1 = box[0].y*gm.imageheight*gm.scale
x2 = box[1].x*gm.imageheight*gm.scale
y2 = box[1].y*gm.imageheight*gm.scale
boxcenter = ((x1+x2)/2,(y1+y2)/2)
distToCenter = calculateDistance(boxcenter[0], boxcenter[1], center[0],center[1])
dists.append((distToCenter,i))

# find the box closest to the center of the frame
closestDist = dists[0]
for box in dists:
if box[0] < closestDist[0]:
closestDist = box

# return values of the closest box
payload = prediction.payload[closestDist[1]]
name = payload.display_name
score = payload.image_object_detection.score
box = payload.image_object_detection.bounding_box.normalized_vertices
x1 = box[0].x*gm.imageheight*gm.scale
y1 = box[0].y*gm.imageheight*gm.scale
x2 = box[1].x*gm.imageheight*gm.scale
y2 = box[1].y*gm.imageheight*gm.scale
return img, name, score, x1, y1, x2, y2, zoom

# if no detections are found, zoom out and recursively run the function over again
except (IndexError, KeyError, TypeError):
zoom -= 1
return make_recursive_prediction(zoom, latitude, longitude)
else: return 0
20 changes: 20 additions & 0 deletions detector/get_size.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import math

def get_roof_size(rType,x1,y1,x2,y2, latitude, zoom):
if zoom == 21:
metersPerPx = 2/46
elif zoom == 20:
metersPerPx = 5/57
elif zoom == 19:
metersPerPx = 10/57
else:
metersPerPx = (156543.03392 * math.cos(latitude * math.pi / 180) / math.pow(2, zoom))/234

widthM = (x2-x1)*metersPerPx
lengthM = (y2-y1)*metersPerPx
area = widthM*lengthM
print(area, widthM, lengthM)

return area


40 changes: 40 additions & 0 deletions detector/rooftop_detection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import cv2, base64
import numpy as np

from detector import get_size as gs
from detector import get_prediction as gp

def draw_box(img, x1, y1, x2, y2):
start = (int(x1),int(y1))
end = (int(x2),int(y2))
image = np.asarray(bytearray(img), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR)

cv2.rectangle(image, start, end, 0, 4)
#cv2.imshow("lalala", image)
#k = cv2.waitKey(0)

b64img= cv2.imencode('.png', image)[1].tostring()
retval, buffer = cv2.imencode('.png', image)
png_as_text = base64.b64encode(buffer)
return png_as_text

def get_roof_data(latitude, longitude):
zoom = 20
image, name, score, x1, y1, x2, y2, endZoom = gp.make_recursive_prediction(zoom, latitude, longitude)
size = gs.get_roof_size(name, x1,y1,x2,y2, latitude, endZoom)

image = draw_box(image, x1, y1, x2, y2)

response = {}
response['image']=str(image)[2:-1]
response['name']=name
response['score']=score
response['size']=size
return response

if __name__ == "__main__":
lat = 43.7322193485497874
longi = -79.6181400203285

get_roof_data(lat, longi)
28 changes: 28 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
cachetools==4.1.0
certifi==2020.4.5.1
chardet==3.0.4
click==7.1.1
Flask==1.1.2
Flask-Cors==3.0.8
google-api-core==1.17.0
google-auth==1.14.1
google-cloud==0.34.0
google-cloud-automl==0.10.0
googleapis-common-protos==1.51.0
grpcio==1.28.1
gunicorn==20.0.4
idna==2.9
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
numpy==1.18.3
opencv-python==4.2.0.34
protobuf==3.11.3
pyasn1==0.4.8
pyasn1-modules==0.2.8
pytz==2019.3
requests==2.23.0
rsa==4.0
six==1.14.0
urllib3==1.25.9
Werkzeug==1.0.1

0 comments on commit fa6c12b

Please sign in to comment.