Поделиться через


Распознавание рукописного ввода в Windows Server 2008 R2

Windows Server 2008 R2 поддерживает распознавание рукописного ввода на стороне сервера. Распознавание на стороне сервера позволяет серверу распознавать содержимое из входных данных пером на веб-страницах. Это особенно полезно, когда пользователи в сети указывают термины, интерпретируемые с помощью пользовательского словаря. Например, если у вас есть медицинское приложение, которое запрашивало у серверной базы данных имена пациентов, эти имена можно было бы добавить в другую базу данных, на которую будут ссылаться перекрестные ссылки при выполнении поиска из рукописной формы Silverlight.

Настройка сервера для распознавания Server-Side

Чтобы настроить распознавание на стороне сервера, необходимо выполнить следующие действия.

  • Установка служб рукописного ввода и рукописного ввода
  • Установка поддержки веб-сервера (IIS) и сервера приложений
  • Включение роли "Возможности рабочего стола"
  • Запуск службы ввода планшетного компьютера

Установка служб рукописного ввода и рукописного ввода

Чтобы установить службы рукописного ввода и рукописного ввода, откройте диспетчер серверов, щелкнув значок диспетчера серверов на панели быстрого запуска. В меню Компоненты щелкните Добавить компоненты. Убедитесь, что выбрано поле Службы рукописного ввода и рукописного ввода проверка. На следующем рисунке показано диалоговое окно Выбор компонентов с выбранными службами рукописного ввода и рукописного ввода .

Диалоговое окно
Диалоговое окно "Выбор компонентов" с выбранным полем рукописного ввода и рукописного ввода проверка

Поддержка установки для веб-сервера (IIS) и сервера приложений

Откройте диспетчер сервера так же, как и на первом шаге. Затем необходимо добавить роли веб-сервера (IIS) и сервера приложений. В меню Роли щелкните Добавить роли. Откроется мастер добавления ролей. Щелкните Далее. Убедитесь, что выбраны сервер приложений и веб-сервер (IIS). На следующем рисунке показано диалоговое окно Выбор ролей сервера с выбранными ролями веб-сервера (IIS) и сервера приложений .

Диалоговое окно
Диалоговое окно "Выбор ролей сервера" с выбранными ролями веб-сервера (IIS) и сервера приложений

При выборе сервера приложений вам будет предложено установить платформу ASP.NET. Нажмите кнопку Добавить необходимые компоненты . После нажатия кнопки Далее откроется диалоговое окно обзора. Нажмите кнопку Далее. Теперь должно появиться диалоговое окно Выбор служб ролей . Убедитесь, что выбран веб-сервер (IIS). На следующем рисунке показано диалоговое окно Выбор служб ролей с включенным веб-сервером (IIS).

Диалоговое окно
Диалоговое окно "Выбор служб ролей" с включенным веб-сервером (IIS)

Щелкните Далее. Откроется диалоговое окно "Обзор"; Нажмите кнопку Далее еще раз. Теперь вы увидите страницу с вариантами ролей для веб-сервера (IIS). Щелкните Далее. На следующей странице кнопка Установить станет активной. Нажмите кнопку Установить , и вы установите поддержку веб-сервера (IIS) и сервера приложений.

Включение роли "Возможности рабочего стола"

Чтобы включить возможности рабочего стола, нажмите кнопку Пуск, выберите пункт Администрирование, а затем диспетчер сервера. Щелкните Добавить службы , а затем выберите службу "Возможности рабочего стола ". На следующем рисунке показано диалоговое окно "Выбор компонентов " с установленным элементом "Возможности рабочего стола".

Диалоговое окно
Диалоговое окно "Выбор компонентов" с выбранной службой возможностей рабочего стола

Нажмите кнопку Далее , чтобы установить возможности рабочего стола.

Запуск службы планшетов

После установки службы "Возможности рабочего стола" в меню Службы появится служба ввода для планшетного компьютера. Чтобы открыть меню Службы , нажмите кнопку Пуск, выберите пункт Администрирование, а затем — Службы. Чтобы запустить службу, щелкните правой кнопкой мыши службу ввода планшетного компьютера и выберите пункт Пуск. На следующем рисунке показано меню Службы с запущенной службой ввода планшетного компьютера.

Меню
Меню "Службы" с запущенной службой ввода планшетного компьютера

Выполнение распознавания Server-Side с помощью Silverlight

В этом разделе показано, как создать веб-приложение, которое использует Silverlight для записи рукописного ввода. Выполните следующие действия, чтобы запрограммировать распознаватель в Visual Studio 2008.

  • Установите и обновите Visual Studio 2008, чтобы добавить поддержку Silverlight.
  • Создайте проект Silverlight в Visual Studio 2008.
  • Добавьте необходимые ссылки на службы в проект.
  • Создайте службу WCF Silverlight для распознавания рукописного ввода.
  • Добавьте ссылку на службу в клиентский проект.
  • Добавьте класс InkCollector в проект InkRecognition.
  • Удаление директив безопасного транспорта из конфигурации клиента

Установка и обновление Visual Studio 2008 для добавления поддержки Silverlight

Перед началом работы необходимо выполнить следующие действия на сервере Windows Server 2008 R2.

После установки этих приложений и обновлений можно приступать к созданию веб-приложения распознавания на стороне сервера.

Создание веб-проекта Silverlight в Visual Studio 2008

В меню Файл выберите Новый проект. Выберите шаблон Приложение Silverlight из списка проектов Visual C#. Присвойте проекту имя InkRecognition и нажмите кнопку ОК. На следующем рисунке показан выбранный проект C# Silverlight с именем InkRecognition.

Выбран проект c# silverlight с именем inkrecognition
Выбран проект c# silverlight с именем inkrecognition

После нажатия кнопки ОК появится диалоговое окно с предложением добавить приложение Silverlight в проект. Выберите Добавить новый веб-проект ASP.NET в решение для размещения Silverlight и нажмите кнопку ОК. На следующем рисунке показано, как настроить пример проекта перед нажатием кнопки ОК.

Диалоговое окно с запросом на добавление приложения silverlight в проект
Диалоговое окно с запросом на добавление приложения silverlight в проект

Добавление необходимых ссылок на службы в проект

Теперь у вас есть универсальный клиентский проект Silverlight (InkRecognition) с веб-проектом (InkRecognition.Web) в решении. Проект откроется с открытыми файлами Page.xaml и Default.aspx. Закройте эти окна и добавьте ссылки System.Runtime.Serialization и System.ServiceModel в проект InkRecognition, щелкнув правой кнопкой мыши папку references в проекте InkRecognition и выбрав команду Добавить ссылку. На следующем рисунке показано диалоговое окно с выбранными необходимыми ссылками.

Диалоговое окно
Диалоговое окно "Добавление ссылок" с выбранными параметрами system.runtime.serialization и system.servicemodel

Затем необходимо добавить ссылки System.ServiceModel и Microsoft.Ink в проект InkRecognition.Web. Ссылка Microsoft.Ink не будет отображаться в ссылках .NET по умолчанию, поэтому найдите Microsoft.Ink.dll в папке Windows. Найдя библиотеку DLL, добавьте сборку в ссылки проекта: перейдите на вкладку Обзор , перейдите в папку, содержащую Microsoft.Ink.dll, выберите Microsoft.Ink.dll и нажмите кнопку ОК. На следующем рисунке показано решение проекта в Windows Обозреватель со всеми добавленными эталонными сборками.

Проект inkrecognition в проводнике Windows со всеми добавленными ссылочными сборками
Проект inkrecognition в проводнике Windows со всеми добавленными ссылочными сборками

Создание службы WCF Silverlight для распознавания рукописного ввода

Затем вы добавите в проект службу WCF для распознавания рукописного ввода. Щелкните правой кнопкой мыши проект InkRecognition.Web, выберите команду Добавить, а затем — Создать элемент. Выберите шаблон WCF Silverlight Service, измените имя на InkRecogitionService и нажмите кнопку Добавить. На следующем рисунке показано диалоговое окно Добавление нового элемента с выбранной службой WCF Silverlight.

Диалоговое окно
Диалоговое окно "Добавление нового элемента" с выбранным и именем службы WCF silverlight

После добавления службы WCF Silverlight откроется код службы InkRecognitionService.cs. Замените код службы приведенным ниже кодом.

using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Collections.Generic;
using System.Text;
using Microsoft.Ink;

namespace InkRecognition.Web
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class InkRecognitionService
    {
        [OperationContract]
        public string[] Recognize(int[][] packets)
        {
            // Deserialize ink.
            Ink ink = new Ink();
            Tablet tablet = new Tablets().DefaultTablet;
            TabletPropertyDescriptionCollection desc = new TabletPropertyDescriptionCollection();
            desc.Add(new TabletPropertyDescription(PacketProperty.X, tablet.GetPropertyMetrics(PacketProperty.X)));
            desc.Add(new TabletPropertyDescription(PacketProperty.Y, tablet.GetPropertyMetrics(PacketProperty.Y)));
            int numOfStrokes = packets.GetUpperBound(0) + 1;
            for (int i = 0; i < numOfStrokes; i++)
            {
                ink.CreateStroke(packets[i], desc);
            }

            // Recognize ink.
            RecognitionStatus recoStatus;
            RecognizerContext recoContext = new RecognizerContext();
            recoContext.RecognitionFlags = RecognitionModes.LineMode | RecognitionModes.TopInkBreaksOnly;
            recoContext.Strokes = ink.Strokes;
            RecognitionResult recoResult = recoContext.Recognize(out recoStatus);
            RecognitionAlternates alternates = recoResult.GetAlternatesFromSelection();
            string[] results = new string[alternates.Count];
            for (int i = 0; i < alternates.Count; i++)
            {
                results[i] = alternates[i].ToString();
            }

            // Send results to client.
            return results;
        }
    }
}

Добавление ссылки на службу в клиентский проект

Теперь, когда у вас есть служба WCF Silverlight для InkRecognition, вы будете использовать службу из клиентского приложения. Щелкните правой кнопкой мыши проект InkRecognition и выберите Добавить ссылку на службу. В появившемся диалоговом окне Добавление ссылки на службу выберите Обнаружение , чтобы обнаружить службы из текущего решения. InkRecognitionService появится в области Службы. Дважды щелкните InkRecognitionService на панели Службы, измените пространство имен на InkRecognitionServiceReference и нажмите кнопку ОК. На следующем рисунке показано диалоговое окно Добавление ссылки на службу с выбранным параметром InkRecognitionService и измененным пространством имен.

Диалоговое окно
Диалоговое окно "Добавление ссылки на службу" с выбранным inkrecognitionservice и измененным пространством имен

Добавление класса InkCollector в проект InkRecognition

Щелкните правой кнопкой мыши проект InkRecognition, выберите команду Добавить, а затем — Создать элемент. В меню Visual C# выберите класс C#. Назовите класс InkCollector. На следующем рисунке показано диалоговое окно с выбранным и именованным классом C#.

Диалоговое окно
Диалоговое окно "Добавление нового элемента" с выбранным классом c# и именем

После добавления класса InkCollector откроется определение класса. Замените код в сборщике рукописного ввода следующим кодом.

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace InkRecognition
{
    public class InkCollector : IDisposable
    {
        public InkCollector(InkPresenter presenter)
        {
            _presenter = presenter;
            _presenter.Cursor = Cursors.Stylus;
            _presenter.MouseLeftButtonDown += new MouseButtonEventHandler(_presenter_MouseLeftButtonDown);
            _presenter.MouseMove += new MouseEventHandler(_presenter_MouseMove);
            _presenter.MouseLeftButtonUp += new MouseButtonEventHandler(_presenter_MouseLeftButtonUp);
        }

        void _presenter_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            _presenter.CaptureMouse();
            if (!e.StylusDevice.Inverted)
            {
                _presenter.Cursor = Cursors.Stylus;
                _stroke = new Stroke(e.StylusDevice.GetStylusPoints(_presenter));
                _stroke.DrawingAttributes = _drawingAttributes;
                _presenter.Strokes.Add(_stroke);
            }
            else
            {
                _presenter.Cursor = Cursors.Eraser;
                _erasePoints = e.StylusDevice.GetStylusPoints(_presenter);
            }
        }

        void _presenter_MouseMove(object sender, MouseEventArgs e)
        {
            if (!e.StylusDevice.Inverted)
            {
                _presenter.Cursor = Cursors.Stylus;
            }
            else
            {
                _presenter.Cursor = Cursors.Eraser;
            }
            if (_stroke != null)
            {
                _stroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(_presenter));
            }
            else if (_erasePoints != null)
            {
                _erasePoints.Add(e.StylusDevice.GetStylusPoints(_presenter));
                StrokeCollection hitStrokes = _presenter.Strokes.HitTest(_erasePoints);
                if (hitStrokes.Count > 0)
                {
                    foreach (Stroke hitStroke in hitStrokes)
                    {
                        _presenter.Strokes.Remove(hitStroke);
                    }
                }
            }
        }

        void _presenter_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            _presenter.ReleaseMouseCapture();
            if (_stroke != null)
            {
                _stroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(_presenter));
            }
            _stroke = null;
            _erasePoints = null;
        }

        public DrawingAttributes DefaultDrawingAttributes
        {
            get { return _drawingAttributes; }
            set { _drawingAttributes = value; }
        }

        public void Dispose()
        {
            _presenter.MouseLeftButtonDown -= new MouseButtonEventHandler(_presenter_MouseLeftButtonDown);
            _presenter.MouseMove -= new MouseEventHandler(_presenter_MouseMove);
            _presenter.MouseLeftButtonUp -= new MouseButtonEventHandler(_presenter_MouseLeftButtonUp);
            _presenter = null;
        }

        private InkPresenter _presenter = null;
        private Stroke _stroke = null;
        private StylusPointCollection _erasePoints = null;
        private DrawingAttributes _drawingAttributes = new DrawingAttributes();
    }
}

Обновление XAML для страницы по умолчанию и добавление кода программной части для распознавания рукописного ввода

Теперь, когда у вас есть класс, который собирает рукописный ввод, необходимо обновить XAML в файле page.xaml следующим кодом XAML. Следующий код добавляет желтый градиент к области ввода, элементу управления InkCanvas и кнопке, которая активирует распознавание.

<UserControl x:Class="InkRecognition.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Border Margin="5" Grid.Row="0" BorderThickness="4" BorderBrush="Black" CornerRadius="5" Height="200">
            <Grid>
                <InkPresenter x:Name="inkCanvas">
                    <InkPresenter.Background>
                        <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                            <GradientStop Offset="0" Color="Yellow"/>
                            <GradientStop Offset="1" Color="LightYellow"/>
                        </LinearGradientBrush>
                    </InkPresenter.Background>
                </InkPresenter>
                <Button Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="10" Content="Recognize" Click="RecoButton_Click"/>
            </Grid>
        </Border>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0" FontSize="28" Text="Result: "/>
            <ComboBox x:Name="results" Grid.Column="1" FontSize="28"/>
        </Grid>
    </Grid>
</UserControl>

Замените страницу кода программной части Page.xaml.cs следующим кодом, который добавит обработчик событий для кнопки Распознать .

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using InkRecognition.InkRecognitionServiceReference;

namespace InkRecognition
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            inkCol = new InkCollector(inkCanvas);
            recoClient = new InkRecognitionServiceClient();
            recoClient.RecognizeCompleted += new EventHandler<RecognizeCompletedEventArgs>(recoClient_RecognizeCompleted);
        }

        private void RecoButton_Click(object sender, RoutedEventArgs e)
        {
            // Serialize the ink into an array on ints.
            ObservableCollection<ObservableCollection<int>> packets = new ObservableCollection<ObservableCollection<int>>();
            double pixelToHimetricMultiplier = 2540d / 96d;

            foreach (Stroke stroke in inkCanvas.Strokes)
            {
                packets.Add(new ObservableCollection<int>());
                int index = inkCanvas.Strokes.IndexOf(stroke);
                for (int i = 0; i < stroke.StylusPoints.Count; i += 2)
                {
                    packets[index].Add(Convert.ToInt32(stroke.StylusPoints[i].X * pixelToHimetricMultiplier));
                    packets[index].Add(Convert.ToInt32(stroke.StylusPoints[i].Y * pixelToHimetricMultiplier));
                }
            }

            // Call the Web service.
            recoClient.RecognizeAsync(packets);
        }

        void recoClient_RecognizeCompleted(object sender, RecognizeCompletedEventArgs e)
        {
            // We have received results from the server, now display them.
            results.ItemsSource = e.Result;
            UpdateLayout();
            results.SelectedIndex = 0;
            inkCanvas.Strokes.Clear();
        }

        private InkRecognitionServiceClient recoClient = null;
        private InkCollector inkCol = null;
    }
}

Удаление директив безопасного транспорта из конфигурации клиента

Прежде чем использовать службу WCF, необходимо удалить все параметры безопасного транспорта из конфигурации службы, так как безопасные транспорты в настоящее время не поддерживаются в службах WCF Silverlight 2.0. В проекте InkRecognition обновите параметры безопасности в ServiceReferences.ClientConfig. Изменение XML-кода безопасности с

          <security mode="None">
            <transport>
              <extendedProtectionPolicy policyEnforcement="WhenSupported" />
            </transport>
          </security>

значение

       <security mode="None"/>

Теперь приложение должно запуститься. На следующем рисунке показано, как приложение выглядит в веб-page с некоторыми рукописными вводами, введенными в поле распознавания.

Приложение в веб-page с некоторым рукописным вводом в поле распознавания
Приложение в веб-page с некоторым рукописным вводом в поле распознавания

На следующем рисунке показан распознанный текст в раскрывающемся списке Результат .

Приложение в awebpage с распознаваемым текстом в раскрывающемся списке результатов
Приложение в awebpage с распознаваемым текстом в раскрывающемся списке результатов