| заглавие | Описание | Ссылка на сайт |
|---|---|---|
| Приложениям дополненной реальности требуется серверная часть веб-службы. Это 90-дневное без обязательств, абсолютно бесплатное предложение использовать Windows Azure в качестве веб-службы для клиентов Windows 8. | Вы получаете: Compute / 750 небольших вычислительных часов в месяц, веб-сайты / 10 веб-сайтов, мобильные сервисы / 10 мобильных сервисов, реляционная база данных / 1 база данных SQL, отчеты SQL / 100 часов в месяц, хранилище / 35 ГБ с 50 000 000 транзакций хранения, пропускная способность / неограниченный входящий и 25 ГБ исходящий, CDN / 20 ГБ исходящий с 500 000 транзакций, кэш / 128 МБ, служебная шина / 1500 часов ретрансляции и 500 000 сообщений | http://www.microsoft.com/click/services /Redirect2.ashx?CR_CC=200114759 ![]() |
| Шаг 0: Что мы будем строить. Дополненная реальность, Windows 8 и облачные вычисления — как реализовать с реальным кодом | Введение высокого уровня в наше законченное приложение. | http://blogs.msdn.com/b/brunoterkaly/archive/2012 / 11/05 / step-0-что-мы-будем-строить- дополненную реальность-windows-8-and-cloud-computing-how-how- в реализации-с реальной code.aspx # |
| Шаг 1 — Дополненная реальность, Windows 8 и облачные вычисления — Как реализовать с реальным кодом | Вступление. Что такое дополненная реальность | http://blogs.msdn.com/b/brunoterkaly/archive/2012/10/29/ шаг-1-дополненная реальность-окна-8-и-облачные вычисления- как реализовать с реальным- code.aspx # |
| Шаг 2 — Дополненная реальность, Windows 8 и облачные вычисления — Как реализовать с реальным кодом | Сборка первой части нашего бэкэнда Azure. | http://blogs.msdn.com/b/brunoterkaly/archive/2012/10/30/ step-2-augmented-reality-windows-8-and- cloud-computing-как реализовать с реальными code.aspx # |
| Шаг 3 — Дополненная реальность, Windows 8 и облачные вычисления — Как реализовать с реальным кодом (Внедрение облачной среды) | В этом посте представлен весь исходный код и пояснения для серверной части Azure. Это серверная часть для Windows 8 Client дополненной реальности. | http://blogs.msdn.com/b/brunoterkaly/archive/2012/11/05 / step-3-augmented-reality-windows-8-and-cloud-computing-как реализовать с реальными реализующий код из облака-обратно-end.aspx # |
| Шаг 4 — Дополненная реальность, Windows 8 и облачные вычисления — Как реализовать с реальным кодом … | Этот пост содержит весь исходный код и пояснения для клиента Windows 8 (демонстрация дополненной реальности). Клиент дополненной реальности Windows 8 обращается к бэкэнду Azure, описанному в шаге 3 выше. | http://blogs.msdn.com/b/brunoterkaly/archive/2012/11/06/ шаг-4-дополненная реальность-окна-8-и-облачные вычисления-как реализовать с реальными- код реализации Windows-8-client.aspx # |
| Исходный код — серверная часть веб-службы | Это проект Windows Azure, к которому обращаются клиенты Windows 8 | http://sdrv.ms/Qoqb1J |
| Исходный код — клиент Windows 8 | Это клиент дополненной реальности для Windows 8 | http://sdrv.ms/T38uBC |
Это проект Windows 8
- Он работает на ОС Windows 8 и был построен с Visual Studio 2012
- Этот пост будет строить это приложение с нуля
- Он будет связываться с облачным бэкэндом, который мы создали в последнем посте.
- Облачный бэкэнд — это облачный проект Windows Azure
- Он был развернут в центре обработки данных
Уровень клиента — Windows 8
- Этот пост основан на последнем посте, который был уровнем Front-End Web Services. Это было облачное приложение Windows Azure (с веб-ролью типа ASP.NET Web API)
- Клиент дополненной реальности Windows 8 не будет работать, если не будет облачного сервера
- Облачный сервер может работать в центре обработки данных MS
- Или он может работать как проект Visual Studio 2012 с использованием эмулятора вычислений Windows Azure
Создание приложения для Windows 8
- В Visual Studio выберите Файл / Новый проект / Приложение Магазина Windows.
- Выберите пустое приложение
Проект по умолчанию: изменение файла манифеста приложения
- Вы ищете обозреватель решений
- Он доступен из меню ВИД
- Щелкните правой кнопкой мыши Package.appmanifest и выберите VIEW DESIGNER. Это позволит нам изменить возможности. Например, мы хотим разрешить подключение к интернету.
Манифест приложения: включение возможностей
- Я выбрал варианты, которые вы видите выше.
- Интернет, микрофон, доступ к библиотеке изображений, доступ к библиотеке видео, веб-камера
- Когда вы запускаете приложение Windows 8, вам все равно необходимо подтвердить использование веб-камеры и микрофона.
Основной интерфейс: MainPage.xaml
- Вы также можете использовать EXPRESSION BLEND для редактирования вашего графического интерфейса.
- Visual Studio 2012 также имеет дизайнера, доступного в меню просмотра.
Понимание XAML
- Пользовательский интерфейс — это просто набор элементов управления XAML
- Это просто большой XML-файл, похожий на пользовательский интерфейс Android
- StackPanels и Grids составляют большую часть интерфейса
- Кнопки, текстовые блоки, изображения, прямоугольники, холсты, радиокнопки вложены в панели стека и сетки
- Существует также CapturePanel для отображения живого видео с веб-камеры.
- Этот экран показывает одну из панелей стека
- Содержит вложенные StackPanels
- Он содержит 2 кнопки и радиокнопки для симулятора GPS
- Симулятор GPS позволяет выбрать Сан-Франциско, Рено, Денвер или Долину Смерти
- Моя система не имеет встроенного симулятора
Понимание XAML
- Радиокнопки расположены в StackPanel
Понимание XAML
- Раздел дополненной реальности — это просто сетка с границами
- Сетка содержит TextBlocks, куда мы будем помещать данные, которые мы получаем от вызова нашего облачного бэкэнда Azure, облачного сервиса.
- Заполнение TextBlocks информацией о местонахождении и погоде выполняется с помощью кода (MainPage.xaml.cs)
<Page x:Class="AugmentedRealityClient.MainPage" IsTabStop="false" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:AugmentedRealityClient" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" HorizontalAlignment="Center" VerticalAlignment="Center"> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}" x:Name="LayoutRoot" HorizontalAlignment="Left" VerticalAlignment="Center"> <!—Two rows, One column--> <Grid.RowDefinitions> <RowDefinition Height="165"/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> </Grid.ColumnDefinitions> <Border BorderThickness="3" BorderBrush="White" Grid.Row="0"/> <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="6" HorizontalAlignment="Left" VerticalAlignment="Center"> <Button x:Name="butConfigure" Content="Configure" Width="200" Height="80" FontSize="32" Margin="6" Click="ConfigureCamera_Click"/> <Button x:Name="butTurnCameraOn" Content="Take Picture" Width="218" Height="80" FontSize="32" Margin="6,6"/> <StackPanel> <TextBlock x:Name="txtGPS" FontSize="14" Canvas.Left="22" Canvas.Top="9" Margin="0,12,0,2" Foreground="Yellow" FontFamily="Segoe UI" Text="GPS Simulator" FontWeight="Bold" HorizontalAlignment="Left" VerticalAlignment="Top" TextAlignment="Center"/> <RadioButton Name="radSF" GroupName="GPS" Content="{Binding Path=City1, Mode=TwoWay}" IsChecked="{Binding Path=IsChecked1, Mode=TwoWay}" Checked="radSF_Checked"> </RadioButton> <RadioButton Name="radReno" GroupName="GPS" Content="{Binding Path=City2, Mode=TwoWay}" IsChecked="{Binding Path=IsChecked2, Mode=TwoWay}" Checked="radReno_Checked"> </RadioButton> <RadioButton Name="radDenver" GroupName="GPS" Content="{Binding Path=City3, Mode=TwoWay}" IsChecked="{Binding Path=IsChecked3, Mode=TwoWay}" Checked="radDenver_Checked"> </RadioButton> <RadioButton Name="radDeathValley" GroupName="GPS" Content="{Binding Path=City4, Mode=TwoWay}" IsChecked="{Binding Path=IsChecked4, Mode=TwoWay}" Checked="radDeathValley_Checked"> </RadioButton> </StackPanel> </StackPanel> <StackPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"> <Canvas x:Name="previewCanvas1" Background="Black" Width="640" Height="600"> <CaptureElement x:Name="previewElement1" HorizontalAlignment="Left" VerticalAlignment="Top"/> <Grid HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5"> <Grid.ColumnDefinitions> <ColumnDefinition Width="100"/> <ColumnDefinition Width="300"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="20"/> <RowDefinition Height="20"/> <RowDefinition Height="20"/> <RowDefinition Height="20"/> <RowDefinition Height="20"/> </Grid.RowDefinitions> <!--Row 1--> <Rectangle Grid.Column="0" Grid.Row="0" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock Grid.Column="0" Grid.Row="0" Text="Neighborhood" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFF2F213"/> <Rectangle Grid.Column="1" Grid.Row="0" Stroke="white" Fill="Black" Opacity=".3"/> <TextBlock x:Name="bus_and_neighborhood" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/> <!--Row 2--> <Rectangle Grid.Column="0" Grid.Row="1" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock Grid.Column="0" Grid.Row="1" Text="Elevation" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFF2F213"/> <Rectangle Grid.Column="1" Grid.Row="1" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock x:Name="elevation" Grid.Column="1" Grid.Row="1" Text="(1,0)" HorizontalAlignment="Center" VerticalAlignment="Center"/> <!--Row 3--> <Rectangle Grid.Column="0" Grid.Row="2" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock Grid.Column="0" Grid.Row="2" Text="Lat/Long" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFF2F213"/> <Rectangle Grid.Column="1" Grid.Row="2" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock x:Name="latlong" Grid.Column="1" Grid.Row="2" Text="(1,0)" HorizontalAlignment="Center" VerticalAlignment="Center"/> <!--Row 4--> <Rectangle Grid.Column="0" Grid.Row="3" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock Grid.Column="0" Grid.Row="3" Text="Max temp" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFF2F213"/> <Rectangle Grid.Column="1" Grid.Row="3" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock x:Name="max_temp" Grid.Column="1" Grid.Row="3" Text="(1,0)" HorizontalAlignment="Center" VerticalAlignment="Center"/> <!--Row 5--> <Rectangle Grid.Column="0" Grid.Row="4" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock Grid.Column="0" Grid.Row="4" Text="MinTemp" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFF2F213"/> <Rectangle Grid.Column="1" Grid.Row="4" Stroke="White" Fill="Black" Opacity=".3"/> <TextBlock x:Name="min_temp" Grid.Column="1" Grid.Row="4" Text="(1,0)" HorizontalAlignment="Center" VerticalAlignment="Center"/> <Image Grid.Column="2" Grid.Row="0" Grid.RowSpan="5" Source="http://www.ssec.wisc.edu/data/us_comp/image1.jpg" Opacity=".7"/> </Grid> </Canvas> </StackPanel> </Grid> </Page>- Порядок элементов управления имеет решающее значение.
- Это позволяет нам накладывать данные поверх потока живого видео с веб-камеры.
- Если вы заметили, многие из текстовых блоков появляются ПОСЛЕ элемента управления CaptureElement.
- Это контролирует z-порядок элементов управления.
| Линия | Комментарий |
|---|---|
| 35-49 | Две кнопки. Одна кнопка предназначена для включения веб-камеры, а другая — для фотографирования. Я иллюстрировал фотографирование в предыдущем посте. Содержит ссылку на метод события (ConfigureCamera_Click) |
| 50-91 | Пользовательский интерфейс для симулятора GPS. Текстовый блок и куча радио кнопок. Все 4 переключателя имеют процедуру обработки события, поскольку в конечном итоге они обращаются в веб-службу Azure для получения нового местоположения GPS. |
| 98 | Канва для отображения живого видеопотока дополненной реальности с веб-камеры |
| 103-105 | Элемент управления, отображающий потоковое видео в режиме дополненной реальности |
| 143, 169, 196, 224, 250 | TextBlocks, которые будут отображать данные дополненной реальности, поступающие из внутреннего облачного приложения Azure. |
| 257 | Используется для хранения последних спутниковых изображений погоды |
MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// Some extra using statements for my code
using Windows.Devices.Enumeration;
using Windows.Media.Capture;
using Windows.Media.MediaProperties;
using System.Net.Http;
using Windows.Data.Json;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace Windows8AugmentedRealityClient
{
public sealed partial class MainPage : Page
{
private Windows.Media.Capture.MediaCapture m_mediaCaptureMgr;
// Our GPS simulator
GPSSimulator _gps_simulator;
// This object get populated with data from calling into
// our Windows Azure Web Service, which was created in the
// previous blog
private LocationInfo loc_info = new LocationInfo();
public MainPage()
{
this.InitializeComponent();
// previewElement1 is our view port to see the streaming
// video content from the web cam
previewElement1.Source = null;
// Make sure it is visible
previewCanvas1.Visibility = Windows.UI.Xaml.Visibility.Visible;
// Initialize our GPS Simulator
_gps_simulator = new GPSSimulator();
_gps_simulator.City1 = "San Francisco";
_gps_simulator.Gps1 = "37.788345,-122.404679";
_gps_simulator.IsChecked1 = true;
_gps_simulator.City2 = "Reno";
_gps_simulator.Gps2 = "39.545353,-119.815631";
_gps_simulator.IsChecked2 = false;
_gps_simulator.City3 = "Denver";
_gps_simulator.Gps3 = "39.752073,-104.979968";
_gps_simulator.IsChecked3 = false;
_gps_simulator.City4 = "Death Valley";
_gps_simulator.Gps4 = "36.619937,-117.10415";
_gps_simulator.IsChecked4 = false;
// Trap some change events (for debugging purposes)
_gps_simulator.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(gpsChanged);
// Bind our GPS Simulator to the Windows 8 form's DataContext
this.DataContext = _gps_simulator;
}
private void gpsChanged(object sender, PropertyChangedEventArgs e)
{
string s = "The property:'" + e.PropertyName + "' was changed";
}
// Ignored for this demo
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
// Hit when user hits the "Configure" button
// This method initializes the web cam to display the live
// streaming video content
internal async void ConfigureCamera_Click(Object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
// Initialize Media Capture API
try
{
// Prepare Media Capture
m_mediaCaptureMgr = new Windows.Media.Capture.MediaCapture();
var _captureSettings = new Windows.Media.Capture.MediaCaptureInitializationSettings();
DeviceInformationCollection deviceInfos = await DeviceInformation.FindAllAsync(Windows.Devices.Enumeration.DeviceClass.VideoCapture);
_captureSettings = new MediaCaptureInitializationSettings();
_captureSettings.StreamingCaptureMode = StreamingCaptureMode.Video;
_captureSettings.PhotoCaptureSource = PhotoCaptureSource.VideoPreview;
if (deviceInfos.Count > 0)
{
_captureSettings.VideoDeviceId = deviceInfos[0].Id;
}
await m_mediaCaptureMgr.InitializeAsync(_captureSettings);
}
catch (Exception exception)
{
// Ignore errors for now
string s = exception.Message;
}
// Start the Preview
try
{
previewElement1.Source = m_mediaCaptureMgr;
await m_mediaCaptureMgr.StartPreviewAsync();
}
catch (Exception exception)
{
previewElement1.Source = null;
}
}
// This method performs the call into our Azure Web Service
// fromt the previous post. This method will pass GPS parameters
// to the cloud service and receive back JSON data that will
// need to be parsed.
private async System.Threading.Tasks.Task CallLocationWebService(string gps)
{
// Call into the emulator. This assumes you are running the
// cloud project from the last post in the backgruond
string _location = "http://127.0.0.1:81/api/values?location={0}";
// You can use the line below once you deploy your cloud
// application to the cloud (a MS data center)
//string _location = "http://locationwebservice.cloudapp.net/api/values?location={0}";
// Now make the aynchronous call. We need to pass the GPS
// parameters here to the _location string mentioned above.
using (HttpClient clientlocation = new HttpClient())
using (var response = await clientlocation.GetAsync(string.Format(_location, gps)))
{
if (response.IsSuccessStatusCode)
{
string webresponse = await response.Content.ReadAsStringAsync();
// Parse the string into a JSONObject
var parsedResults = JsonObject.Parse(webresponse);
IJsonValue val;
// Extract data embedded in JSONObject.
// Assign to controls in user interface
if (parsedResults.TryGetValue("latitude", out val))
loc_info.latitude = val.GetString();
if (parsedResults.TryGetValue("longitude", out val))
loc_info.longitude = val.GetString();
if (parsedResults.TryGetValue("bus_and_neighborhood", out val))
loc_info.bus_and_neighborhood = val.GetString();
if (parsedResults.TryGetValue("elevation", out val))
loc_info.elevation = val.GetString();
if (parsedResults.TryGetValue("bus_and_neighborhood", out val))
loc_info.bus_and_neighborhood = val.GetString();
if (parsedResults.TryGetValue("max_temp", out val))
loc_info.max_temp = val.GetString();
if (parsedResults.TryGetValue("min_temp", out val))
loc_info.min_temp = val.GetString();
this.bus_and_neighborhood.Text = loc_info.bus_and_neighborhood;
this.elevation.Text = loc_info.elevation;
this.latlong.Text = loc_info.latitude + "/" + loc_info.longitude;
this.max_temp.Text = loc_info.max_temp;
this.min_temp.Text = loc_info.min_temp;
}
}
}
// Checkbox events
// Called when user clicks a radio button on the GPS Simulator
private async void radSF_Checked(object sender, RoutedEventArgs e)
{
string s = _gps_simulator.Gps1;
await CallLocationWebService(s);
}
private async void radReno_Checked(object sender, RoutedEventArgs e)
{
string s = _gps_simulator.Gps2;
await CallLocationWebService(s);
}
private async void radDenver_Checked(object sender, RoutedEventArgs e)
{
string s = _gps_simulator.Gps3;
await CallLocationWebService(s);
}
private async void radDeathValley_Checked(object sender, RoutedEventArgs e)
{
string s = _gps_simulator.Gps4;
await CallLocationWebService(s);
}
// A helper method. Not currently used but was valuable during
// debugging my controls.
public IEnumerable<T> HelperFindMatch<T>(DependencyObject depObj) where T : DependencyObject
{
System.Diagnostics.Debugger.Break();
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in HelperFindMatch<T>(child))
{
yield return childOfChild;
}
}
}
}
// A helper method. Not currently used but was valuable during
// debugging my controls.
public T HelperFindVisualChildByName<T>(DependencyObject parent, string name) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
string controlName = child.GetValue(Control.NameProperty) as string;
if (controlName.IndexOf("rad") != -1 && controlName != name)
{
return child as T;
}
else
{
T result = HelperFindVisualChildByName<T>(child, name);
if (result != null)
return result;
}
}
return null;
}
}
// This class represents the data populated by the Windows Azure
// Web Service
public class LocationInfo
{
// Data we will lookup
public string latitude { get; set; }
public string longitude { get; set; }
public string elevation { get; set; }
public string bus_and_neighborhood { get; set; }
public string max_temp { get; set; }
public string min_temp { get; set; }
}
//Implement INotifiyPropertyChanged interface to subscribe for
//property change notifications
public class GPSSimulator : INotifyPropertyChanged
{
private string _gps1;
private string _city1;
private bool _ischecked1;
private string _gps2;
private string _city2;
private bool _ischecked2;
private string _gps3;
private string _city3;
private bool _ischecked3;
private string _gps4;
private string _city4;
private bool _ischecked4;
public string Gps1
{
get { return _gps1; }
set
{
_gps1 = value;
RaisePropertyChanged("Gps1");
}
}
public string City1
{
get { return _city1; }
set
{
_city1 = value;
RaisePropertyChanged("City1");
}
}
public bool IsChecked1
{
get { return _ischecked1; }
set
{
_ischecked1 = value;
RaisePropertyChanged("IsChecked1");
}
}
public string Gps2
{
get { return _gps2; }
set
{
_gps2 = value;
RaisePropertyChanged("Gps2");
}
}
public string City2
{
get { return _city2; }
set
{
_city2 = value;
RaisePropertyChanged("City2");
}
}
public bool IsChecked2
{
get { return _ischecked2; }
set
{
_ischecked2 = value;
RaisePropertyChanged("IsChecked2");
}
}
public string Gps3
{
get { return _gps3; }
set
{
_gps3 = value;
RaisePropertyChanged("Gps3");
}
}
public string City3
{
get { return _city3; }
set
{
_city3 = value;
RaisePropertyChanged("City3");
}
}
public bool IsChecked3
{
get { return _ischecked3; }
set
{
_ischecked3 = value;
RaisePropertyChanged("IsChecked3");
}
}
public string Gps4
{
get { return _gps4; }
set
{
_gps4 = value;
RaisePropertyChanged("Gps4");
}
}
public string City4
{
get { return _city4; }
set
{
_city4 = value;
RaisePropertyChanged("City4");
}
}
public bool IsChecked4
{
get { return _ischecked4; }
set
{
_ischecked4 = value;
RaisePropertyChanged("IsChecked4");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
}
Спасибо за прочтение.
Ваше задание — перейти на http://programmableweb.com и выполнить собственную дополненную реальность и сопоставления данных.
Не забудьте отправить его мне, чтобы я мог написать об этом в блоге









