다음을 통해 공유


Windows Server 2008 R2의 필기 인식

Windows Server 2008 R2는 서버 쪽 필기 인식을 지원합니다. 서버 쪽 인식을 사용하면 서버가 웹 페이지의 펜 입력에서 콘텐츠를 인식할 수 있습니다. 이는 네트워크의 사용자가 사용자 지정 사전을 사용하여 해석되는 용어를 지정할 때 특히 유용합니다. 예를 들어 서버 데이터베이스에 환자 이름을 쿼리하는 의료 애플리케이션이 있는 경우 필기 Silverlight 양식에서 검색을 수행할 때 상호 참조되는 다른 데이터베이스에 해당 이름을 추가할 수 있습니다.

Server-Side 인식용 서버 설정

서버 쪽 인식을 설정하려면 다음 단계를 수행해야 합니다.

  • 잉크 및 필기 서비스 설치
  • 웹 서버(IIS) 및 애플리케이션 서버에 대한 지원 설치
  • 데스크톱 환경 역할 사용
  • 태블릿 PC 입력 서비스 시작

잉크 및 필기 서비스 설치

잉크 및 필기 서비스를 설치하려면 빠른 실행 트레이에서 서버 관리자 아이콘을 클릭하여 서버 관리자를 엽니다. 기능 메뉴에서 기능 추가를 클릭합니다. 잉크 및 필기 서비스 검사 상자를 선택해야 합니다. 다음 이미지는 잉크 및 필기 서비스가 선택된 기능 선택 대화 상자를 보여 줍니다.

잉크 및 필기 서비스 검사 상자가 선택된 기능 선택 대화 상자
잉크 및 필기 서비스 검사 상자가 선택된 기능 선택 대화 상자

웹 서버(IIS) 및 애플리케이션 서버에 대한 설치 지원

첫 번째 단계에서 수행한 것처럼 서버 관리자를 엽니다. 다음으로, 웹 서버(IIS) 및 애플리케이션 서버 역할을 추가해야 합니다. 역할 메뉴에서 역할 추가를 클릭합니다. 역할 추가 마법사가 나타납니다. 다음을 클릭합니다. 애플리케이션 서버웹 서버(IIS)가 선택되어 있는지 확인합니다. 다음 이미지는 웹 서버(IIS)애플리케이션서버 역할이 선택된 서버 역할 선택 대화 상자를 보여 줍니다.

웹 서버(iis) 및 애플리케이션 서버 역할이 선택된 서버 역할 선택 대화 상자
웹 서버(iis) 및 애플리케이션 서버 역할이 선택된 서버 역할 선택 대화 상자

애플리케이션 서버를 선택하면 ASP.NET 프레임워크를 설치하라는 메시지가 표시됩니다. 필요한 기능 추가 단추를 클릭합니다. 다음을 클릭하면 개요 대화 상자가 표시됩니다. 다음을 클릭합니다. 이제 역할 서비스 선택 대화 상자를 사용할 수 있습니다. 웹 서버(IIS)가 선택되어 있는지 확인합니다. 다음 이미지는 웹 서버(IIS)가 사용하도록 설정된 역할 서비스 선택 대화 상자를 보여 줍니다.

웹 서버(iis)가 사용하도록 설정된 역할 서비스 선택 대화 상자
웹 서버(iis)가 사용하도록 설정된 역할 서비스 선택 대화 상자

다음을 클릭합니다. 개요 대화 상자가 나타납니다. 다음 을 다시 클릭합니다. 이제 웹 서버(IIS)에 대한 역할에 대한 옵션을 제공하는 페이지가 표시됩니다. 다음을 클릭합니다. 다음 페이지에서 설치 단추가 활성화됩니다. 설치를 클릭하면 웹 서버(IIS) 및 애플리케이션 서버에 대한 지원이 설치됩니다.

데스크톱 환경 역할 사용

데스크톱 환경을 사용하도록 설정하려면 시작을 클릭하고 관리 도구를 클릭한 다음 서버 관리자 클릭합니다. 서비스 추가를 선택한 다음 데스크톱 환경 서비스를 선택합니다. 다음 이미지는 데스크톱 환경 항목이 설치된 기능 선택 대화 상자를 보여 줍니다.

데스크톱 환경 서비스가 선택된 기능 선택 대화 상자
데스크톱 환경 서비스가 선택된 기능 선택 대화 상자

다음을 클릭하여 데스크톱 환경을 설치합니다.

태블릿 서비스 시작

데스크톱 환경 서비스를 설치하면 태블릿 PC 입력 서비스가 서비스 메뉴에 표시됩니다. 서비스 메뉴에 액세스하려면 시작, 관리 도구, 서비스를 차례로 클릭합니다. 서비스를 시작하려면 태블릿 PC 입력 서비스를 마우스 오른쪽 단추로 클릭한 다음 시작을 클릭합니다. 다음 이미지는 태블릿 PC 입력 서비스가 시작된 서비스 메뉴를 보여 줍니다.

태블릿 PC 입력 서비스가 시작된 서비스 메뉴
태블릿 PC 입력 서비스가 시작된 서비스 메뉴

Silverlight를 사용하여 Server-Side 인식 수행

이 섹션에서는 Silverlight를 사용하여 필기 입력을 캡처하는 웹 애플리케이션을 만드는 방법을 보여줍니다. Visual Studio 2008에서 인식기를 프로그래밍하려면 다음 단계를 사용합니다.

  • Visual Studio 2008을 설치하고 업데이트하여 Silverlight에 대한 지원을 추가합니다.
  • Visual Studio 2008에서 새 Silverlight 프로젝트를 만듭니다.
  • 프로젝트에 필요한 서비스 참조를 추가합니다.
  • 잉크 인식을 위한 Silverlight WCF 서비스를 만듭니다.
  • 클라이언트 프로젝트에 서비스 참조를 추가합니다.
  • InkRecognition 프로젝트에 InkCollector 클래스를 추가합니다.
  • 클라이언트 구성에서 보안 전송 지시문 제거

Silverlight에 대한 지원을 추가하도록 Visual Studio 2008 설치 및 업데이트

시작하기 전에 Windows Server 2008 R2 서버에서 다음 단계를 수행해야 합니다.

이러한 애플리케이션 및 업데이트를 설치한 후에는 서버 쪽 인식 웹 애플리케이션을 만들 준비가 된 것입니다.

Visual Studio 2008에서 새 Silverlight 웹 프로젝트 만들기

파일 메뉴에서 새 프로젝트를 클릭합니다. Visual C# 프로젝트 목록에서 Silverlight 애플리케이션 템플릿을 선택합니다. 프로젝트 이름을 InkRecognition으로 지정하고 확인을 클릭합니다. 다음 이미지는 선택되고 이름이 InkRecognition인 C# Silverlight 프로젝트를 보여줍니다.

이름이 inkrecognition인 c# silverlight 프로젝트가 선택됨
이름이 inkrecognition인 c# silverlight 프로젝트가 선택됨

확인을 클릭하면 프로젝트에 Silverlight 애플리케이션을 추가하라는 대화 상자가 표시됩니다. 솔루션에 새 ASP.NET 웹 프로젝트 추가를 선택하여 Silverlight를 호스트하고 확인을 클릭합니다. 다음 이미지는 확인을 클릭하기 전에 예제 프로젝트를 설정하는 방법을 보여줍니다.

프로젝트에 silverlight 애플리케이션을 추가하라는 메시지가 표시된 대화 상자
프로젝트에 silverlight 애플리케이션을 추가하라는 메시지가 표시된 대화 상자

프로젝트에 필요한 서비스 참조 추가

이제 솔루션에 웹 프로젝트(InkRecognition.Web)가 설정된 일반 Silverlight 클라이언트 프로젝트(InkRecognition)가 설정되었습니다. Page.xaml 및 Default.aspx가 열리면 프로젝트가 열립니다. 이러한 창을 닫고 InkRecognition 프로젝트의 references 폴더를 마우스 오른쪽 단추로 클릭하고 참조 추가를 선택하여 System.Runtime.Serialization 및 System.ServiceModel 참조를 InkRecognition 프로젝트에 추가합니다. 다음 이미지는 필수 참조가 선택된 대화 상자를 보여 줍니다.

system.runtime.serialization 및 system.servicemodel이 선택된 참조 추가 대화 상자
system.runtime.serialization 및 system.servicemodel이 선택된 참조 추가 대화 상자

다음으로, InkRecognition.Web 프로젝트에 System.ServiceModel 및 Microsoft.Ink 참조를 추가해야 합니다. Microsoft.Ink 참조는 기본적으로 .NET 참조에 표시되지 않으므로 Windows 폴더에서 Microsoft.Ink.dll 검색합니다. DLL을 찾은 후 프로젝트 참조에 어셈블리를 추가합니다. 찾아보기 탭을 선택하고, Microsoft.Ink.dll 포함하는 폴더로 변경하고, Microsoft.Ink.dll 선택한 다음 확인을 클릭합니다. 다음 이미지는 모든 참조 어셈블리가 추가된 Windows Explorer 프로젝트의 솔루션을 보여줍니다.

모든 참조 어셈블리가 추가된 windows 탐색기의 inkrecognition 프로젝트
모든 참조 어셈블리가 추가된 windows 탐색기의 inkrecognition 프로젝트

잉크 인식용 Silverlight WCF 서비스 만들기

다음으로, 프로젝트에 잉크 인식을 위한 WCF 서비스를 추가합니다. InkRecognition.Web 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가를 클릭한 다음 새 항목을 클릭합니다. WCF Silverlight Service 템플릿을 선택하고 이름을 InkRecogitionService로 변경한 다음 추가를 클릭합니다. 다음 이미지는 Silverlight WCF 서비스가 선택되고 이름이 지정된 새 항목 추가 대화 상자를 보여줍니다.

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;
        }
    }
}

클라이언트 프로젝트에 서비스 참조 추가

이제 InkRecognition용 Silverlight WCF 서비스가 있으므로 클라이언트 애플리케이션에서 서비스를 사용합니다. InkRecognition 프로젝트를 마우스 오른쪽 단추로 클릭하고 서비스 참조 추가를 선택합니다. 표시되는 서비스 참조 추가 대화 상자에서 검색 을 선택하여 현재 솔루션에서 서비스를 검색합니다. InkRecognitionService가 서비스 창에 표시됩니다. 서비스 창에서 InkRecognitionService를 두 번 클릭하고 네임스페이스를 InkRecognitionServiceReference로 변경한 다음 확인을 클릭합니다. 다음 이미지는 InkRecognitionService가 선택되고 네임스페이스가 변경된 서비스 참조 추가 대화 상자를 보여줍니다.

inkrecognitionservice가 선택되고 네임스페이스가 변경된 서비스 참조 추가 대화 상자
inkrecognitionservice가 선택되고 네임스페이스가 변경된 서비스 참조 추가 대화 상자

InkRecognition 프로젝트에 InkCollector 클래스 추가

InkRecognition 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가를 클릭한 다음 새 항목을 클릭합니다. Visual C# 메뉴에서 C# 클래스를 선택합니다. 클래스 이름을 InkCollector로 지정합니다. 다음 이미지는 C# 클래스가 선택되고 이름이 지정된 대화 상자를 보여줍니다.

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 업데이트 및 필기 인식에 대한 코드 숨김 추가

이제 잉크를 수집하는 클래스가 있으므로 page.xaml의 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 서비스를 사용하려면 먼저 보안 전송이 현재 Silverlight 2.0 WCF 서비스에서 지원되지 않으므로 서비스 구성에서 모든 보안 전송 옵션을 제거해야 합니다. InkRecognition 프로젝트에서 ServiceReferences.ClientConfig의 보안 설정을 업데이트합니다. 에서 보안 XML 변경

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

       <security mode="None"/>

이제 애플리케이션이 실행되어야 합니다. 다음 이미지는 인식 상자에 입력된 일부 필기와 함께 애플리케이션이 awebpage 내에서 어떻게 보이는지 보여 줍니다.

인식 상자에 입력된 일부 필기를 사용하여 awebpage 내의 애플리케이션
인식 상자에 입력된 일부 필기를 사용하여 awebpage 내의 애플리케이션

다음 이미지는 결과 드롭다운 목록에서 인식된 텍스트를 보여줍니다.

결과 드롭다운 목록에서 인식된 텍스트와 함께 awebpage 내의 애플리케이션
결과 드롭다운 목록에서 인식된 텍스트와 함께 awebpage 내의 애플리케이션