From fa6c12bc340c9d2bc4f4c5d89aa32e2bb05bc894 Mon Sep 17 00:00:00 2001 From: Varghese Rony George Date: Sun, 26 Apr 2020 19:23:09 -0400 Subject: [PATCH] Back end --- .gitignore | 6 ++ Aptfile | 4 + Procfile | 1 + README.md | 3 +- __init__.py | 0 __pycache__/get_map.cpython-38.pyc | Bin 0 -> 891 bytes __pycache__/get_prediction.cpython-38.pyc | Bin 0 -> 2160 bytes __pycache__/get_size.cpython-38.pyc | Bin 0 -> 572 bytes api.py | 51 ++++++++++++ detector/__pycache__/get_map.cpython-38.pyc | Bin 0 -> 918 bytes .../__pycache__/get_prediction.cpython-38.pyc | Bin 0 -> 2208 bytes detector/__pycache__/get_size.cpython-38.pyc | Bin 0 -> 599 bytes .../rooftop_detection.cpython-38.pyc | Bin 0 -> 1285 bytes detector/get_map.py | 30 +++++++ detector/get_prediction.py | 76 ++++++++++++++++++ detector/get_size.py | 20 +++++ detector/rooftop_detection.py | 40 +++++++++ requirements.txt | 28 +++++++ 18 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 Aptfile create mode 100644 Procfile create mode 100644 __init__.py create mode 100644 __pycache__/get_map.cpython-38.pyc create mode 100644 __pycache__/get_prediction.cpython-38.pyc create mode 100644 __pycache__/get_size.cpython-38.pyc create mode 100644 api.py create mode 100644 detector/__pycache__/get_map.cpython-38.pyc create mode 100644 detector/__pycache__/get_prediction.cpython-38.pyc create mode 100644 detector/__pycache__/get_size.cpython-38.pyc create mode 100644 detector/__pycache__/rooftop_detection.cpython-38.pyc create mode 100644 detector/get_map.py create mode 100644 detector/get_prediction.py create mode 100644 detector/get_size.py create mode 100644 detector/rooftop_detection.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2d1cceb --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.vscode +venv +solargeo.json +bfg-1.13.0.jar +*\google_creds.json +*\keys.json diff --git a/Aptfile b/Aptfile new file mode 100644 index 0000000..6f0ea40 --- /dev/null +++ b/Aptfile @@ -0,0 +1,4 @@ +libsm6 +libxrender1 +libfontconfig1 +libice6 \ No newline at end of file diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..6f18d33 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: gunicorn api:app \ No newline at end of file diff --git a/README.md b/README.md index 91a2b2c..247f147 100644 --- a/README.md +++ b/README.md @@ -1,2 +1 @@ -# EarthXHackothon - Hackathon Repo +# envohacks diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/__pycache__/get_map.cpython-38.pyc b/__pycache__/get_map.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c69e9d9510604186215d2424d90f0c1fda155774 GIT binary patch literal 891 zcmYjPOK;RL5FR_uYagXll?viR%`q#@Pzh(R`k5n9ZHq{BlV zeT1aT$u11ybIcAq^Y};{>*1l6wIyoatP+SP}z2oAeEJfiwT>qVDdZx?us23S&OXFi%5)9CHd$kj2-rOZo_HiaH$ zvTD~x7>!o-A?5J}xo64yB-W`BWmyzRuE8SPw6;_=eY2d__=bFz8!P8)bu;!o;tw-=sGU z#6FrC{wpqJov&OE6)4xl#A!iQX{D9x@=s8=aJm>}+v7bglpfFKX`#l?l+2M-6?Hxq z^;wY!xd!Mpgd4Qy Klu(9>82tzEGVSjG literal 0 HcmV?d00001 diff --git a/__pycache__/get_prediction.cpython-38.pyc b/__pycache__/get_prediction.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e42dc89bb9b7494f14adffc1df0b17afc16e0e7 GIT binary patch literal 2160 zcmcIlPjA~c6elH0mTlRw6E}a>F4%@0W(-Y`0_%pM7}ljh5v)klCPh0To1ln{BS(K6 ziq2w>I%VfAA0avHuzNoZ54-G?udo5b9%Z*_u=6DFJ-$cs@jddrA73;YH3Z)ufB*Kw z=XHes)WW-86@;&$<-Y)-h~gM|6OKJx%7$kEH)1m(9>IFdjIG4>?6QyJisw+mP`^s8 z2Z+_EO)F={uPv|6@P*6jm)L8(M4zE&=s9|YSc5uC$ZGk(KiOP=xV!mu%U^%K@n~afck|(sopJSujV4nS=Ho^Z-yQI*&q8rG zqT@PDVzYj#93w((Rli~|QVrg6&1)&BtC5mu_3oAl}EzJv4 z5@|{M(kv>n0+Ere@u$=M^3|V;)i?_S5oKwg>48r3iaxp$&swb5m-?6LB^9nsLEh6q3fthn56>7yxMegKcb#fZlinc z=}a)?hZ7?t4H5<>f>E3WRM~@o2TAT#I6EG)T>Or>3r_rXKm2m<1>8u!Hyj5M-`nO{ z4<;s2+S_C4Np={7NBLfl3IBSFmBC0gZ>rk*ShYcf9mB;gCb)@t6XcL+?ex<(@b(ry z0zuz`G$dMt{GCJ6lz7rxK$o~6lE8@@TUYwHx`rZfD2IyV$6RzRWt^@lV+8H=9`JjL z&?pyWP!rOCMXDVJaX5?v!5+bAkcR9%Q0Jvjcp38rkZ$Bj2Nb&Q$~>vT#-)d-%n-AH z?4bCFoEzLY$K%(+kftyNIWr3)P~U=Pcc9{K!>WGeS~@Tas|Wcc9BPWHB>mbMJ~JMn z?_Wb!fg~$SsBomyulL=4qo~R%HJ4DosjYOhEwEbDrrMbs+B#^-f9ASV?ajFjS(ENU z>7T62#-sl`01m$9|99hl#i?fz^r3$)&!E9Of6|3+)dSvdzW*QF~P5*;`%(GDU= zbi^$&e_$Tfz}J5;(m&iQ`2rP4EXeY%&rBPA2eV(Hlu&aAuoE)T+Pa#B)ZjCkU?5kT zbQhJ;OH@S{L=p_jq*nk-P%tGd`4LqBOa9wpt(92tV?-gDtsD~c4LlsOsCOuo#e=lR zlo_*>>s0jSC*YCoYn1aT6TqO-J$FAFrW7jG-_K6Hxm2S@9E}fvAM#h3XjSx zS9UNMu#|c()X5+YMt%tp;6TQis%@r}oo;ZRapio=Mw4E3cQjy=?otvQF`u(=$n)p~ z!22zBbvufTvn){#lvyN(l&NZ*rM*eljFO%Ptv5)gYz>l(dzLO&a4_DZ=caeXriN>RAEa0DjxC|}-1_&~m zM$I6GYkYu-*}*mV=coT7AVbS^u!Co@V>Yo3z3b6=a~|XlF70*al#%5g(JvQofmzR; zyl5-n*N{$t{=;`wD>om+7042ias5>B+nQ*6QWb#Sh-axH8Qht|2a1#^PW0Qy@925& vYoYmr0Est@*;hJO^LZeP0MD-BK=>~17!W3Lst)-VXKy8O literal 0 HcmV?d00001 diff --git a/__pycache__/get_size.cpython-38.pyc b/__pycache__/get_size.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..587e20abf4ca7f995716ac9fc101a1ecf1a78590 GIT binary patch literal 572 zcmYk4y^hmB5XWcNpK%fzf;cHWz=Z?J2*3{umxCfaK*=5& z14d>L1Eb7&3o&8j2@Ko@pTOxPuxS@<%pU3(C10aypOJGat}wa@%7;h}(hcS!-9_?{ zZZaQfp9Kou5$!2>NqfM;K3tFbB2`o4Oe$$;og1gF7RIYZUaCPm_Qcaw%?(}NF?5Am9$-E&;Vf0TnloDeployed to Wherever! ' + #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", +# } \ No newline at end of file diff --git a/detector/__pycache__/get_map.cpython-38.pyc b/detector/__pycache__/get_map.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..651a96aed09f7a12d566f7c62acbb4e3731d1749 GIT binary patch literal 918 zcmYjP&ubJh6izakU;CrhQmEpO`-1MCycAKPisGT5rC5f+WjcA?o$l;pOtRH3TM*WR zHw8UJ&kGh^vepg}F$Tew8r##}(3o0p_Ij?5?m)^x30Ym} zZZ5}*cRkE{%l=UE^nyOH^ivY+%s^Qd2CRROl^Qys4RWXqD9fi(jxE>46p|3XF~>C| zfrd&;WqqAzC0GwPvG|GGRs29u7^Ks-o;Jz`6NQEMtzTzKgN-qTDwhImqZnrc_*e)t zw9N${LNOQ`<#yNJa2@oQPWxCM3#g(pHd63m0@`Tn4Zzr@Q%rP!Q8COVTCPkdRFSI@ zm3WS3g8zz3Sq+xdLkG$oV&c4@t8A>5JLNw_-NEVN_10#(t3m1XC{u%B`W*Dg$U5CZ z)9K5?yqfH%FRCLs%<_>=;fe_`kQ=E|^wmfA-TK&um%N3A^?d|FIbCNF4d@zW_ym+) zL}81ruyqv5bm~nJf3G}lG!|9i2#Yi2yLRQ1VU(qSSHaDvC2M@)h^b6<+wW&PyCp) zdqQStOGx2P#4kuLNZj|=^p#Wo0tZC3JxMm=j4fAJRky3Fs;jb~jjEF<9o-@NzWI0yOldv4wP6hZ9L&GYy z9wAnvWon-pzqOn?!xs%!zr;@SHTn#_Krhi7#G16Sf}A-Rt1z}`jn;ofPMbDp6UKQu zM_Vv1P`rz}?JMvL?R2qfdSj79p?k8i&xE%Dnp(>EN#HYgwEqyq@_-39@GzS_O>5C-JMpB*rZshFrPM} z@WF^DL*|PI0iD)Bj1tO15PVbnGka_pOYrsJOFsu9&;`CknMv`5A+a2UbbXvY@L4Rl7jCTQF6enx z3L5)iA{T?K-|0EFKj`#ap@kw&%`A2D=-Efo%NO{8h`Xq06UmHzS^RB9` zGhPRRux-?F9TVKdyalpPw08FB!?`)2k3rA}Bn^p{q0$$SG$k&$C3J~1A_*LZv2&#} z*)ty19&^zxDdTiQ858(UAHw)h5gMc-kGCLm@RMr$Ug(cQPq0mx^VQIbXkJ29*f{qP<;7!WP&gDHk#mC^=Xm;77}6A`AZKPq1R9p$vpUe5 z@55ii@~w1WWTgR=ny{%UDv}JVXZXz6L_fTRf&)pGS5Rh4dsrLRhmEWvE7V*;!=|>< z(YC;9R-I|*?r3YECI4AlpK0%|ZOE#uFXjHpnrsvt_|_CH+0;7%1zWO|^Ciunk!(&{ z7i~Ew%Lm3K#^|^&Ej^#Lqy-V&zxGzPwDt&{W4jOAmhItuHV?Em zT*wyk@&Aq1l=E@{Vy?-$Y)Euqzec-=Akh)`#NvT@R0UuE!AQSwuH*}pA+aR$vpzE| z^gXP8gJMF>T|il=#L~{yJd_64#m+I1D^0q~${0jkmsDQx3eXCgB}XeapbF5+z3Jg< z4iP^E6biYNLUCTB#vuy^heDOO7Y~>+Ll$$m9+0zGU`n#D!Otxk5&*!d?^QI~jLMx>do!z^U9uWI`ZZw;#W!$)YApIt3M&nEj~z7kf#sFjMoxBn6n$t(|9! z>(1q$XrgiN76*72#8vpxZ-5}9X;ckj)Qt}@F*~>l@8axT22^O7Hn#CRw#_ECfV-Vt zG#5ec;M^VrZzQQA`aHP#k|bYJVr zfW!e$Vnq@-J%tYx$zh)8%aMNoOSq0Hue$u4bGP0JJx@Z8gZ3jR!EwmG(iNNP+%5x1 S*C7Q}fa{I{0Ta7olYarOaWyjl literal 0 HcmV?d00001 diff --git a/detector/__pycache__/get_size.cpython-38.pyc b/detector/__pycache__/get_size.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2af87724458a20b95c8067e32e84827c7e37ba6 GIT binary patch literal 599 zcmYk4&u-H|5XNVB?bxvsE~Ka^T(~tHklF(Wga{?AKmw{tkOP(lGTFs3`Lot~(>0y_cDEd_9EV&9?4-c7!|Sj=QzG$prwjap`RDovACWuZL8>E5Mpz0Eyb*S>Oto?eVb5iZo`nM*M&&J|5{ytDttMcg|lhc-D literal 0 HcmV?d00001 diff --git a/detector/__pycache__/rooftop_detection.cpython-38.pyc b/detector/__pycache__/rooftop_detection.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eace9931dcb6424ff2afb10285ee1b7bb7f82e0e GIT binary patch literal 1285 zcmYjR&5ImG6t9o|sP5^REbAt^pi%JRTmmj31PPL`Sya#sB<51IX=ZikDh+yo~pPyw8 zLVsH2>Y$+9hgm-ZB9X*X#J3!C-0Or>;AHCLF88ptQILJkKz5}267fKK(gz-@fn;Yy za~beRhJ2_(6{+EpfG2)}#)A#qfsV(xW2rJpon0u9M^>)1lG(&$WifHB)8&YO`!Ek- z)-Qn=)ZirsN|yMPv@S@r*PUMX41PfjZO{@+EXhx#^^LP~8=x<|^;Yv6zi}H+Qt7N+ zjKIz$c&v%^_R%U>qn5p0i%A=_p$S)mCS2oo&Rwt@Ph z3+GlQt{}kZyp~#c$geM`ufph z9%wZ&qDZI8x~QUeVWzB&&Wg12PDHKl+=k=s+};}d+w!y{=bv_D0rUI-_(A8^MrhMf zRmjfGa*-8a9u0Ffu6PK-J?zaV`Ba`@-l!_VTUwbFGw7dm|& zKUDRZDXaJpLXN-4%$Kv1_^6nd&&A}dj@27UDgz0WI@V=*3LBE`0swrgT69cm@qKbq zo?CG1T_6bWz_*J>WY^gPDa86cSe+1SyBtH{0nEM|8W1FIi9svekOul$dMIooW=vpSrdR)xc1wDaT@yn+R|-lhT6!uwv!~0^arw!nn*hL5bTVk3)}_n z0UrSOfk)5Gvvn}1>GcR=c#LgWgnJ}I^8oW94sj-(ae&&8Qa0M?nVv$?v` z@?fs{&^`lOto~i}$#)dc9uGO23X_=`^hhu*i*zeG7iF3ESL*lSUj2b3wnBPj$u&!M zfN&p>=hpWoXdTn4uF3)sweW7qyVmgbekqKw#@eQbu!C>n8)Sz#cn`Dw(;wRnEJ<>a z6-ko*`1|$me*NR&b89k+wK#`|IIuG0Urkwnzi+mu;bK)$~V}*guf| z&=L#yo3m{hlcb}NJ9qoEuSDF(-iOWZ<)xfW)#vub^_{eX8HsR2*flm{5WPeG1JMml A%K!iX literal 0 HcmV?d00001 diff --git a/detector/get_map.py b/detector/get_map.py new file mode 100644 index 0000000..50164ae --- /dev/null +++ b/detector/get_map.py @@ -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 + diff --git a/detector/get_prediction.py b/detector/get_prediction.py new file mode 100644 index 0000000..72794e3 --- /dev/null +++ b/detector/get_prediction.py @@ -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 \ No newline at end of file diff --git a/detector/get_size.py b/detector/get_size.py new file mode 100644 index 0000000..68133ad --- /dev/null +++ b/detector/get_size.py @@ -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 + + diff --git a/detector/rooftop_detection.py b/detector/rooftop_detection.py new file mode 100644 index 0000000..990d5b9 --- /dev/null +++ b/detector/rooftop_detection.py @@ -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) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c3d9d67 --- /dev/null +++ b/requirements.txt @@ -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