1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- # -*- coding: utf-8 -*-
- from __future__ import unicode_literals, division, print_function
- from math import log, tan, pi, radians
- import matplotlib.pyplot as plt
- import numpy as np
- from django.core.management.base import BaseCommand, CommandError
- from django.conf import settings
- from panorama.models import Panorama, Reference
- def bearing_diff(b1, b2):
- """In degrees"""
- return (b1 - b2) % 360
- def projection_factory(transform):
- def projection(location, p1, p2):
- """For now, simply returns the scaling factors for x and y given two reference points"""
- dx = (p2.x - p1.x) / (radians(bearing_diff(location.bearing(p2.reference_point), location.bearing(p1.reference_point))))
- dy = (p2.y - p1.y) / (transform(location.elevation(p2.reference_point)) - transform(location.elevation(p1.reference_point)))
- return (dx, dy)
- return projection
- equirectangular = projection_factory(lambda phi: radians(phi))
- cylindrical = projection_factory(lambda phi: tan(radians(phi)))
- mercator = projection_factory(lambda phi: log(tan(pi/4 + radians(phi)/2)))
- projections = [('equirectangular', equirectangular),
- ('cylindrical', cylindrical),
- ('mercator', mercator)]
- class Command(BaseCommand):
- def add_arguments(self, parser):
- parser.add_argument('pano_id', type=int)
- def handle(self, *args, **options):
- p = Panorama.objects.get(pk=options['pano_id'])
- for proj_name, proj in projections:
- self.stdout.write("\n{}".format(proj_name))
- data = {'distx': [], 'disty': [], 'dx': [], 'dy': [], 'ref1': [], 'ref2': [], 'middlex': [], 'ref1.x': []}
- for ref1 in p.panorama_references.order_by('x'):
- for ref2 in p.panorama_references.order_by('x'):
- if ref2 == ref1:
- continue
- if ref2.x >= ref1.x:
- (dx, dy) = proj(p, ref1, ref2)
- else:
- (dx, dy) = proj(p, ref2, ref1)
- distx = ref2.x - ref1.x
- disty = ref2.y - ref1.y
- middlex = (ref2.x + ref1.x) / 2
- data['ref1'].append(ref1)
- data['ref2'].append(ref2)
- data['ref1.x'].append(ref1.x)
- data['distx'].append(distx)
- data['disty'].append(disty)
- data['middlex'].append(middlex)
- data['dx'].append(dx)
- data['dy'].append(dy)
- #self.stdout.write('{} - {}'.format(ref1.reference_point.name, ref2.reference_point.name))
- #self.stdout.write('dx = {}'.format(dx))
- #self.stdout.write('dy = {}'.format(dy))
- # Detect outliers
- for axis in ['dx', 'dy']:
- median = np.median(data[axis])
- self.stdout.write("\nMedian for {}: {}".format(axis, median))
- for ref1, ref2, d in zip(data['ref1'], data['ref2'], data[axis]):
- if ref2.pk < ref1.pk:
- continue
- if abs(d - median) / median >= 0.15:
- self.stdout.write("Outlier: ({:5}, {:5}) - ({:5}, {:5}) → {}={}".format(ref1.x, ref1.y, ref2.x, ref2.y, axis, d))
- mediandx = np.median(data['dx'])
- mediandy = np.median(data['dy'])
- if proj_name == 'equirectangular':
- for xvar in ['distx', 'disty', 'middlex', 'ref1.x']:
- fig, ax = plt.subplots()
- ax.scatter(x=data[xvar], y=data['dx'], c=data['ref1.x'], alpha=0.5)
- ax.hlines([mediandx], 0, 1, transform=ax.get_yaxis_transform(), colors='r')
- ax.set_title('dx as a function of {}'.format(xvar))
- plt.show()
- for xvar in ['dx', 'distx', 'disty', 'middlex', 'ref1.x']:
- fig, ax = plt.subplots()
- ax.scatter(x=data[xvar], y=data['dy'], c=data['ref1.x'], alpha=0.5)
- ax.hlines([mediandy], 0, 1, transform=ax.get_yaxis_transform(), colors='r')
- ax.set_title('dy as a function of {}, for {} projection'.format(xvar, proj_name))
- plt.show()
|