隨着微軟顏齡中文網cn.how-old.net的上線,她也順勢來到了3大移動平台。
用戶在微軟顏齡這一應用中選擇一張包含若干人臉的照片,就可以通過雲計算得到他們的性別和年齡。
今天我們就和大家分享一下開發windows phone 平台的 微軟顏齡 中的經驗。
用Windows Phone的小伙伴也可以掃描下面的二維碼來安裝體驗一下:
技術背景
微軟顏齡的技術來自必應和微軟研究院的Oxford項目。該項目包含大量面部、語言和視覺方面的服務。微軟顏齡 這款有趣的應用僅僅使用了其中人臉偵測的部分api。有興趣的小伙伴可以訪問http://www.projectoxford.ai/來嘗試一下其他api,或許結合上你的好點子,一個有趣的應用就會從你手中誕生。
FACE API應用
微軟顏齡windows phone版從開始開發到第一版發布只有短短幾天時間,能做到這么快的發布,得益於Project Oxford優秀的SDK和例子程序,以及我們在之前的CNBLOGS等UAP應用開發中的積累。
在引用了Project Oxford的.Net SDK之后,我們只要調用FileOpenPicker在應用中得到用戶所選擇照片的Stream,就可以通過SDK的api分析出照片中人臉的信息:
/// <summary>
/// Detects an image asynchronously.
/// </summary>
/// <param name="imageStream">The image stream.</param>
/// <param name="analyzesFaceLandmarks">If set to <c>true</c> [analyzes face landmarks].</param>
/// <param name="analyzesAge">If set to <c>true</c> [analyzes age].</param>
/// <param name="analyzesGender">If set to <c>true</c> [analyzes gender].</param>
/// <param name="analyzesHeadPose">If set to <c>true</c> [analyzes head pose].</param>
/// <returns>The detected faces.</returns>
public async Task<Face[]> DetectAsync(Stream imageStream, bool analyzesFaceLandmarks = false, bool analyzesAge = false, bool analyzesGender = false, bool analyzesHeadPose = false)
SDK的api本身可以設置檢測包括人臉的整體位置,五官位置(analyzesFaceLandmarks),年齡(analyzesAge),性別(analyzesGender),甚至相對照片平面的三維角度(analyzesHeadPose),而微軟顏齡應用則只是利用了其中的年齡和性別信息。具體可以查看SDK中的Face.cs文件,或是通過在API Sample上提交一張照片取得分析結果來查看。
在通過SDK的api取得必要的人臉信息之后,我們就可以經過一系列計算,將其展示在用戶的圖片之上了。這一過程在SDK的例子程序的UIHelper.cs文件中也有現成的,我們可以根據自己的需求對其進行自定義。比如在windows phone版微軟顏齡的第二版中,我們就將性別替換為相應圖標的路徑,並且增加了邊框顏色的屬性,使得男女在界面上區別更明顯:
原版:
第二版:
不斷進步
接下來我們結合在之前的開發中積累的經驗與創新的思路,終於很快地將cn.how-old.net上的體驗在windows Phone平台展現出來:
比如首頁的自帶圖片選擇控件,就是巧妙地控制了ScrollViewer與StackPanel的共同運作。通過設置ScrollViewer的HorizontalSnapPointsAlignment 及 HorizontalSnapPointsType屬性,使得在滑動的時候,Image元素可以總是停在屏幕的正中,就像在瀏覽相冊一樣。
<ScrollViewer x:Name="sc" Grid.Row="1" Margin="0,20,0,0"
HorizontalScrollBarVisibility="Hidden"
HorizontalSnapPointsAlignment="Center"
HorizontalSnapPointsType="Mandatory"
VerticalAlignment="Top" ViewChanged="sc_ViewChanged"
HorizontalAlignment="Center" Width="780" Background="{ThemeResource BackgroundColor}">
<StackPanel Orientation="Horizontal" Height="260" HorizontalAlignment="Center">
<Image Source="Assets/Images/Left_Edge.png" Stretch="UniformToFill" Width="260"/>
<Image Source="Assets/Images/0.png" Stretch="UniformToFill" Width="260"/>
<Image Source="Assets/Images/1.png" Stretch="UniformToFill" Width="260"/>
…
<Image Source="Assets/Images/13.png" Stretch="UniformToFill" Width="260"/>
<Image Source="Assets/Images/14.png" Stretch="UniformToFill" Width="260"/>
<Image Source="Assets/Images/Right_Edge.jpg" Stretch="UniformToFill" Width="260"/>
</StackPanel>
</ScrollViewer>
然而ScrollViewer並不像ListView那樣有SelectedIndex屬性,那么我們如何知道用戶選擇的是哪張圖片呢?因為我們設置了相同的Image元素寬度,並且ScrollViewer是3倍Image元素的寬度,加上Image元素序列首尾有單獨的首尾元素,所以簡單的計算一下index就可以了:
private int idx = 0;
private void sc_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
idx = (int)(this.sc.HorizontalOffset / 260.0f);
}
另一方面頁面布局則是我們的designer的設計與我們在實現UI布局的經驗的結合。我們的頁面上有不少固定大小的元素,比如上面用來選擇自帶例子圖片的ScrollViewer控件。如果不做任何處理,在大屏手機上就會顯得比較小。所以我們在這里利用了Grid與Viewbox的組合:
<Grid x:Name="grid_Main" Opacity="0">
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="10">
…title行
</StackPanel>
<Viewbox Grid.Row="1" Width="10000" HorizontalAlignment="Center" Margin="-5000,20">
…ScrollViewer等圖片選擇控件
</Viewbox>
<StackPanel Grid.Row="2" Orientation="Vertical" VerticalAlignment="Center" Margin="0,10">
…footer行
</StackPanel>
</Grid>
用Grid設置title和footer為固定高度,而中間ScrollViewer等圖片選擇控件所占據的空間可以隨屏幕變化。加入Viewbox讓我們固定大小的控件可以在布局中自動縮放而不必費心費力地通過代碼來調整:
Wxga: 1080p:
是不是很方便呢?
小結
今天就先向大家分享這些心得,歡迎大家繼續關注和拍磚,讓我們共同進步。
我們的已經發布的應用和代碼可以在下面找到:
Windows Phone Store App link:
http://www.windowsphone.com/zh-cn/store/app/博客園-uap/500f08f0-5be8-4723-aff9-a397beee52fc
Windows Store App link:
http://apps.microsoft.com/windows/zh-cn/app/c76b99a0-9abd-4a4e-86f0-b29bfcc51059
GitHub open source link:
https://github.com/MS-UAP/cnblogs-UAP
MSDN Sample Code:
https://code.msdn.microsoft.com/CNBlogs-Client-Universal-9c9692d1