Translate

레이블이 Xamarin인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Xamarin인 게시물을 표시합니다. 모든 게시물 표시

2017년 4월 13일 목요일

Xamarin(자마린) Android Tesseract OCR 어플 만들기 - 소스코드 및 결과


*  Xamarin(자마린) Android Tesseract OCR 어플 만들기 - 개발 환경설정 에서 이어짐.

Android Studio 개발을 진행중이라 포스팅이 늦었다. 정리가 되면 올릴 예정.



글자 인식 라이브러리인 Tesseract를 사용하기 위해서는 확장자 .traineddata 형식의 언어데이터가 필요하다.

여기서 다운받을 수 있다.
https://github.com/tesseract-ocr/tessdata

테스트용으로 kor, eng를 다운받았다.

다운받은 파일들은 Android 프로젝트 안에 있는 Assets 폴더에 tessdata라는 폴더를 생성하고 넣어준다.






Android 프로젝트에 있는 MainActivity.cs 를 작성한다.

using System;

using Android.App;
using Android.Content.PM;
using Android.OS;
using TinyIoC;
using Tesseract;
using Tesseract.Droid;
using XLabs.Ioc;
using XLabs.Ioc.TinyIOC;
using XLabs.Platform.Device;


namespace Xocr.Droid
{
    [Activity(Label = "Xocr", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            var container = TinyIoCContainer.Current;
            container.Register<IDevice>(AndroidDevice.CurrentDevice);
            container.Register<ITesseractApi>((cont, parameters) =>
            {
                return new TesseractApi(ApplicationContext, Tesseract.Droid.AssetsDeployment.OncePerInitialization);
            });
            Resolver.SetResolver(new TinyResolver(container));

            global::Xamarin.Forms.Forms.Init(this, bundle);
            LoadApplication(new App());
        }
    }
}

앞에서 다운받았던 라이브러리들이 사용되는데, Ioc는 디자인 틀과 동시에 Register 함수를 통해 인스턴트를 등록시키는 역할을 한다. 이를 통해 tessdata를 불러와 TesseractAPI를 등록하는 작업을 수행한다.


+
OncePerInitialization이 무엇인가 하고 소스를 확인해보니, Init할때마다 tessdata를 업데이트하기 때문에 속도가 느리므로 디버그 모드에서 사용하라고 한다.
그 반대인 OncePerVersion는 tessdata를 업데이트하지 않지만 속도가 빠르므로 실제 프로그램에서 사용하라는 것 같다.
테스트해보니 첫 수행에서는 별 차이 없는 속도고, 두번째 이후부터 차이가 생기는 것 같다.


이제 PCL 프로젝트의 MainPage.xaml.cs를 작성한다.

using System;
using System.Threading.Tasks;
using Tesseract;
using Xamarin.Forms;
using XLabs.Ioc;
using XLabs.Platform.Device;
using XLabs.Platform.Services.Media;

namespace Xocr
{
    public partial class MainPage : ContentPage
    {

        private Button _takePictureButton;
        private Label _recognizedTextLabel;
        private Image _takenImage;

        private readonly ITesseractApi _tesseractApi;
        private readonly IDevice _device;

        public MainPage()
        {
            InitializeComponent();

            //TesseractAPI
            _tesseractApi = Resolver.Resolve<ITesseractApi>();
            _device = Resolver.Resolve<IDevice>();

            //UI 생성
            BuildUi();

            //(버튼)이벤트 생성
            WireEvents();

        }


        private void BuildUi()
        {
            // 버튼 생성
            _takePictureButton = new Button
            {
                Text = "New scan"
            };

            _recognizedTextLabel = new Label();


            _takenImage = new Image() { HeightRequest = 200 };

            //버튼, 이미지, 인식결과텍스트 순서대로 배치
            Content = new ScrollView
            {
                Content = new StackLayout
                {
                    Children =
                        {
                            _takePictureButton,
                            _takenImage,
                            _recognizedTextLabel
                        }
                }
            };

        }

        private void WireEvents()
        {
            _takePictureButton.Clicked += TakePictureButton_Clicked;
        }

        async void TakePictureButton_Clicked(object sender, EventArgs e)
        {
            //버튼이 클릭되었을 때, Text 및 Enable 상태 변경
            _takePictureButton.Text = "Working...";
            _takePictureButton.IsEnabled = false;

            //TesseractAPI 초기화 (언어 선정)
            if (!_tesseractApi.Initialized)
                await _tesseractApi.Init("eng");

            //카메라 촬영 후 byte[] 형식 변수로 받아오기
            var photo = await TakePic();
            if (photo != null)
            {
                var imageBytes = new byte[photo.Source.Length];
                photo.Source.Position = 0;
                photo.Source.Read(imageBytes, 0, (int)photo.Source.Length);
                photo.Source.Position = 0;

                //문자 인식 수행
                var tessResult = await _tesseractApi.SetImage(imageBytes);

                //촬영이미지, 인식 결과 출력
                if (tessResult)
                {
                    _takenImage.Source = ImageSource.FromStream(() => photo.Source);
                    _recognizedTextLabel.Text = _tesseractApi.Text;
                }
            }

            //버튼 상태 복구
            _takePictureButton.Text = "New scan";
            _takePictureButton.IsEnabled = true;
        }

        private async Task<MediaFile> TakePic()
        {
            var mediaStorageOptions = new CameraMediaStorageOptions
            {
                DefaultCamera = CameraDevice.Rear
            };
            var mediaFile = await _device.MediaPicker.TakePhotoAsync(mediaStorageOptions);

            return mediaFile;
        }
    }
}

Init("eng"); 를 Init("kor"); 로 수정하면 인식 언어를 바꿀 수 있다.



다음은 결과 화면이다.
뉴스기사를 출력해서 인식해 보았다.





초기화면




English 결과


Korean 결과

카메라 촬영은 가로모드만 지원하고 세로로찍어도 가로로 돌아간 상태로 출력된다.
인식 성능은 속도가 상당히 나쁜편이다.
특히 사진이 부정확해서 인식이 어려울 때는 유난히 더 느리다.

개선할 방법을 공부해봐야겠다.


참고 사이트 : http://thatcsharpguy.com/post/tesseract-ocr-xamarin/

2017년 4월 3일 월요일

Xamarin(자마린) Android Tesseract OCR 어플 만들기 - 개발 환경설정


Laptop
운영체제Windows 10 Home 64bit
개발프로그램Microsoft Visual Studio Community 2015 한글판
Xamarin 4.3.0.795
Xamarin.Android 7.1.0.43

Mobile
모델LG X5
운영체제Android 6.0.1  Marshmallow

원래 안드로이드 스튜디오로 tess-two 모듈을 사용하고 싶었으나..
열심히 찾아봐도 Google이 올렸던 원본 라이브러리는 사라진데다
남아있는건 버전 차이 때문인건지 오류 투성이인 예제들 뿐이다.

포기하고 다른 툴을 찾다가 익숙한 Microsoft Visual Studio라는 점 때문에 끌린 Xamarin 선택.

Xamarin은 크로스플랫폼 개발용이라는 특징이 있는 툴로, C#을 언어로 사용한다.

설치 링크 : https://www.xamarin.com/download

당연히 Visual Studio가 이미 설치되어 있다면 I already have Visual Studio installed를 No로 하면 된다.



설치가 시작되면 여러 세부 설정들과 함께 위와 유사한 창이 뜬다.
저 하늘색 i 표시는 이미 설치되어 있다는 뜻으로 첫 설치라면 안뜨는게 맞다.
실제 필요 드라이브 용량은 사진에는 적게 나와있지만 기억상 36~38GB쯤 되었던것 같다.
 
네이티브 개발 키트 부분은 각자 버전에 맞춰 체크하고
맨 윗부분의 Windows 개발에 관련된 부분은 일단 모두 스킵하고
C#/.NET를 체크하면 아래, SDK, JDK 등에 모두 자동으로 체크가 된다.
 
하지만 설치 완료 후에 SDK, JDK는 구버전이라며 에러가 나니 따로 설치하도록 한다.
어차피 다운로드 대기 시간이 길기도 하니 함께 설치하면 된다.
 
다만 SDK의 경우 기본 경로를 쓰면 겹칠 위험이 있으므로 C: 등에 폴더를 따로 만들어 쓰도록 하자.
JDK는 버전이 다르기 때문에 폴더가 따로 생성된다.
 
(정확히는 Android Studio 설치. SDK만 설치하는 링크를 찾아봤으나 없었다.)
 
 
 
 
 
설치가 모두 완료되면, Microsoft Visual Studio를 실행하면 된다.
 
 
새 프로젝트 창을 켜고 사진과 같이 [Visual C#] - [Cross-Platform] - [플랫폼 간 앱] 을 선택하고, 이름은 임의로 Xocr로 하겠다.
 
여기서 주의사항은 저장 경로에 한글이나 공백이 들어가지 않는게 좋으며, find 관련 에러가 난다면 이것이 원인일 확률이 높다.
 
 
 
 
다음 나오는 화면에서는 코드 공유 전략에서만 PCL을 선택해주고 OK를 누른다.
 
 
 
 
 
 
 
이것은 Xamarin 설치 과정에서 iOS 체크하는 부분을 모두 빼면 나타나는 오류창이다. 이후 iOS 프로젝트가 아예 생성되지 않기때문에 뜨지 않을 것이고, Android만을 다룰 현재 예제에서는 크게 상관없다. 테스트를 해보지 못했기 때문에 이후에도 iOS를 굳이 언급하지 않겠다.
 
 
 
 
위에서 말했듯이 기본적으로 설정되어 있는 SDK, JDK가 구버전이기 때문에 오류가 뜰 것이다.
메뉴의 [도구] - [옵션] - [Xamarin] - [Android Setting] 탭으로 가면 경로 설정을 할 수 있다.
 
(기본적인 경로는 각각 C:\Program Files (x86)\Android\android-sdk~ 와 C:\Program Files (x86)\Java~ 일 것이다.)
 
 
 
 
이것으로 실행 시 오류가 모두 사라졌다면 마지막으로 라이브러리 설치 도구인 Nuget이라는 확장 프로그램을 설치해주면 된다.
 
설치 링크 : https://www.nuget.org/
 
 
 
설치 파일을 실행하면 이런식으로 현재 컴퓨터에 설치된 Visual Studio 버전 리스트가 뜬다.
사용할 버전을 선택하고 Install을 눌러주면 된다.
Xamarin에서 설치한 버전이라면 Community 일 것이다.
 
 
 
 
프로젝트명에서 우측버튼을 클릭하여 [NuGet 패키지 관리] 라는 메뉴를 선택한다.
프로젝트에 다음 두가지 라이브러리를 검색하여 설치한다.
 
XLabs.Forms
Xamarin.Tesseract
 
Xocr.Android 프로젝트에도 마찬가지로 설치해주고,
여기에는 XLabs.IoC.TinyIoC 를 추가적으로 설치한다.
 
빌드해서 오류가 안뜬다면 세팅은 완료된다.
실행은 AVD가 아닌 USB케이블로 기기에 직접 실행하는 방식으로 했다.
그 때 기기 OS 버전에 맞는 API를 설치하라고 뜰텐데, 절차에 따르면 된다.
USB디버깅이나 개발자모드 등에 대한 설명은 생략.
 
 
 
이 화면을 보면 성공.
 
 
 
+
 
기기 목록이 뜨지 않고 시작 버튼을 눌렀을 때 이런 오류창이 뜬다면 Xocr.Android 프로젝트명에서 우측버튼을 누르고 [시작 프로젝트로 설정]을 선택해준다.