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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

Включение роли Desktop Experience

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

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

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

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

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

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

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

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

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

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

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

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

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

В меню "Файл" щелкните "Создать проект". Выберите шаблон приложения Silverlight в списке проектов Visual C#. Назовите проект InkRecognition и нажмите кнопку ОК. На следующем рисунке показан выбранный проект Silverlight C# с именем 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, щелкнув правой кнопкой мыши папку ссылок в проекте InkRecognition и выбрав добавить ссылку. На следующем рисунке показано диалоговое окно с выбранными необходимыми ссылками.

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

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

проект inkrecognition в обозревателе windows со всеми эталонными сборками, добавленными
проект inkrecognition в проводнике Windows со всеми добавленными эталонными сборками

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

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

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

После добавления службы 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;
        }
    }
}

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

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

диалоговое окно «Добавление ссылки на службу» с выбранной службой inkrecognitionservice и измененным пространством имен
диалоговое окно «Добавление ссылки на службу» с выбранной службой inkrecognitionservice и изменённым пространством имен

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

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

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

После добавления класса InkCollector будет открыто определение класса. Замените код в 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"/>

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

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

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

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