<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:blogChannel="http://backend.userland.com/blogChannelModule" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:betag="https://blogengine.io/schemas/tags">
  <channel>
    <title>Andrej Tozon's blog</title>
    <description>In the Attic</description>
    <link>http://www.tozon.info/blog/</link>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>BlogEngine.NET 3.3.6.0</generator>
    <language>en-GB</language>
    <blogChannel:blogRoll>http://www.tozon.info/blog/opml.axd</blogChannel:blogRoll>
    <blogChannel:blink>http://www.tozon.info/blog/syndication.axd</blogChannel:blink>
    <dc:creator>Andrej Tozon</dc:creator>
    <dc:title>Andrej Tozon's blog</dc:title>
    <geo:lat>0.000000</geo:lat>
    <geo:long>0.000000</geo:long>
    <item>
      <title>Text-To-Speech with Windows 10 IoT Core &amp; UWP on Raspberry Pi Part 2</title>
      <description>&lt;p&gt;In my &lt;a href="http://tozon.info/blog/post/2017/07/28/Text-To-Speech-with-Windows-10-Iot-Core-UWP-on-Raspberry-Pi" target="_blank"&gt;previous post&lt;/a&gt;, I've written about using Raspberry Pi running Windows 10 IoT Core for Text-To-Speech services for my smart home. As I've mentioned in that post, I have speakers in two floors wired to an amplifier, connected to a Raspberry Pi. The thing is that each of the speakers is wired to its own audio channel - ground floor speaker is wired to the left and 1st floor speaker is wired to the right channel. It may not be what you'd call a true stereo when listening to music, but it plays a big deal with speech running through the house. With such wiring, I can target the floor I want to convey the speech through, exclusively or with subtle mix, e.g. 100% volume to ground floor and only 10% to 1st floor (it's basically how audio balancing works). This basically lets me cover these use cases and more:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Want to call your children that are playing in their rooms upstairs, to lunch? Use 1st floor speaker.&lt;/li&gt;&lt;li&gt;Somebody at the door? Send the message to upstairs and ground floor speakers equally.&lt;/li&gt;&lt;li&gt;Late at night, kids are sleeping? Maybe use ground floor speakers at full and upstairs speakers at a minimum?&lt;/li&gt;&lt;li&gt;Etc...&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Scenarios are limitless. And the MediaPlayer class from my previous example offers just what I needed to implement this - audio balance. You can simply set the balance prior to playing your audio, like this:&lt;/p&gt;&lt;pre&gt;public async Task SayAsync(string text, double balance)&lt;br&gt;{&lt;br&gt;&lt;span style="font-weight: bold;"&gt;&amp;nbsp; &amp;nbsp; speechPlayer.AudioBalance = balance;&lt;/span&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; using (var stream = await speechSynthesizer.SynthesizeTextToStreamAsync(text))&lt;br&gt;&amp;nbsp; &amp;nbsp; {&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; speechPlayer.Source = MediaSource.CreateFromStream(stream, stream.ContentType);&lt;br&gt;&amp;nbsp; &amp;nbsp; }&lt;br&gt;&amp;nbsp; &amp;nbsp; speechPlayer.Play();&lt;br&gt;}&lt;/pre&gt;&lt;div&gt;This code is from my previous blog post, with additional parameter for setting the &lt;span style="font-style: italic;"&gt;AudioBalance &lt;/span&gt;property prior to playing the synthesized speech.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;h4&gt;Playing speech remotely&lt;/h4&gt;&lt;div&gt;Of course the real fun begins when you're able to control your audio player remotely, e.g. from an application or even web browser. To achieve this, I have put together a simple "web server" that runs as a background service on Windows 10 IoT Core. I've used the &lt;a href="https://github.com/ms-iot/samples/tree/develop/IoTBlockly/SimpleWebServer" target="_blank"&gt;SimpleWebServer from IoTBlockly code sample&lt;/a&gt; as a base for my own implementation of a "poor man's Web API server", just trying to simulate controllers, etc. I won't go into that code as &lt;span style="text-decoration-line: underline;"&gt;it's very hacky, absolutely not production ready, complete or even tested&lt;/span&gt;, but it appears to work OK for my current needs. Full source code I've used for this blog post is included in my &lt;a href="https://github.com/andrejt/IoT.Audio" target="_blank"&gt;sample project&lt;/a&gt;; I'm only listing the part that controls the speech here:&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;internal class SayController : Controller&lt;br&gt;{&lt;br&gt;&amp;nbsp; &amp;nbsp; private readonly SpeechService _speechService;
&lt;br&gt;&amp;nbsp; &amp;nbsp; public SayController(SpeechService speechService)&lt;br&gt;&amp;nbsp; &amp;nbsp; {&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; _speechService = speechService;&lt;br&gt;&amp;nbsp; &amp;nbsp; }
&lt;br&gt;&amp;nbsp; &amp;nbsp; public async Task&amp;lt;WebServerResponse&amp;gt; Get(string text, string floor)&lt;br&gt;&amp;nbsp; &amp;nbsp; {&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (string.IsNullOrEmpty(floor))
        {
            await _speechService.SayAsync(text, 0)
        }
        else if (floor.ToLower() == "up")
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; await _speechService.SayAsync(text, -1);&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; await _speechService.SayAsync(text, 1);&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return WebServerResponse.CreateOk("OK");&lt;br&gt;&amp;nbsp; &amp;nbsp; }&lt;br&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;The code is pretty much self explaining - the first parameter contains the text that should be spoken and the second parameter is the name of the floor the text should be spoken on ("up" sets the audio balance to the left channel and "down" to the right).&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;With such server set up on Raspberry Pi (the sample is set to listening on port 8085), it's easy for me to make my home say the synthesized text on a specific floor by simply calling its URL:&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;pre&gt;http://&amp;lt;IP&amp;gt;:8085/say?text=Hello&amp;amp;floor=up&lt;/pre&gt;&lt;p&gt;Sample source code for this post is &lt;a href="https://github.com/andrejt/IoT.Audio" target="_blank"&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;</description>
      <link>http://www.tozon.info/blog/post/2017/08/12/text-to-speech-with-windows-10-iot-core-and-uwp-on-raspberry-pi-part-2</link>
      <comments>http://www.tozon.info/blog/post/2017/08/12/text-to-speech-with-windows-10-iot-core-and-uwp-on-raspberry-pi-part-2#comment</comments>
      <guid>http://www.tozon.info/blog/post.aspx?id=2f5d6f2d-81bb-4eb9-b38f-05e1d8f4a4f4</guid>
      <pubDate>Sun, 13 Aug 2017 01:24:00 +0100</pubDate>
      <category>Development</category>
      <category>IoT</category>
      <category>SmartHome</category>
      <category>UWP</category>
      <category>Windows IoT Core</category>
      <dc:publisher>Andrej</dc:publisher>
      <pingback:server>http://www.tozon.info/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.tozon.info/blog/post.aspx?id=2f5d6f2d-81bb-4eb9-b38f-05e1d8f4a4f4</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.tozon.info/blog/trackback.axd?id=2f5d6f2d-81bb-4eb9-b38f-05e1d8f4a4f4</trackback:ping>
      <wfw:comment>http://www.tozon.info/blog/post/2017/08/12/text-to-speech-with-windows-10-iot-core-and-uwp-on-raspberry-pi-part-2#comment</wfw:comment>
      <wfw:commentRss>http://www.tozon.info/blog/syndication.axd?post=2f5d6f2d-81bb-4eb9-b38f-05e1d8f4a4f4</wfw:commentRss>
    </item>
    <item>
      <title>Text-To-Speech with Windows 10 Iot Core &amp; UWP on Raspberry Pi</title>
      <description>&lt;p&gt;One of the best features I’ve found in using &lt;a href="https://developer.microsoft.com/en-us/windows/iot" target="_blank"&gt;Windows 10 IoT Core&lt;/a&gt; on my home &lt;a href="http://raspberrypi.org/" target="_blank"&gt;Raspberry Pi&lt;/a&gt; (which is a small, inexpensive piece of hardware) is, it can do voice synthesis very well (i.e. it can “speak”). While Windows developers could develop applications with this same functionality for quite a long time, I was still overwhelmed when I saw such small device say anything I ordered it to. It currently may not support all the options and voices older platforms do, but it’s more than enough for scenarios like home automation, notifications, etc. The fact that &lt;a href="https://developer.microsoft.com/en-us/windows/iot" target="_blank"&gt;Windows 10 IoT Core&lt;/a&gt; even supports &lt;a href="https://en.wikipedia.org/wiki/Microsoft_Cortana" target="_blank"&gt;Cortana&lt;/a&gt; means Microsoft has big plans for IoT Core and voice recognition an synthesis.&lt;/p&gt;&lt;p&gt;When building my house a few years ago, I’ve put in a pair of audio cables going to both of two floors, to be later able to install two small (but powerful) speakers into a central ceiling of each floor. A private little whole house audio/ambient music system, if you will. I’ve plugged them into an amplifier installed in my utility room and connected to a Raspberry Pi running Windows IoT Core. [Sure, it’s all possible and doable wireless as well, but I’d still trust wired installations over wireless, so if given a chance, I’d pick wires anytime].&lt;/p&gt;&lt;h4&gt;Windows 10 IoT Core&lt;/h4&gt;&lt;p align="left"&gt;So Why &lt;a href="https://developer.microsoft.com/en-us/windows/iot" target="_blank"&gt;Windows IoT Core&lt;/a&gt;? Just because it could run Windows Universal apps (where speech synthesis was supported) and I’ve already known UWP very well and have worked with the API several times in the past - it was a perfect fit.&lt;/p&gt;&lt;p&gt;Having wired my whole house audio system to &lt;a href="http://raspberrypi.org/" target="_blank"&gt;Raspberry Pi&lt;/a&gt; gave me quite a few gains:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;telling time – my house reports the time every hour, on the hour. I’ve got quite used to this in the past two years, as it’s quite useful to keep track of time, especially when you’re busy; it’s really nonintrusive.&lt;/li&gt;&lt;li&gt;status notifications – I have my whole house wired and interconnected with my smart home installation so anything important I don’t want to miss (like low water level, motion detection, even weather report) can be reported audibly, with detailed spoken report;&lt;/li&gt;&lt;li&gt;door bell – I also have my front door bell wired to the Raspberry Pi. It can play any sound or speech when somebody rings a bell;&lt;/li&gt;&lt;li&gt;calendar – every morning, shortly before it’s time to go for work or school, I can hear a quick list of activities for that day – kids’ school schedule, any scheduled meetings, after-school activities, … along with weather forecast;&lt;/li&gt;&lt;li&gt;background music – not directly speech related, but Raspberry Pi with Windows IoT is also a great music player. Scheduled in the morning for when it’s time to get up, it quietly starts playing the preset internet radio station.&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;These are just a few examples of how I’m finding &lt;a href="https://developer.microsoft.com/en-us/windows/iot" target="_blank"&gt;Windows 10 IoT Core&lt;/a&gt; speech capabilities on &lt;a href="http://raspberrypi.org/" target="_blank"&gt;Raspberry Pi&lt;/a&gt; useful and I’m regularly getting ideas for more. For this blog post, however, , I’d like to focus on showing how easy it is to implement the first case from the above list – telling time – using Visual Studio to create a background Universal Windows Application and deploy it to &lt;a href="http://raspberrypi.org/" target="_blank"&gt;Raspberry Pi&lt;/a&gt; running &lt;a href="https://developer.microsoft.com/en-us/windows/iot" target="_blank"&gt;Windows 10 IoT Core&lt;/a&gt;.&lt;/p&gt;&lt;h4&gt;Development&lt;/h4&gt;&lt;p&gt;What I’ll be using:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Visual Studio 2017 – see &lt;a href="https://www.visualstudio.com/" target="_blank"&gt;here&lt;/a&gt; for downloads,&lt;/li&gt;&lt;li&gt;Raspberry Pi 3 with latest Windows 10 IoT Core installed – see &lt;a href="http://dev.windows.com/iot" target="_blank"&gt;here&lt;/a&gt; for download and instructions on how to install it.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I’ll also be using the Background Application IoT Visual Studio template. To install IoT Core templates, install Windows IoT Core Projects extension using the Extensions and Updates menu option:&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_17.png"&gt;&lt;img width="644" height="403" title="image" style="display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_15.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;After that (possibly restart Visual Studio – installing may also take some time for additional downloads), create a new IoT project&amp;nbsp; (File | New | Project…):&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_18.png"&gt;&lt;img width="644" height="365" title="image" style="display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_16.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Select the Windows IoT Core template group on the left and pick the only template in that group – &lt;em&gt;Background Application (IoT)&lt;/em&gt;. Enter a project name and Click OK to create the project.&lt;/p&gt;&lt;p&gt;After project is created, add the &lt;em&gt;BackgroundTaskDeferral&lt;/em&gt; line to prevent background service exiting too early:&lt;/p&gt;&lt;pre&gt;private BackgroundTaskDeferral deferral;
public void Run(IBackgroundTaskInstance taskInstance)
 {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; deferral = taskInstance.GetDeferral();&lt;br&gt;}&lt;/pre&gt;&lt;p&gt;Then add the following class:&lt;/p&gt;&lt;pre&gt;internal class SpeechService
{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly SpeechSynthesizer speechSynthesizer;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public SpeechService()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; speechSynthesizer = CreateSpeechSynthesizer();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static SpeechSynthesizer CreateSpeechSynthesizer()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;}&lt;/pre&gt;
&lt;p&gt;This is just an internal class that currently does nothing but trying to create a class called SpeechSynthesizer.&lt;/p&gt;&lt;h4&gt;SpeechSynthesizer&lt;/h4&gt;&lt;p&gt;The &lt;a href="https://docs.microsoft.com/en-us/uwp/api/Windows.Media.SpeechSynthesis.SpeechSynthesizer" target="_blank"&gt;SpeechSynthesizer&lt;/a&gt; class has been around for quite a while and in various implementations across different frameworks. I’ll use the one what we’ve currently got on Windows 10 / UWP, where it sits under the &lt;a href="https://docs.microsoft.com/en-us/uwp/api/windows.media.speechsynthesis" target="_blank"&gt;Windows.Media.SpeechSynthesis namespace&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the above code, something’s missing – the code that actually creates the SpeechSynthesizer object. Turns out it’s not very difficult to to that:&lt;/p&gt;&lt;pre&gt;var synthesizer = new SpeechSynthesizer();
return synthesizer;&lt;/pre&gt;&lt;p&gt;But there’s more… First, you can give it a voice you like. To get the list of voices your platform supports, inspect the &lt;em&gt;SpeechSynthesizer.AllVoices&lt;/em&gt; static property. To enumerate through all the voices you can use this:&lt;/p&gt;&lt;pre&gt;foreach (var voice in SpeechSynthesizer.AllVoices)
{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Debug.WriteLine($"{voice.DisplayName} ({voice.Language}), {voice.Gender}");
}&lt;/pre&gt;&lt;p&gt;The above code would vary depending on which language(s) you have installed. For example, English language only would give you:&lt;/p&gt;Microsoft David Mobile (en-US), Male&lt;br&gt;Microsoft Zira Mobile (en-US), Female&lt;br&gt;Microsoft Mark Mobile (en-US), Male&lt;p&gt;Also note that not all languages support speech synthesis. To add one or check what’s supported, go to &lt;em&gt;Region &amp;amp; Language&lt;/em&gt; settings and click on the language you want to add speech support for. Example for German:&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_19.png"&gt;&lt;img width="526" height="484" title="image" style="display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_17.png" border="0"&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_20.png"&gt;&lt;img width="441" height="484" title="image" style="display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_18.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;As you can see, speech data for German takes about 111 MB to download. Once it is installed, it’ll appear on the list.&lt;/p&gt;&lt;p&gt;If you don’t like the default voice, you can either pick another one based on its ID or one of its attributes like gender or language; the following code snippet pick the first available female voice or falls back to the default voice if no female voices were found:&lt;/p&gt;&lt;pre&gt;var voice = SpeechSynthesizer.AllVoices.SingleOrDefault(i =&amp;gt; i.Gender == VoiceGender.Female) ?? SpeechSynthesizer.DefaultVoice;&lt;/pre&gt;&lt;p&gt;The DefaultVoice static property will give you the default voice for the current platform settings in case your query fails.&lt;/p&gt;&lt;p&gt;When you have your voice selected, assign it to SpeechSynthesizer:&lt;/p&gt;&lt;pre&gt;synthesizer.Voice = voice;&lt;/pre&gt;
&lt;h4&gt;What’s Coming with Windows 10 Fall Creators update&lt;/h4&gt;&lt;p&gt;There are additional options you can set to SpeechSynthesizer. Adding to existing &lt;em&gt;IncludeSentenceBoundaryMetadata&lt;/em&gt; and &lt;em&gt;IncludeWordBoundaryMetadata&lt;/em&gt; properties, the forthcoming Windows 10 Fall Creators update is looking to add some new interesting ones: &lt;em&gt;AudioPitch&lt;/em&gt; will allow altering the pitch of synthesized utterances (change to higher and lower tones), &lt;em&gt;AudioVolume&lt;/em&gt; will be used to individually control the volume and &lt;em&gt;SpeakingRate&lt;/em&gt; to alter the tempo of spoken utterances. To try those now, you need to be on latest &lt;a href="https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewiso" target="_blank"&gt;Windows 10 Insider Preview&lt;/a&gt; (Windows 10 IoT Core version is available from &lt;a href="https://www.microsoft.com/en-us/software-download/windowsiot" target="_blank"&gt;here&lt;/a&gt;) and at least Windows SDK build 16225.&lt;/p&gt;&lt;p&gt;I’m running the latest stable Windows 10 IoT Core version on my home Raspberry Pi so for now I’ll stick to using the latest stable version of SDK (Windows 10 Creators update or build 15063).&lt;/p&gt;&lt;p&gt;To continue with the code, this is how I’ve implemented the &lt;em&gt;CreateSpeechSynthesizer&lt;/em&gt; method:&lt;/p&gt;&lt;pre&gt;private static SpeechSynthesizer CreateSpeechSynthesizer()
{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var synthesizer = new SpeechSynthesizer();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var voice = SpeechSynthesizer.AllVoices.SingleOrDefault(i =&amp;gt; i.Gender == VoiceGender.Female) ?? SpeechSynthesizer.DefaultVoice;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; synthesizer.Voice = voice;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return synthesizer;
}&lt;/pre&gt;&lt;h4&gt;Speech&lt;/h4&gt;&lt;p&gt;It only takes a few lines to actually produce something with SpeechSynthesizer: add a MediaPlayer to the SpeechService class, along with the new SayAsync method:&lt;/p&gt;&lt;pre&gt;&lt;em&gt;private readonly SpeechSynthesizer speechSynthesizer;&lt;br&gt;&lt;/em&gt;private readonly MediaPlayer speechPlayer;
&lt;br&gt;&lt;em&gt;public SpeechService()&lt;br&gt;&lt;/em&gt;&lt;em&gt;{&lt;br&gt;&lt;/em&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; speechSynthesizer = CreateSpeechSynthesizer();&lt;br&gt;&lt;/em&gt;&amp;nbsp;&amp;nbsp; speechPlayer = new MediaPlayer();&lt;br&gt;&lt;em&gt;}
&lt;br&gt;&lt;/em&gt;public async Task SayAsync(string text)&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (var stream = await speechSynthesizer.SynthesizeTextToStreamAsync(text))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; speechPlayer.Source = MediaSource.CreateFromStream(stream, stream.ContentType);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; speechPlayer.Play();&lt;br&gt;}&lt;/pre&gt;&lt;p&gt;Let’s take a closer look to the SayAsync method. The SynthesizeTextToStreamAsync method does the actual speech synthesis - it turns text to spoken audio stream. That stream is assigned to MediaPlayer’s Source property and played using the Play method.&lt;/p&gt;&lt;p&gt;Easy.&lt;/p&gt;&lt;h4&gt;Ready to tell time&lt;/h4&gt;&lt;p&gt;We need another method for telling time, here’s an example:&lt;/p&gt;&lt;pre&gt;public async Task SayTime()
{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var now = DateTime.Now;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var hour = now.Hour;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; string timeOfDay;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (hour &amp;lt;= 12)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; timeOfDay = "morning";&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (hour &amp;lt;= 17)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; timeOfDay = "afternoon";&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; timeOfDay = "evening";&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (hour &amp;gt; 12)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hour -= 12;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (now.Minute == 0)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; await SayAsync($"Good {timeOfDay}, it's {hour} o'clock.");&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; await SayAsync($"Good {timeOfDay}, it's {hour} {now.Minute}.");&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
}&lt;/pre&gt;

&lt;p&gt;And the last thing to add is a way to invoke the above method on proper intervals. This is my full StartupTask class for reference:&lt;/p&gt;&lt;pre&gt;public sealed class StartupTask : IBackgroundTask
{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private BackgroundTaskDeferral deferral;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Timer clockTimer;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private SpeechService speechService;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Run(IBackgroundTaskInstance taskInstance)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; deferral = taskInstance.GetDeferral();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; speechService = new SpeechService();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var timeToFullHour = GetTimeSpanToNextFullHour();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; clockTimer = new Timer(OnClock, null, timeToFullHour, TimeSpan.FromHours(1));&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; speechService.SayTime();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static TimeSpan GetTimeSpanToNextFullHour()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var now = DateTime.Now;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var nextHour = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0).AddHours(1);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return nextHour - now;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private async void OnClock(object state)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; await speechService.SayTime();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
}&lt;/pre&gt;





&lt;p&gt;Timer will fire every hour and your device will tell the time. Feel free to experiment with other shorter time spans to get hear it tell the time more often.&lt;/p&gt;&lt;h4&gt;Deploying to a device&lt;/h4&gt;&lt;p&gt;There are many ways to deploy your app to an IoT Core device, but I usually find it easiest to deploy from within Visual Studio.&lt;br&gt;
&lt;/p&gt;&lt;p&gt;Open project’s Property pages and select &lt;em&gt;Debug&lt;/em&gt; page. Find the &lt;em&gt;Start options&lt;/em&gt; section, select &lt;em&gt;Remote Machine&lt;/em&gt; as &lt;em&gt;Target Device&lt;/em&gt; and hit the &lt;em&gt;Find&lt;/em&gt; button. If your device is online, it will be listed in the &lt;em&gt;Auto Detected&lt;/em&gt;&amp;nbsp; list. Select it, leaving &lt;em&gt;Authentication Mode&lt;/em&gt; to &lt;em&gt;Universal&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_21.png"&gt;&lt;img width="644" height="129" title="image" style="display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_19.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Select Debug | Start Without Debugging or simply press&amp;nbsp; CTRL+F5 to deploy application without debugger attached. With speakers or headphones attached to the device, you should hear the time immediately after application is successfully deployed.&lt;/p&gt;&lt;p&gt;You can also check the application status on the Windows Device Application Portal:&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_22.png"&gt;&lt;img width="644" height="190" title="image" style="display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_20.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Hit the switch in the &lt;em&gt;Startup&lt;/em&gt; column to &lt;em&gt;On&lt;/em&gt; if you want the background application automatically start whenever device boots up.&lt;/p&gt;&lt;h4&gt;Audio issues&lt;/h4&gt;&lt;p&gt;When I first tried playing audio through Raspberry Pi, there were annoying clicks playing before and after voice was spoken. I’ve solved that with a cheap, 10$ USB audio card. Plus I’ve gained a mic input.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_23.png"&gt;&lt;img width="364" height="484" title="image" style="display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_21.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;h4&gt;Wrap up&lt;/h4&gt;&lt;p&gt;We’ve created a small background app that literally tells time, running on a number of small devices that support Windows 10 IoT Core. In future posts, I’ll add additional features, some of them I’ve introduced in the beginning of this blog post.&lt;/p&gt;&lt;p&gt;Full source code from this post is available on &lt;a href="https://github.com/andrejt/IoT.Audio" target="_blank"&gt;github&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;You can also read part 2 of this post &lt;a href="http://tozon.info/blog/post/2017/08/12/text-to-speech-with-windows-10-iot-core-and-uwp-on-raspberry-pi-part-2" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;</description>
      <link>http://www.tozon.info/blog/post/2017/07/28/Text-To-Speech-with-Windows-10-Iot-Core-UWP-on-Raspberry-Pi</link>
      <comments>http://www.tozon.info/blog/post/2017/07/28/Text-To-Speech-with-Windows-10-Iot-Core-UWP-on-Raspberry-Pi#comment</comments>
      <guid>http://www.tozon.info/blog/post.aspx?id=a92513fc-4eb3-4903-bda6-ef3de0300758</guid>
      <pubDate>Sat, 29 Jul 2017 00:39:00 +0100</pubDate>
      <category>Development</category>
      <category>IoT</category>
      <category>SmartHome</category>
      <category>Windows IoT Core</category>
      <dc:publisher>Andrej</dc:publisher>
      <pingback:server>http://www.tozon.info/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.tozon.info/blog/post.aspx?id=a92513fc-4eb3-4903-bda6-ef3de0300758</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.tozon.info/blog/trackback.axd?id=a92513fc-4eb3-4903-bda6-ef3de0300758</trackback:ping>
      <wfw:comment>http://www.tozon.info/blog/post/2017/07/28/Text-To-Speech-with-Windows-10-Iot-Core-UWP-on-Raspberry-Pi#comment</wfw:comment>
      <wfw:commentRss>http://www.tozon.info/blog/syndication.axd?post=a92513fc-4eb3-4903-bda6-ef3de0300758</wfw:commentRss>
    </item>
    <item>
      <title>Microsoft Cognitive Services - Computer Vision</title>
      <description>&lt;p&gt;Similar to Face API, Computer Vision API service deals with image recognition, though on a bit wider scale. Computer Vision Cognitive Service can recognize different things on a photo and tries to describe what's going on - with a formed statement that describes the whole photo, a list of tags,&amp;nbsp; describing objects and living things on it, or, similar to Face API, detect faces. It can event do basic text recognition (printed or handwritten).&lt;/p&gt;
&lt;h4&gt;Create a Computer Vision service resource on Azure&lt;/h4&gt;
&lt;p&gt;To start experimenting with Computer Vision API, you have to first add the service on Azure dashboard. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=Untitled.png"&gt;&lt;img width="644" height="412" title="Untitled" style="display: inline; background-image: none;" alt="Untitled" src="http://www.tozon.info/blog/image.axd?picture=Untitled_thumb.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The steps are almost identical to what I've described in &lt;a href="http://tozon.info/blog/post/2017/07/08/Microsoft_Cognitive_Service_-_Starting_with_Face_API" target="_blank"&gt;my Face API blog post&lt;/a&gt;, so I'm not going to describe all the steps; the only thing worth of a mention is the pricing: there are currently two tiers: the free tier (F0) is free and allows for 20 API calls per minute and 5.000 calls per month, while the standard tier (S1) offers up to 10 calls per second. Check the &lt;a style="background-color: rgb(246, 246, 246);" href="https://azure.microsoft.com/en-us/pricing/details/cognitive-services/computer-vision/" target="_blank"&gt;official pricing page here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hit the Create button and wait for service to be created and deployed (should take under a minute). You get a new pair of key to access the service; the keys are, again, available through the&amp;nbsp; Resource Management -&amp;gt; Keys section.&lt;/p&gt;
&lt;h4&gt;Trying it out&lt;/h4&gt;
&lt;p&gt;To try out the service yourself, you can either try the &lt;a href="https://westus.dev.cognitive.microsoft.com/docs/services/56f91f2d778daf23d8ec6739/operations/56f91f2e778daf14a499e1fa" target="_blank"&gt;official documentation page with ready-to-test API testing console&lt;/a&gt;, or you can download a C# SDK from &lt;a href="https://www.nuget.org/packages/Microsoft.ProjectOxford.Vision" target="_blank"&gt;nuget&lt;/a&gt; (source code with samples for &lt;a href="https://github.com/Microsoft/Cognitive-vision-windows" target="_blank"&gt;UWP&lt;/a&gt;, &lt;a href="https://github.com/Microsoft/Cognitive-vision-android" target="_blank"&gt;Android&lt;/a&gt; &amp;amp; &lt;a href="https://github.com/DanilaVladi/Microsoft-Cognitive-Services-Swift-SDK" target="_blank"&gt;iOS (Swift)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also, source code used in this article is available from my &lt;a href="https://github.com/andrejt/CognitiveServicesPlayground" target="_blank"&gt;Cognitive Services playground app repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For this blog post, I'll be using the aforementioned &lt;a href="https://www.nuget.org/packages/Microsoft.ProjectOxford.Vision" target="_blank"&gt;C# SDK&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When using the SDK, The most universal API call for Computer Vision API is the &lt;span style="font-style: italic;"&gt;AnalyzeImageAsync&lt;/span&gt;:&lt;/p&gt;
&lt;pre&gt;var result = await visionClient.AnalyzeImageAsync(stream, new[] {VisualFeature.Description, VisualFeature.Categories, VisualFeature.Faces, VisualFeature.Tags});&lt;br&gt;var detectedFaces = result?.Faces;&lt;br&gt;var tags = result?.Tags;&lt;br&gt;var description = result?.Description?.Captions?.FirstOrDefault().Text;
var categories = result?.Categories;&lt;/pre&gt;
&lt;p&gt;Depending on &lt;span style="font-style: italic;"&gt;visualFeatures&lt;/span&gt; parameter, the &lt;span style="font-style: italic;"&gt;AnalyzeImageAsync &lt;/span&gt;can return one or more types of information (some of them also separately available by calling other methods):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Description: one on more sentences, describing the content of the image, described in plain English,&lt;/li&gt;
&lt;li&gt;Faces: a list of detected faces; unlike the Face API, the Vision API returns age and gender for each of the faces,&lt;/li&gt;
&lt;li&gt;Tags: a list of tags, related to image content,&lt;/li&gt;
&lt;ul&gt;
&lt;!--StartFragment--&gt;
&lt;/ul&gt;
&lt;li&gt;ImageType: whether the image is a clip art or a line drawing,&lt;/li&gt;
&lt;li&gt;Color: the dominant colors and whether it's a black and white image,&lt;/li&gt;
&lt;li&gt;Adult: indicates whether the image contains adult content (with confidentiality scores),&lt;/li&gt;
&lt;ul&gt;
&lt;!--EndFragment--&gt;&lt;/ul&gt;
&lt;li&gt;Categories: one or more categories from the set of 86 two-level concepts, according to the following taxonomy:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/cognitive-services/computer-vision/category-taxonomy" target="_blank"&gt;&lt;img width="640" height="459" src="https://docs.microsoft.com/en-us/azure/cognitive-services/computer-vision/images/analyze_categories.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;span style="font-style: italic;"&gt;details&lt;/span&gt; parameter lets you specify a domain-specific models you want to test against. Currently, two models are supported: landmarks and celebrities. You can call the &lt;span style="font-style: italic;"&gt;ListModelsAsync&lt;/span&gt; method to get all models that are supported, along with categories they belong to.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_16.png"&gt;&lt;img width="479" height="484" title="image" style="display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_14.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another fun feature of Vision API is recognizing text in image, either printed or handwritten.&lt;/p&gt;
&lt;pre&gt;var result = await visionClient.RecognizeTextAsync(stream);&lt;br&gt;Region = result?.Regions?.FirstOrDefault();&lt;br&gt;Words = Region?.Lines?.FirstOrDefault()?.Words;&lt;/pre&gt;
&lt;div&gt;The &lt;span style="font-style: italic;"&gt;RecognizeTextAsync &lt;/span&gt;method will return a list of regions where printed text was detected, along with general image text angle and orientation. Each region can contain multiple lines of (presumably related) text, and each line object will contain a list of detected words. Region, Line and Word will also return coordinates, pointing to a region within image where that piece of information was detected.&lt;/div&gt;
&lt;div&gt;Also worth noting is the &lt;em&gt;RecognizeTextAsync&lt;/em&gt; takes additional parameters:&lt;/div&gt;
&lt;div&gt;&lt;em&gt;language&lt;/em&gt; – the language to be detected in the image (default is “unk” – unknown),&lt;/div&gt;
&lt;div&gt;&lt;em&gt;detectOrientation&lt;/em&gt; – detects the image orientation based on orientation of detected text (default is true).&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;/div&gt;
&lt;div&gt;Source code and sample app for this blog post is available on &lt;a href="https://github.com/andrejt/CognitiveServicesPlayground" target="_blank"&gt;github&lt;/a&gt;.&lt;/div&gt;</description>
      <link>http://www.tozon.info/blog/post/2017/07/18/microsoft-cognitive-services-computer-vision</link>
      <comments>http://www.tozon.info/blog/post/2017/07/18/microsoft-cognitive-services-computer-vision#comment</comments>
      <guid>http://www.tozon.info/blog/post.aspx?id=ffa3415d-15fb-4bde-9625-ce8d38d15219</guid>
      <pubDate>Wed, 19 Jul 2017 01:44:00 +0100</pubDate>
      <category>Development</category>
      <category>Microsoft Cognitive Services</category>
      <dc:publisher>Andrej</dc:publisher>
      <pingback:server>http://www.tozon.info/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.tozon.info/blog/post.aspx?id=ffa3415d-15fb-4bde-9625-ce8d38d15219</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.tozon.info/blog/trackback.axd?id=ffa3415d-15fb-4bde-9625-ce8d38d15219</trackback:ping>
      <wfw:comment>http://www.tozon.info/blog/post/2017/07/18/microsoft-cognitive-services-computer-vision#comment</wfw:comment>
      <wfw:commentRss>http://www.tozon.info/blog/syndication.axd?post=ffa3415d-15fb-4bde-9625-ce8d38d15219</wfw:commentRss>
    </item>
    <item>
      <title>Microsoft Cognitive Services - playground app</title>
      <description>&lt;p&gt;I've just published my Cognitive Services sample app to &lt;a href="https://github.com/andrejt/CognitiveServicesPlayground" target="_blank"&gt;github&lt;/a&gt;. Currently it's limited to Face API service, but I'll work on expanding it to cover other services as well.&lt;/p&gt;&lt;p&gt;The Microsoft Cognitive Service Playground app aims to support:&lt;/p&gt;&lt;ul&gt;&lt;li&gt; managing person groups,&lt;/li&gt;&lt;li&gt;managing persons,&lt;/li&gt;&lt;li&gt;associating faces with persons,&lt;/li&gt;&lt;li&gt;training person groups,&lt;/li&gt;&lt;li&gt;detecting faces on photos,&lt;/li&gt;&lt;li&gt;identifying faces.&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Basic tutorial&lt;/h4&gt;&lt;p&gt;1. Download/clone the solution, open it in Visual Studio 2017 and run.&lt;/p&gt;&lt;p&gt;2. Enter the key in the Face API Key text box. If you don't already have a Face API access key, read &lt;a href="http://tozon.info/blog/post/2017/07/08/Microsoft_Cognitive_Service_-_Starting_with_Face_API" target="_blank"&gt;this blog post&lt;/a&gt; on how to get it.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_3.png"&gt;&lt;img width="644" height="87" title="image" style="display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_1.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;3. Click the &lt;span style="font-style: italic;"&gt;Apply&lt;/span&gt; button.&lt;/p&gt;&lt;p&gt;4. If the key is correct, you will be asked to persist the key for future use. Click Yes if you want it to be stored in application local data folder - it will be read back every time application is started (note: the key is stored in plain text, not encrypted).&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_4.png"&gt;&lt;img width="640" height="198" title="image" style="border: 0px currentcolor; border-image: none; display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_2.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;5. Click the &lt;span style="font-style: italic;"&gt;Add group&lt;/span&gt; button.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_5.png"&gt;&lt;img width="244" height="131" title="image" style="display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_3.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;6. Enter the group name and click &lt;span style="font-style: italic;"&gt;Add&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_6.png"&gt;&lt;img width="244" height="96" title="image" style="margin: 0px; display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_4.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;7. Select the newly created group and start adding persons. &lt;/p&gt;&lt;p&gt;8. Click the &lt;span style="font-style: italic;"&gt;Add person&lt;/span&gt; button.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_7.png"&gt;&lt;img width="244" height="101" title="image" style="margin: 0px; display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_5.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;9. Enter person's name and click &lt;span style="font-style: italic;"&gt;Add&lt;/span&gt;. The person will be added to the selected group.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_8.png"&gt;&lt;img width="244" height="113" title="image" style="margin: 0px; display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_6.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;10. Repeat steps 8 and 9 to add more persons in the same group.&lt;/p&gt;&lt;p&gt;11. Click the &lt;span style="font-style: italic;"&gt;Open image&lt;/span&gt; button and pick an image with one or more faces on it.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_9.png"&gt;&lt;img width="644" height="313" title="image" style="display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_7.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;12. The photo should be displayed and if any faces were detected, they should appear framed in rectangles. If not, try with different photo.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_10.png"&gt;&lt;img width="244" height="144" title="image" style="margin: 0px; display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_8.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;13. Select a person from the list and click on the rectangle around the face that belongs to that person. A context menu should appear.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_11.png"&gt;&lt;img width="244" height="89" title="image" style="margin: 0px; display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_9.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;14. Select the &lt;span style="font-style: italic;"&gt;Add this face to selected person&lt;/span&gt; option. The face is now associated with selected person.&lt;/p&gt;&lt;p&gt;15. Repeat steps 13 and 14 for different photos and different persons. Try associating multiple faces to every single person.&lt;/p&gt;&lt;p&gt;16. Click the &lt;span style="font-style: italic;"&gt;Train group&lt;/span&gt; button. Training status should appear. Wait for the status to change to &lt;span style="font-style: italic;"&gt;Succeeded&lt;/span&gt;. Your group is trained!&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_12.png"&gt;&lt;img width="244" height="66" title="image" style="margin: 0px; display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_10.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;17. Open a new photo, preferably one you haven't use before for training, but featuring a face that belongs to one of the persons in the group. Ensure the face is detected (the rectangle is drawn around it).&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_13.png"&gt;&lt;img width="244" height="219" title="image" style="margin: 0px; display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_11.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;18. Click on the rectangle and select &lt;span style="font-style: italic;"&gt;Identify this face&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_14.png"&gt;&lt;img width="244" height="144" title="image" style="margin: 0px; display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_12.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;19. With any luck (and the power of AI), the rectangle will get the proper name tag. Previously unknown face has just got a name attached to it!&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tozon.info/blog/image.axd?picture=image_15.png"&gt;&lt;img width="244" height="211" title="image" style="margin: 0px; display: inline; background-image: none;" alt="image" src="http://www.tozon.info/blog/image.axd?picture=image_thumb_13.png" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;20. Enjoy experimenting with different photos and different faces ;)&lt;/p&gt;&lt;p&gt;21. Revisit my older blog posts on the subject (&lt;a href="http://www.tozon.info/blog/post/2017/07/11/microsoft-cognitive-services-face-identification" target="_blank"&gt;here&lt;/a&gt; and &lt;a href="http://www.tozon.info/blog/post/2017/07/11/microsoft-cognitive-services-face-identification" target="_blank"&gt;here&lt;/a&gt;).&lt;/p&gt;</description>
      <link>http://www.tozon.info/blog/post/2017/07/14/microsoft-cognitive-services-playground-app</link>
      <comments>http://www.tozon.info/blog/post/2017/07/14/microsoft-cognitive-services-playground-app#comment</comments>
      <guid>http://www.tozon.info/blog/post.aspx?id=0c25236a-66d3-4d49-b05a-aa7b0de6303e</guid>
      <pubDate>Fri, 14 Jul 2017 23:17:00 +0100</pubDate>
      <category>Development</category>
      <category>Microsoft Cognitive Services</category>
      <dc:publisher>Andrej</dc:publisher>
      <pingback:server>http://www.tozon.info/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.tozon.info/blog/post.aspx?id=0c25236a-66d3-4d49-b05a-aa7b0de6303e</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.tozon.info/blog/trackback.axd?id=0c25236a-66d3-4d49-b05a-aa7b0de6303e</trackback:ping>
      <wfw:comment>http://www.tozon.info/blog/post/2017/07/14/microsoft-cognitive-services-playground-app#comment</wfw:comment>
      <wfw:commentRss>http://www.tozon.info/blog/syndication.axd?post=0c25236a-66d3-4d49-b05a-aa7b0de6303e</wfw:commentRss>
    </item>
    <item>
      <title>Microsoft Cognitive Services - Face identification</title>
      <description>&lt;p&gt;In today's Cognitive Services post, things are going to get a bit more interesting - we're moving from face detection to face identification. The difference is that we're not only going to detect there is a face (or more faces) present on a photo, but actually identify the person that face belongs to. But to do that, we need to teach the AI about people we'd like to keep track of. Even a computer can't identify someone it has never "seen" and has no information of how they look like.&lt;/p&gt;&lt;p&gt;The Face API identification works on a principle of groups - you create a group of people, attach one ore more faces to each group member, to finally be able to find out if the face on your new photo belongs to any member of that group. &lt;span style="font-style: italic;"&gt;[The alternative to groups are face lists, but in I'll stick with groups for now.]&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The Face API supports everything you need for managing groups, people and their faces. Here I'm expanding my Universal Windows demo application I've started building in &lt;a href="http://www.tozon.info/blog/post/2017/07/09/microsoft-cognitive-services-face-api-sdks" target="_blank"&gt;my previous post&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Creating a person group with C# SDK is simple:&lt;/p&gt;&lt;pre&gt;await client.CreatePersonGroupAsync(Guid.NewGuid().ToString(), "My family");
&lt;/pre&gt;&lt;div&gt;CreatePersonGroupAsync method takes a group ID for first parameter (easiest to use is to provide a GUID if you don't have other preferences or requirements), while the second name is a friendly name of the group that can be displayed throughout your app. There's a third - optional - parameter that takes any custom data you want to be associated with the group.&lt;/div&gt;&lt;div&gt;&lt;br&gt;&lt;/div&gt;&lt;div&gt;Once you've created one or more group, you can retrieve them using the&amp;nbsp;ListPersonGroupsAsync method:&lt;/div&gt;&lt;pre&gt;var personGroups = await client.ListPersonGroupsAsync();&lt;/pre&gt;&lt;p&gt;You can start adding people to your group by calling the&amp;nbsp;CreatePersonAsync, which is very similar to the above CreatePersonGroupAsync:&lt;/p&gt;&lt;pre&gt;var result = await client.CreatePersonAsync(personGroupId, "Andrej");&lt;/pre&gt;&lt;p&gt;The first parameter is the same personGroupId (GUID) I've used with the above method and identifies the person group. The second parameter is the name of the person you're adding. Again, there's a third parameter for optional user data if you want some additional data to associate with that person. The return result object contains a GUID of added person.&lt;/p&gt;&lt;p&gt;And again, you can now list all the persons in a particular group by calling the&amp;nbsp;ListPersonsAsync method:&lt;/p&gt;&lt;pre&gt;var persons = await client.ListPersonsAsync(personGroupId);&lt;/pre&gt;&lt;p&gt;A quick note here: both ListPersonGroupsAsync and ListPersonsAsync support paging to limit the returned result set.&lt;/p&gt;&lt;p&gt;Once you've added a few persons in a person group, it's time to give those persons faces.&lt;/p&gt;&lt;p&gt;Prepare a few photos of each person and start adding their faces. It's easier to use photos with single person on it to avoid one extra step of selecting particular face on the photo to be associated with a person. If only one face is detected on a photo, that one face will be added to the selected person.&lt;/p&gt;&lt;pre&gt;var file = await fileOpenPicker.PickSingleFileAsync();&lt;br&gt;using (var stream = await file.OpenStreamForReadAsync())&lt;br&gt;{&lt;br&gt;&amp;nbsp; &amp;nbsp; var result = await client.AddPersonFaceAsync(personGroupId, personId, stream);&lt;br&gt;}&lt;/pre&gt;&lt;p&gt;It takes just a personGroupId, personId and a photo file stream for AddPersonFaceAsync method to add a face to a person (personId) in a person group (personGroupId). There are two more parameters though - userData is again used for providing additional data to that face, while the last parameter - targetFace - takes a rectangle with pixel coordinates on the photo that bounds the face you want to add. Also, instead of uploading a photo stream you can use a method overload taking a valid URL that returns a photo containing a person's face.&lt;br&gt;The returned result of the above method will return the ID of persisted face that was just associated with a person.&lt;/p&gt;&lt;p&gt;To check how many faces are associated with specific person, simply call the GetPersonAsync method:&lt;/p&gt;&lt;pre&gt;var person = await client.GetPersonAsync(personGroupId, personId);&lt;/pre&gt;&lt;p&gt;The returned person object will contain person's ID, name, user data and an array of persisted faces' IDs.&lt;/p&gt;&lt;p&gt;I've found that adding around 3 faces for a person is good enough for successfully identifying people in various conditions. However, I'd recommend adding faces in different conditions for improved accuracy (summer/winter, different hair styles, lightning conditions, ...) Also, I believe adding a few faces every now and then would help in keeping the data in sync with the latest looks (like when kids are growing up).&lt;/p&gt;&lt;h4&gt;Training&lt;/h4&gt;&lt;p&gt;Now that we have at least one group with a few persons in it, and every person is associated with a few faces, it's time to train that group.&lt;/p&gt;&lt;pre&gt;await client.TrainPersonGroupAsync(personGroupId);&lt;/pre&gt;&lt;p&gt;Simply call the TrainPersonGroupAsync method with the group ID to start the training process. How much it takes depends on how many persons are in the group and the number of faces, but for a small(er) amounts it usually takes a few seconds. To check the training status, call the&amp;nbsp;GetPersonGroupTrainingStatusAsync method:&lt;/p&gt;&lt;pre&gt;var status = await client.GetPersonGroupTrainingStatusAsync(personGroupId);&lt;/pre&gt;&lt;p&gt;The returned status includes an actual field 'status' that indicates the training status: &lt;span style="font-style: italic;"&gt;notstarted&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;running&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;succeeded &lt;/span&gt;and &lt;span style="font-style: italic;"&gt;failed&lt;/span&gt;. You'll be mostly interested in &lt;span style="font-style: italic;"&gt;succeeded &lt;/span&gt;and &lt;span style="font-style: italic;"&gt;failed &lt;/span&gt;statuses. When you get &lt;span style="font-style: italic;"&gt;succeeded&lt;/span&gt;, it means your data is trained and ready to use. In case of &lt;span style="font-style: italic;"&gt;failed &lt;/span&gt;something went wrong and you should check another field returned with status - the &lt;span style="font-style: italic;"&gt;message &lt;/span&gt;field should report what went wrong.&lt;/p&gt;&lt;h4&gt;Face identification&lt;/h4&gt;&lt;p&gt;Finally, with everything in place, we get to the fun part - identifying faces.&lt;/p&gt;&lt;p&gt;Face identification is a two-way process. First you need to call the Face API to detect faces on your photo, like in. This call will return detected face's ID (or more, if multiple faces were detected). Using that ID you need to call the actual identification API to check if that face matches any of persisted faces in the particular group.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;pre style="line-height: 1.42857;"&gt;var file = await fileOpenPicker.PickSingleFileAsync();
Face[] faces;&lt;br&gt;using (var stream = await file.OpenStreamForReadAsync())&lt;br&gt;{&lt;br&gt;&amp;nbsp; &amp;nbsp; faces = await client.&lt;span style="font-weight: bold;"&gt;DetectAsync&lt;/span&gt;(stream);&lt;br&gt;}
var faceIds = faces.Select(i =&amp;gt; i.FaceId).ToArray();
var identifyResults = await client.&lt;span style="font-weight: bold;"&gt;IdentifyAsync&lt;/span&gt;(personGroupId, faceIds);
foreach (var identifyResult in identifyResults)&lt;br&gt;{
    var candidate = identifyResult.Candidates.FirstOrDefault();
    if (candidate != null)
    {
        var person = await client.&lt;span style="font-weight: bold;"&gt;GetPersonAsync&lt;/span&gt;(personGroupId, candidate.PersonId);
        Console.WriteLine($"{person.Name} was identified (with {candidate.Confidence) confidence!");
    }
}
&lt;/pre&gt;&lt;p&gt;In the above code snippet, three API methods are marked bold: DetectAsync detects faces in the photo (see &lt;a href="http://tozon.info/blog/post/2017/07/09/microsoft-cognitive-services-face-api-sdks" target="_blank"&gt;previous post&lt;/a&gt; for more info). It will return face detected face IDs we need for the next call (note: face IDs are stored on servers for 24 hours only, after that they will no longer be available). Taking those IDs, we call the IdentifyAsync metod, also providing the personGroupId. The Face API service will then take provided face IDs and compare those faces with all the faces in the group to return results. The results contain an array of candidates for each face match; having a candidate doesn't necessarily mean we got a perfect match! We can check candidate's Confidence property that return the match confidence score - higher it is, more we can trust the resulting match). To finally get to the name of the person identified, we call the GetPersonAsync method with the identified person's ID.&lt;/p&gt;&lt;p&gt;That's it for person, groups and faces management and basic face identification. I'll get to the more practical examples of face identification in the next posts.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Also check out the &lt;a href="https://github.com/andrejt/CognitiveServicesPlayground" target="_blank"&gt;sample code on github&lt;/a&gt;.&lt;/p&gt;</description>
      <link>http://www.tozon.info/blog/post/2017/07/11/microsoft-cognitive-services-face-identification</link>
      <comments>http://www.tozon.info/blog/post/2017/07/11/microsoft-cognitive-services-face-identification#comment</comments>
      <guid>http://www.tozon.info/blog/post.aspx?id=e5a812ff-8452-49a0-8ae2-0f517da36594</guid>
      <pubDate>Wed, 12 Jul 2017 00:56:00 +0100</pubDate>
      <category>Development</category>
      <category>Microsoft Cognitive Services</category>
      <dc:publisher>Andrej</dc:publisher>
      <pingback:server>http://www.tozon.info/blog/pingback.axd</pingback:server>
      <pingback:target>http://www.tozon.info/blog/post.aspx?id=e5a812ff-8452-49a0-8ae2-0f517da36594</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.tozon.info/blog/trackback.axd?id=e5a812ff-8452-49a0-8ae2-0f517da36594</trackback:ping>
      <wfw:comment>http://www.tozon.info/blog/post/2017/07/11/microsoft-cognitive-services-face-identification#comment</wfw:comment>
      <wfw:commentRss>http://www.tozon.info/blog/syndication.axd?post=e5a812ff-8452-49a0-8ae2-0f517da36594</wfw:commentRss>
    </item>
  </channel>
</rss>