저번에 Tesseract와 OpenALPR을 이용하여 C# 프로그램을 만들었는데 이번에는 안드로이드에서 만들어보겠습니다!!


참고 ☞ C# 문자인식 프로그래밍


안드로이드에서 문자인식을 하기위해서는 기본적으로 OpenCV 라이브러리가 필요합니다.


참고 ☞ 안드로이드에서 OpenCV 사용하기


안드로이드에서는 API를 사용하지 않고 조금 원시적인(?) 방법으로 문자인식으로 해보려고 합니다.


※ 문자인식을 하기 위한 절차


1. 안드로이드와 카메라를 연동합니다.(CameraPreview)

2. 사진을 촬영하고 내부저장소에 저장합니다.(PNG)

3. 저장소에 저장된 이미지파일을 불러옵니다.(Bitmap)

4. 불러온 이미지 파일에 전처리 작업을 수행합니다.(GrayScale, ThresHold, 등)

5. 전체 이미지에서 번호판 영역을 관심영역으로 설정하고 따로 분류합니다.(ROI, contours)

6. 분류된 번호판 영역 이미지 파일에서 번호판 숫자 및 문자를 라벨링 처리합니다.

7. 라벨링 처리 된 숫자 및 문자들을 미리 준비한 템플릿과 비교합니다.

8. 비교한 결과 중 가장 매칭률이 높은 숫자 및 문자를 선별합니다.

9. 모든 숫자와 문자를 순서대로 조합하면 문자인식 결과입니다.


안드로이드에서도 물론 Tesseract API(tess-two)를 사용할 수 있습니다. (30줄 이내에...) 

하지만 이런 원시적인 방법을 통해 실제로 문자 및 패턴인식을 하는 원리를 파악할 수 있으며 가장 중요한것은 인식률이 상당히 높다는 것입니다!!! (Tesseract OCR이 한글 문자 인식률이 매우 낮은걸로 유명하죠... 하지만 워낙 라이브러리 자체가 유연해서 거의 모든 프로그래밍 언어를 지원하며 문자 인식 훈련을 통해 인식률을 높일수 있답니다.)


자 그럼 절차대로 하나하나씩 따라해봅시다.


1, 2. 안드로이드 카메라 연동 및 사진 저장 : 이미 블로그에 설명한 내용이 있으므로 링크로 대체합니다.


3. 저장된 이미지 파일 불러오기 : 내부 저장소에 저장된 이미지 파일을 불러오는 방법은 다음과 같이 간단합니다. PNG파일을 File 객체를 통해 지정하고 BitmapFactory.decodeFile을 통해 이미지를 비트맵 객체로 불러올 수 있습니다.


File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/OpenCVTest/sample.png");

if(file.exists()){

Bitmap myBitmap = BitmapFactory.decodeFile(file.getAbsolutePath());


4. 이미지 전처리 작업 : 기본적으로 GrayScale(흑백) 및 ThresHold(이진화) 처리를 수행합니다.


Bitmap image1;

OpenCVLoader.initDebug();


Mat img1=new Mat();

Utils.bitmapToMat(myBitmap ,img1);


Mat imageGray1 = new Mat();

Mat imageCny1 = new Mat();


Imgproc.cvtColor(img1, imageGray1, Imgproc.COLOR_BGR2GRAY);

Imgproc.threshold(imageGray1, imageCny1, 160, 255, Imgproc.THRESH_BINARY);


5. 이미지 관심영역 추출 : 링크


6, 7, 8, 9. 번호판 숫자 인식 : 

코드가 약간 복잡합니다. 간단히 설명드리면 다음 절차와 같이 수행합니다.

1. 전체사진 불러오기 -> 전처리 -> 번호판만 추출

2. 번호판사진 불러오기 -> 흑백 반전(검은바탕에 흰색 숫자가 되도록) -> 숫자 추출

3. 추출된 숫자와 템플릿 비교

4. 결과 출력


* 신형 번호판의 숫자와 문자는 00가 0000 이런식으로 숫자6개 문자1개 총 7개의 라벨이 생깁니다. 하지만 'ㄱ ㅏ' 라는 문자의 경우 'ㄱ'과 'ㅏ'를 따로 라벨링 처리하기 때문에 총 8개의 문자가 생길때도 있습니다. 이를 처리하기위해 라벨이 7개, 8개인 경우를 각각 조건문으로 처리했습니다.


int[][] listarr = new int[8][4];

List<MatOfPoint> contoursROI = new ArrayList<>();

Mat hierarchyROI = new Mat();

Mat matROI = new Mat();

Mat ResultROI = new Mat();

Utils.bitmapToMat(roi, matROI);

Imgproc.cvtColor(matROI, ResultROI, Imgproc.COLOR_BGR2GRAY, 1);

Imgproc.findContours(ResultROI, contoursROI, hierarchyROI, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

int count = 0;

for(int idx = 0; idx >= 0; idx = (int) hierarchyROI.get(0, idx)[0]) {

    if(count>7) break;

    MatOfPoint matOfPoint = contoursROI.get(idx);

    Rect rect = Imgproc.boundingRect(matOfPoint);

    // 해상도별로 조절하기.

    if(rect.x < roi.getWidth()/20 || rect.x > roi.getWidth()-(roi.getWidth()/10) ||

            rect.y < roi.getHeight()/10 || rect.y > roi.getHeight()-(roi.getHeight()/10) ||

            rect.width < roi.getWidth()/50 || rect.width > roi.getWidth()/8 ||

            rect.height <= roi.getHeight()/10 ) continue;


    Log.d("RECT : ", "x : " + rect.x + ", y : " + rect.y + ", w :" + rect.width + ", h : " + rect.height);

    Imgproc.rectangle(matROI, rect.tl(), rect.br(), new Scalar(255, 0, 0, 255), 1);


    listarr[count][0] = rect.x;

    listarr[count][1] = rect.y;

    listarr[count][2] = rect.width;

    listarr[count][3] = rect.height;

    count++;

}

if(count == 7) {

    // 오름차순 정렬

    for(int i = 0; i < 7; i++) {

        for(int j = i; j < 7; j++) {

            if(listarr[i][0] > listarr[j][0]) {

                // 스왑

                int[] temp = new int[4];

                temp[0] = listarr[i][0];

                temp[1] = listarr[i][1];

                temp[2] = listarr[i][2];

                temp[3] = listarr[i][3];

                listarr[i][0] = listarr[j][0];

                listarr[i][1] = listarr[j][1];

                listarr[i][2] = listarr[j][2];

                listarr[i][3] = listarr[j][3];

                listarr[j][0] = temp[0];

                listarr[j][1] = temp[1];

                listarr[j][2] = temp[2];

                listarr[j][3] = temp[3];

            }

        }

    }


    for(int i = 0; i < 7; i++) {

        Bitmap tempBitmap = Bitmap.createBitmap(roi, listarr[i][0], listarr[i][1], listarr[i][2], listarr[i][3]);

        tempBitmap = Bitmap.createScaledBitmap(tempBitmap, 10, 15, true);

        if(i == 0)

            imageViewROI1.setImageBitmap(tempBitmap);

        else if(i == 1)

            imageViewROI2.setImageBitmap(tempBitmap);

        else if(i == 2)

            imageViewROI3.setImageBitmap(tempBitmap);

        else if(i == 3)

            imageViewROI4.setImageBitmap(tempBitmap);

        else if(i == 4)

            imageViewROI5.setImageBitmap(tempBitmap);

        else if(i == 5)

            imageViewROI6.setImageBitmap(tempBitmap);

        else if(i == 6)

            imageViewROI7.setImageBitmap(tempBitmap);


        int num_count = 0;

        double max = 0.0;

        int num = 0;

        if(i==2) { // 문자

            for(int n = 0; n < 10; n++) {

                for(int j = 0; j < 15; j++) {

                    for(int k = 0; k < 10; k++) {

                        if(ones[n][j][k] == tempBitmap.getPixel(k, j))

                            num_count++;

                    }

                }

                double result = (double)num_count/proones[n]*100;

                if(result > 100) result = 100;

                if(result > max) {

                    max = result;

                    num = n;

                }

                num_count=0;

            }

        }

        else { // 숫자

            for(int n = 0; n < 10; n++) {

                for(int j = 0; j < 15; j++) {

                    for(int k = 0; k < 10; k++) {

                        if(nums[n][j][k] == tempBitmap.getPixel(k, j))

                            num_count++;

                    }

                }

                double result = (double)num_count/pronums[n]*100;

                if(result > 100) result = 100;

                if(result > max) {

                    max = result;

                    num = n;

                }

                num_count=0;

            }

        }


        avg+=max;

        String floatnum = String.format("%.2f", max);


        if(i == 2) { // 한글 처리

            // 중략


            }


            int a = 0, b = 0, c = 0;

            for(int x=0; x<tempBitmap.getHeight(); x++) {

                for (int y = 0; y < tempBitmap.getWidth(); y++) {

                    if (tempBitmap.getPixel(y, x) == -1) {

                        Log.d("arr", "ones[5][" + a + "][" + b + "] = " + tempBitmap.getPixel(y, x) + ";");

                        c++;

                    }

                    b++;

                }

                b = 0;

                a++;

            }

            Log.d("count" , ""+c);

        }

        else { // 숫자 처리

            textViewResult.append(i + "번째 분석 결과 : " + num + " / 정확도 : " + floatnum +"%\n");

            result += Integer.toString(num);

        }

    }

}

else if(count == 8) {

    // 오름차순 정렬

    for(int i = 0; i < 8; i++) {

        for(int j = i; j < 8; j++) {

            if(listarr[i][0] > listarr[j][0]) {

                // 스왑

                int[] temp = new int[4];

                temp[0] = listarr[i][0];

                temp[1] = listarr[i][1];

                temp[2] = listarr[i][2];

                temp[3] = listarr[i][3];

                listarr[i][0] = listarr[j][0];

                listarr[i][1] = listarr[j][1];

                listarr[i][2] = listarr[j][2];

                listarr[i][3] = listarr[j][3];

                listarr[j][0] = temp[0];

                listarr[j][1] = temp[1];

                listarr[j][2] = temp[2];

                listarr[j][3] = temp[3];

            }

        }

    }

    // 한글인 경우

    if(abs(listarr[2][0]-listarr[3][0]) < 20) {

        if(listarr[2][1] > listarr[3][1]) {

            // 스왑

            int[] temp = new int[4];

            temp[0] = listarr[2][0];

            temp[1] = listarr[2][1];

            temp[2] = listarr[2][2];

            temp[3] = listarr[2][3];

            listarr[2][0] = listarr[3][0];

            listarr[2][1] = listarr[3][1];

            listarr[2][2] = listarr[3][2];

            listarr[2][3] = listarr[3][3];

            listarr[3][0] = temp[0];

            listarr[3][1] = temp[1];

            listarr[3][2] = temp[2];

            listarr[3][3] = temp[3];

        }

    }


    for(int i = 0; i < 8; i++) {

        Bitmap tempBitmap = Bitmap.createBitmap(roi, listarr[i][0], listarr[i][1], listarr[i][2], listarr[i][3]);

        tempBitmap = Bitmap.createScaledBitmap(tempBitmap, 10, 15, true);

        if(i == 0)

            imageViewROI1.setImageBitmap(tempBitmap);

        else if(i == 1)

            imageViewROI2.setImageBitmap(tempBitmap);

        else if(i == 2)

            imageViewROI3.setImageBitmap(tempBitmap);

        else if(i == 3)

            imageViewROI4.setImageBitmap(tempBitmap);

        else if(i == 4)

            imageViewROI5.setImageBitmap(tempBitmap);

        else if(i == 5)

            imageViewROI6.setImageBitmap(tempBitmap);

        else if(i == 6)

            imageViewROI7.setImageBitmap(tempBitmap);

        else if(i == 7)

            imageViewROI8.setImageBitmap(tempBitmap);


        int num_count = 0;

        double max = 0.0;

        int num = 0;

        // 자음

        if(i==2) {

            for(int n = 0; n < 10; n++) {

                for(int j = 0; j < 15; j++) {

                    for(int k = 0; k < 10; k++) {

                        if(cons[n][j][k] == tempBitmap.getPixel(k, j))

                            num_count++;

                    }

                }

                double result = (double)num_count/procons[n]*100;

                if(result > 100) result = 100;

                if(result > max) {

                    max = result;

                    num = n;

                }

                num_count=0;

            }

        }


        // 모음

        else if(i==3) {

            for(int n = 0; n < 4; n++) {

                for(int j = 0; j < 15; j++) {

                    for(int k = 0; k < 10; k++) {

                        if(vocs[n][j][k] == tempBitmap.getPixel(k, j))

                            num_count++;

                    }

                }

                double result = (double)num_count/provocs[n]*100;

                if(result > 100) result = 100;

                if(result > max) {

                    max = result;

                    num = n;

                }

                num_count=0;

            }

        }


        // 숫자

        else {

            for(int n = 0; n < 10; n++) {

                for(int j = 0; j < 15; j++) {

                    for(int k = 0; k < 10; k++) {

                        if(nums[n][j][k] == tempBitmap.getPixel(k, j))

                            num_count++;

                    }

                }

                double result = (double)num_count/pronums[n]*100;

                if(result > 100) result = 100;

                if(result > max) {

                    max = result;

                    num = n;

                }

                num_count=0;

            }

        }


        avg+=max;

        String floatnum = String.format("%.2f", max);


        // 자음

        if(i==2) {

            // 중략

        }


        // 모음

        else if(i==3) {

            // 중략

        }


        // 숫자

        else {

            textViewResult.append(i + "번째 분석 결과 : " + num + " / 정확도 : " + floatnum +"%\n");

            result += Integer.toString(num);

        }

    }

}

else {

    Toast.makeText(context, "숫자 생성 실패", Toast.LENGTH_SHORT).show();

}


Utils.matToBitmap(matROI, roi2);


imageViewROI = (ImageView)findViewById(R.id.image_result_ROI);

imageViewROI.setImageBitmap(roi2);


String resultnum = String.format("%.2f", avg/count);

textViewResult.append("\n\n분석 결과 : " + result + " / 정확도 : " + resultnum + "%");

}


중간에 문자 비교 코드는 너무 길어서 중략 처리했습니다.

다음은 미리 저장해둔 문자 템플릿입니다.


nums = new int[10][15][10];

pronums = new int[10];


cons = new int[10][15][10];

procons = new int[10];


vocs = new int[4][15][10];

provocs = new int[4];


ones = new int[10][15][10];

proones = new int[10];


// 픽셀 개수

pronums[0] = 50;

pronums[1] = 40;

pronums[2] = 40;

pronums[3] = 45;

pronums[4] = 50;

pronums[5] = 55;

pronums[6] = 50;

pronums[7] = 37;

pronums[8] = 50;

pronums[9] = 40;


// 0

nums[0][0][3] = -1; nums[0][0][4] = -1; nums[0][0][5] = -1; nums[0][0][6] = -1;

nums[0][1][2] = -1; nums[0][1][3] = -1; nums[0][1][6] = -1; nums[0][1][7] = -1;

nums[0][2][0] = -1; nums[0][2][1] = -1; nums[0][2][8] = -1; nums[0][2][9] = -1;

nums[0][3][0] = -1; nums[0][3][1] = -1; nums[0][3][8] = -1; nums[0][3][9] = -1;

nums[0][4][0] = -1; nums[0][4][1] = -1; nums[0][4][8] = -1; nums[0][4][9] = -1;

nums[0][5][0] = -1; nums[0][5][1] = -1; nums[0][5][8] = -1; nums[0][5][9] = -1;

nums[0][6][0] = -1; nums[0][6][1] = -1; nums[0][6][8] = -1; nums[0][6][9] = -1;

nums[0][7][0] = -1; nums[0][7][1] = -1; nums[0][7][8] = -1; nums[0][7][9] = -1;

nums[0][8][0] = -1; nums[0][8][1] = -1; nums[0][8][8] = -1; nums[0][8][9] = -1;

nums[0][9][0] = -1; nums[0][9][1] = -1; nums[0][9][8] = -1; nums[0][9][9] = -1;

nums[0][10][0] = -1; nums[0][10][1] = -1; nums[0][10][8] = -1; nums[0][10][9] = -1;

nums[0][11][0] = -1; nums[0][11][1] = -1; nums[0][11][8] = -1; nums[0][11][9] = -1;

nums[0][12][0] = -1; nums[0][12][1] = -1; nums[0][12][8] = -1; nums[0][12][9] = -1;

nums[0][13][2] = -1; nums[0][13][3] = -1; nums[0][13][6] = -1; nums[0][13][7] = -1;

nums[0][14][3] = -1; nums[0][14][4] = -1; nums[0][14][5] = -1; nums[0][14][6] = -1;


// 1

nums[1][0][7] = -1; nums[1][0][8] = -1;

nums[1][1][6] = -1; nums[1][1][7] = -1; nums[1][1][8] = -1;

nums[1][2][1] = -1; nums[1][2][2] = -1; nums[1][2][3] = -1; nums[1][2][4] = -1; nums[1][2][5] = -1; nums[1][2][6] = -1; nums[1][2][7] = -1; nums[1][2][8] = -1;

nums[1][3][0] = -1; nums[1][3][1] = -1; nums[1][3][2] = -1; nums[1][3][3] = -1; nums[1][3][4] = -1; nums[1][3][5] = -1; nums[1][3][6] = -1; nums[1][3][7] = -1; nums[1][3][8] = -1;

nums[1][4][6] = -1; nums[1][4][7] = -1; nums[1][4][8] = -1;

nums[1][5][7] = -1; nums[1][5][8] = -1;

nums[1][6][7] = -1; nums[1][6][8] = -1;

nums[1][7][7] = -1; nums[1][7][8] = -1;

nums[1][8][7] = -1; nums[1][8][8] = -1;

nums[1][9][7] = -1; nums[1][9][8] = -1;

nums[1][10][7] = -1; nums[1][10][8] = -1;

nums[1][11][7] = -1; nums[1][11][8] = -1;

nums[1][12][7] = -1; nums[1][12][8] = -1;

nums[1][13][7] = -1; nums[1][13][8] = -1;

nums[1][14][7] = -1; nums[1][14][8] = -1;


// 2

nums[2][0][3] = -1; nums[2][0][4] = -1;

nums[2][1][1] = -1; nums[2][1][2] = -1; nums[2][1][5] = -1; nums[2][1][6] = -1;

nums[2][2][0] = -1; nums[2][2][1] = -1; nums[2][2][7] = -1;

nums[2][3][0] = -1; nums[2][3][1] = -1; nums[2][3][7] = -1; nums[2][3][8] = -1;

nums[2][4][7] = -1; nums[2][4][8] = -1;

nums[2][5][7] = -1; nums[2][5][8] = -1;

nums[2][6][6] = -1; nums[2][6][7] = -1;

nums[2][7][6] = -1; nums[2][7][7] = -1;

nums[2][8][5] = -1; nums[2][8][6] = -1;

nums[2][9][4] = -1; nums[2][9][5] = -1;

nums[2][10][3] = -1; nums[2][10][4] = -1;

nums[2][11][3] = -1; nums[2][11][4] = -1;

nums[2][12][2] = -1; nums[2][12][3] = -1;

nums[2][13][1] = -1; nums[2][13][2] = -1; nums[2][13][3] = -1;

nums[2][14][1] = -1; nums[2][14][2] = -1; nums[2][14][3] = -1; nums[2][14][4] = -1; nums[2][14][5] = -1; nums[2][14][6] = -1; nums[2][14][7] = -1; nums[2][14][8] = -1; nums[2][14][9] = -1;


// 3

nums[3][0][2] = -1; nums[3][0][3] = -1; nums[3][0][4] = -1; nums[3][0][5] = -1; nums[3][0][6] = -1; nums[3][0][7] = -1; nums[3][0][8] = -1; nums[3][0][9] = -1;

nums[3][1][3] = -1; nums[3][1][4] = -1; nums[3][1][5] = -1; nums[3][1][6] = -1; nums[3][1][7] = -1; nums[3][1][8] = -1; nums[3][1][9] = -1;

nums[3][2][7] = -1; nums[3][2][8] = -1;

nums[3][3][6] = -1; nums[3][3][7] = -1;

nums[3][4][5] = -1; nums[3][4][6] = -1;

nums[3][5][4] = -1; nums[3][5][5] = -1; nums[3][5][6] = -1;

nums[3][6][5] = -1; nums[3][6][6] = -1; nums[3][6][7] = -1;

nums[3][7][7] = -1;

nums[3][8][7] = -1; nums[3][8][8] = -1;

nums[3][9][7] = -1; nums[3][9][8] = -1;

nums[3][10][0] = -1; nums[3][10][1] = -1; nums[3][10][7] = -1;

nums[3][11][0] = -1; nums[3][11][1] = -1; nums[3][11][7] = -1;

nums[3][12][0] = -1; nums[3][12][1] = -1; nums[3][12][6] = -1;

nums[3][13][1] = -1; nums[3][13][2] = -1; nums[3][13][3] = -1; nums[3][13][4] = -1; nums[3][13][5] = -1; nums[3][13][6] = -1;

nums[3][14][2] = -1; nums[3][14][3] = -1; nums[3][14][4] = -1;


// 4

nums[4][0][6] = -1; nums[4][0][7] = -1;

nums[4][1][6] = -1; nums[4][1][7] = -1;

nums[4][2][5] = -1; nums[4][2][6] = -1; nums[4][2][7] = -1;

nums[4][3][4] = -1; nums[4][3][5] = -1; nums[4][3][6] = -1; nums[4][3][7] = -1;

nums[4][4][3] = -1; nums[4][4][4] = -1; nums[4][4][6] = -1; nums[4][4][7] = -1;

nums[4][5][3] = -1; nums[4][5][6] = -1; nums[4][5][7] = -1;

nums[4][6][2] = -1; nums[4][6][3] = -1; nums[4][6][6] = -1; nums[4][6][7] = -1;

nums[4][7][2] = -1; nums[4][7][6] = -1; nums[4][7][7] = -1;

nums[4][8][1] = -1; nums[4][8][2] = -1; nums[4][8][6] = -1; nums[4][8][7] = -1;

nums[4][9][1] = -1; nums[4][9][6] = -1; nums[4][9][7] = -1;

nums[4][10][0] = -1; nums[4][10][1] = -1; nums[4][10][2] = -1; nums[4][10][3] = -1; nums[4][10][4] = -1; nums[4][10][5] = -1; nums[4][10][6] = -1; nums[4][10][7] = -1; nums[4][10][8] = -1; nums[4][10][9] = -1;

nums[4][11][0] = -1; nums[4][11][1] = -1; nums[4][11][2] = -1; nums[4][11][3] = -1; nums[4][11][4] = -1; nums[4][11][5] = -1; nums[4][11][6] = -1; nums[4][11][7] = -1; nums[4][11][8] = -1; nums[4][11][9] = -1;

nums[4][12][6] = -1; nums[4][12][7] = -1;

nums[4][13][6] = -1; nums[4][13][7] = -1;

nums[4][14][6] = -1; nums[4][14][7] = -1;


// 5

nums[5][0][2] = -1; nums[5][0][3] = -1; nums[5][0][4] = -1; nums[5][0][5] = -1; nums[5][0][6] = -1; nums[5][0][7] = -1; nums[5][0][8] = -1;

nums[5][1][1] = -1;  nums[5][1][2] = -1; nums[5][1][3] = -1; nums[5][1][4] = -1; nums[5][1][5] = -1; nums[5][1][6] = -1; nums[5][1][7] = -1;

nums[5][2][1] = -1; nums[5][2][2] = -1;

nums[5][3][1] = -1; nums[5][3][2] = -1;

nums[5][4][1] = -1; nums[5][4][2] = -1;

nums[5][5][1] = -1; nums[5][5][2] = -1;

nums[5][6][1] = -1; nums[5][6][2] = -1; nums[5][6][3] = -1; nums[5][6][4] = -1; nums[5][6][5] = -1; nums[5][6][6] = -1; nums[5][6][7] = -1;

nums[5][7][1] = -1; nums[5][7][2] = -1; nums[5][7][3] = -1; nums[5][7][4] = -1; nums[5][7][5] = -1; nums[5][7][6] = -1; nums[5][7][7] = -1; nums[5][7][8] = -1;

nums[5][8][8] = -1; nums[5][8][9] = -1;

nums[5][9][8] = -1; nums[5][9][9] = -1;

nums[5][10][8] = -1; nums[5][10][9] = -1;

nums[5][11][0] = -1; nums[5][11][1] = -1; nums[5][11][8] = -1; nums[5][11][9] = -1;

nums[5][12][0] = -1; nums[5][12][1] = -1; nums[5][12][7] = -1; nums[5][12][8] = -1;

nums[5][13][1] = -1; nums[5][13][2] = -1; nums[5][13][3] = -1; nums[5][13][4] = -1; nums[5][13][5] = -1; nums[5][13][6] = -1; nums[5][13][7] = -1;

nums[5][14][2] = -1; nums[5][14][3] = -1; nums[5][14][4] = -1; nums[5][14][5] = -1; nums[5][14][6] = -1;


// 6

nums[6][0][6] = -1; nums[6][0][7] = -1;

nums[6][1][6] = -1;

nums[6][2][5] = -1; nums[6][2][6] = -1;

nums[6][3][4] = -1; nums[6][3][5] = -1;

nums[6][4][4] = -1;

nums[6][5][3] = -1; nums[6][5][4] = -1;

nums[6][6][2] = -1; nums[6][6][3] = -1; nums[6][6][4] = -1; nums[6][6][5] = -1; nums[6][6][6] = -1;

nums[6][7][2] = -1; nums[6][7][3] = -1; nums[6][7][4] = -1; nums[6][7][5] = -1; nums[6][7][6] = -1; nums[6][7][7] = -1; nums[6][7][8] = -1;

nums[6][8][1] = -1; nums[6][8][2] = -1; nums[6][8][7] = -1; nums[6][8][8] = -1;

nums[6][9][0] = -1; nums[6][9][1] = -1; nums[6][9][8] = -1; nums[6][9][9] = -1;

nums[6][10][0] = -1; nums[6][10][1] = -1; nums[6][10][8] = -1; nums[6][10][9] = -1;

nums[6][11][0] = -1; nums[6][11][1] = -1; nums[6][11][8] = -1; nums[6][11][9] = -1;

nums[6][12][0] = -1; nums[6][12][1] = -1; nums[6][12][2] = -1; nums[6][12][7] = -1; nums[6][12][8] = -1;

nums[6][13][1] = -1; nums[6][13][2] = -1; nums[6][13][3] = -1; nums[6][13][4] = -1; nums[6][13][5] = -1; nums[6][13][6] = -1; nums[6][13][7] = -1;

nums[6][14][3] = -1; nums[6][14][4] = -1; nums[6][14][5] = -1;


// 7

nums[7][0][0] = -1; nums[7][0][1] = -1; nums[7][0][2] = -1; nums[7][0][3] = -1; nums[7][0][4] = -1; nums[7][0][5] = -1; nums[7][0][6] = -1; nums[7][0][7] = -1; nums[7][0][8] = -1; nums[7][0][9] = -1;

nums[7][1][0] = -1; nums[7][1][1] = -1; nums[7][1][2] = -1; nums[7][1][6] = -1; nums[7][1][7] = -1; nums[7][1][8] = -1; nums[7][1][9] = -1;

nums[7][2][0] = -1; nums[7][2][1] = -1; nums[7][2][7] = -1; nums[7][2][8] = -1;

nums[7][3][7] = -1;

nums[7][4][7] = -1;

nums[7][5][6] = -1;

nums[7][6][5] = -1; nums[7][6][6] = -1;

nums[7][7][5] = -1;

nums[7][8][5] = -1;

nums[7][9][4] = -1; nums[7][9][5] = -1;

nums[7][10][4] = -1;

nums[7][11][3] = -1; nums[7][11][4] = -1;

nums[7][12][3] = -1;

nums[7][13][2] = -1; nums[7][13][3] = -1;

nums[7][14][2] = -1;


// 8

nums[8][0][4] = -1; nums[8][0][5] = -1;

nums[8][1][2] = -1; nums[8][1][3] = -1; nums[8][1][4] = -1; nums[8][1][5] = -1; nums[8][1][6] = -1; nums[8][1][7] = -1;

nums[8][2][1] = -1; nums[8][2][2] = -1; nums[8][2][7] = -1; nums[8][2][8] = -1;

nums[8][3][1] = -1; nums[8][3][8] = -1;

nums[8][4][0] = -1; nums[8][4][1] = -1; nums[8][4][8] = -1;

nums[8][5][1] = -1; nums[8][5][8] = -1;

nums[8][6][2] = -1; nums[8][6][3] = -1; nums[8][6][4] = -1; nums[8][6][5] = -1; nums[8][6][6] = -1; nums[8][6][7] = -1;

nums[8][7][2] = -1; nums[8][7][3] = -1; nums[8][7][4] = -1; nums[8][7][5] = -1; nums[8][7][6] = -1; nums[8][7][7] = -1;

nums[8][8][1] = -1; nums[8][8][2] = -1; nums[8][8][7] = -1; nums[8][8][8] = -1;

nums[8][9][0] = -1; nums[8][9][1] = -1; nums[8][9][8] = -1; nums[8][9][9] = -1;

nums[8][10][0] = -1; nums[8][10][1] = -1; nums[8][10][8] = -1; nums[8][10][9] = -1;

nums[8][11][0] = -1; nums[8][11][1] = -1; nums[8][11][8] = -1; nums[8][11][9] = -1;

nums[8][12][1] = -1; nums[8][12][2] = -1; nums[8][12][7] = -1; nums[8][12][8] = -1;

nums[8][13][1] = -1; nums[8][13][2] = -1; nums[8][13][3] = -1; nums[8][13][6] = -1; nums[8][13][7] = -1;

nums[8][14][3] = -1; nums[8][14][4] = -1; nums[8][14][5] = -1; nums[8][14][6] = -1;


// 9

nums[9][0][3] = -1; nums[9][0][4] = -1; nums[9][0][5] = -1;

nums[9][1][1] = -1; nums[9][1][2] = -1; nums[9][1][3] = -1; nums[9][1][4] = -1; nums[9][1][5] = -1; nums[9][1][6] = -1; nums[9][1][7] = -1;

nums[9][2][0] = -1; nums[9][2][1] = -1; nums[9][2][7] = -1; nums[9][2][8] = -1;

nums[9][3][0] = -1; nums[9][3][1] = -1; nums[9][3][7] = -1; nums[9][3][8] = -1;

nums[9][4][0] = -1; nums[9][4][1] = -1; nums[9][4][7] = -1; nums[9][4][8] = -1;

nums[9][5][1] = -1; nums[9][5][2] = -1; nums[9][5][8] = -1; nums[9][5][9] = -1;

nums[9][6][1] = -1; nums[9][6][2] = -1; nums[9][6][3] = -1; nums[9][6][8] = -1; nums[9][6][9] = -1;

nums[9][7][3] = -1; nums[9][7][4] = -1; nums[9][7][5] = -1; nums[9][7][6] = -1; nums[9][7][7] = -1; nums[9][7][8] = -1;

nums[9][8][5] = -1; nums[9][8][6] = -1; nums[9][8][7] = -1;

nums[9][9][6] = -1; nums[9][9][7] = -1;

nums[9][10][6] = -1;

nums[9][11][6] = -1; nums[9][11][7] = -1;

nums[9][12][5] = -1;

nums[9][13][4] = -1; nums[9][13][5] = -1;


// 자음 및 모음 중략...


이런식으로 3차원 배열에 이미지 템플릿(자음, 모음, 숫자)에 해당하는 픽셀값을 미리 설정해 두고 추출된 이미지와 1:1 비교해서 일치하는 값만큼 숫자를 증가시켜 그 숫자의 비율을 정확도로 칭하고 그 정확도가 가장 높은 숫자를 인식된 숫자라고 판별합니다.


다음은 실행 결과입니다.





프로그램 코드가 너무 긴 관계로 일부 코드를 생략했습니다. 무조건 복사 붙여넣기 한다고 실행 되지 않을것입니다. 프로그램 원리나 소스코드에 대해 궁금하신분은 댓글 또는 방명록에 남겨주시면 상세하게 답변해드리겠습니다. 

공감♡ 버튼을 눌러주시면 더욱 유용하고 좋은 포스팅으로 찾아뵙겠습니다.








to Top