feat: 切换后端至PaddleOCR-NCNN,切换工程为CMake
1.项目后端整体迁移至PaddleOCR-NCNN算法,已通过基本的兼容性测试 2.工程改为使用CMake组织,后续为了更好地兼容第三方库,不再提供QMake工程 3.重整权利声明文件,重整代码工程,确保最小化侵权风险 Log: 切换后端至PaddleOCR-NCNN,切换工程为CMake Change-Id: I4d5d2c5d37505a4a24b389b1a4c5d12f17bfa38c
This commit is contained in:
		
							
								
								
									
										42
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/java/test/MLTest.java
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/java/test/MLTest.java
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
			
		||||
package org.opencv.test.ml;
 | 
			
		||||
 | 
			
		||||
import org.opencv.ml.Ml;
 | 
			
		||||
import org.opencv.ml.SVM;
 | 
			
		||||
import org.opencv.core.Mat;
 | 
			
		||||
import org.opencv.core.MatOfFloat;
 | 
			
		||||
import org.opencv.core.MatOfInt;
 | 
			
		||||
import org.opencv.core.CvType;
 | 
			
		||||
import org.opencv.test.OpenCVTestCase;
 | 
			
		||||
import org.opencv.test.OpenCVTestRunner;
 | 
			
		||||
 | 
			
		||||
public class MLTest extends OpenCVTestCase {
 | 
			
		||||
 | 
			
		||||
    public void testSaveLoad() {
 | 
			
		||||
        Mat samples = new MatOfFloat(new float[] {
 | 
			
		||||
            5.1f, 3.5f, 1.4f, 0.2f,
 | 
			
		||||
            4.9f, 3.0f, 1.4f, 0.2f,
 | 
			
		||||
            4.7f, 3.2f, 1.3f, 0.2f,
 | 
			
		||||
            4.6f, 3.1f, 1.5f, 0.2f,
 | 
			
		||||
            5.0f, 3.6f, 1.4f, 0.2f,
 | 
			
		||||
            7.0f, 3.2f, 4.7f, 1.4f,
 | 
			
		||||
            6.4f, 3.2f, 4.5f, 1.5f,
 | 
			
		||||
            6.9f, 3.1f, 4.9f, 1.5f,
 | 
			
		||||
            5.5f, 2.3f, 4.0f, 1.3f,
 | 
			
		||||
            6.5f, 2.8f, 4.6f, 1.5f
 | 
			
		||||
        }).reshape(1, 10);
 | 
			
		||||
        Mat responses = new MatOfInt(new int[] {
 | 
			
		||||
            0, 0, 0, 0, 0, 1, 1, 1, 1, 1
 | 
			
		||||
        }).reshape(1, 10);
 | 
			
		||||
        SVM saved = SVM.create();
 | 
			
		||||
        assertFalse(saved.isTrained());
 | 
			
		||||
 | 
			
		||||
        saved.train(samples, Ml.ROW_SAMPLE, responses);
 | 
			
		||||
        assertTrue(saved.isTrained());
 | 
			
		||||
 | 
			
		||||
        String filename = OpenCVTestRunner.getTempFileName("yml");
 | 
			
		||||
        saved.save(filename);
 | 
			
		||||
        SVM loaded = SVM.load(filename);
 | 
			
		||||
        assertTrue(loaded.isTrained());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/objc/gen_dict.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/objc/gen_dict.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
    "enum_fix" : {
 | 
			
		||||
        "EM" : { "Types": "EMTypes" },
 | 
			
		||||
        "SVM" : { "Types": "SVMTypes" },
 | 
			
		||||
        "KNearest" : { "Types": "KNearestTypes" },
 | 
			
		||||
        "DTrees" : { "Flags": "DTreeFlags" },
 | 
			
		||||
        "StatModel" : { "Flags": "StatModelFlags" }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/python/pyopencv_ml.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/python/pyopencv_ml.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
template<>
 | 
			
		||||
bool pyopencv_to(PyObject *obj, CvTermCriteria& dst, const ArgInfo& info)
 | 
			
		||||
{
 | 
			
		||||
    CV_UNUSED(info);
 | 
			
		||||
    if(!obj)
 | 
			
		||||
        return true;
 | 
			
		||||
    return PyArg_ParseTuple(obj, "iid", &dst.type, &dst.max_iter, &dst.epsilon) > 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
bool pyopencv_to(PyObject* obj, CvSlice& r, const ArgInfo& info)
 | 
			
		||||
{
 | 
			
		||||
    CV_UNUSED(info);
 | 
			
		||||
    if(!obj || obj == Py_None)
 | 
			
		||||
        return true;
 | 
			
		||||
    if(PyObject_Size(obj) == 0)
 | 
			
		||||
    {
 | 
			
		||||
        r = CV_WHOLE_SEQ;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return PyArg_ParseTuple(obj, "ii", &r.start_index, &r.end_index) > 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										201
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/python/test/test_digits.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/python/test/test_digits.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,201 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
SVM and KNearest digit recognition.
 | 
			
		||||
 | 
			
		||||
Sample loads a dataset of handwritten digits from '../data/digits.png'.
 | 
			
		||||
Then it trains a SVM and KNearest classifiers on it and evaluates
 | 
			
		||||
their accuracy.
 | 
			
		||||
 | 
			
		||||
Following preprocessing is applied to the dataset:
 | 
			
		||||
 - Moment-based image deskew (see deskew())
 | 
			
		||||
 - Digit images are split into 4 10x10 cells and 16-bin
 | 
			
		||||
   histogram of oriented gradients is computed for each
 | 
			
		||||
   cell
 | 
			
		||||
 - Transform histograms to space with Hellinger metric (see [1] (RootSIFT))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[1] R. Arandjelovic, A. Zisserman
 | 
			
		||||
    "Three things everyone should know to improve object retrieval"
 | 
			
		||||
    http://www.robots.ox.ac.uk/~vgg/publications/2012/Arandjelovic12/arandjelovic12.pdf
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Python 2/3 compatibility
 | 
			
		||||
from __future__ import print_function
 | 
			
		||||
 | 
			
		||||
# built-in modules
 | 
			
		||||
from multiprocessing.pool import ThreadPool
 | 
			
		||||
 | 
			
		||||
import cv2 as cv
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
from numpy.linalg import norm
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SZ = 20 # size of each digit is SZ x SZ
 | 
			
		||||
CLASS_N = 10
 | 
			
		||||
DIGITS_FN = 'samples/data/digits.png'
 | 
			
		||||
 | 
			
		||||
def split2d(img, cell_size, flatten=True):
 | 
			
		||||
    h, w = img.shape[:2]
 | 
			
		||||
    sx, sy = cell_size
 | 
			
		||||
    cells = [np.hsplit(row, w//sx) for row in np.vsplit(img, h//sy)]
 | 
			
		||||
    cells = np.array(cells)
 | 
			
		||||
    if flatten:
 | 
			
		||||
        cells = cells.reshape(-1, sy, sx)
 | 
			
		||||
    return cells
 | 
			
		||||
 | 
			
		||||
def deskew(img):
 | 
			
		||||
    m = cv.moments(img)
 | 
			
		||||
    if abs(m['mu02']) < 1e-2:
 | 
			
		||||
        return img.copy()
 | 
			
		||||
    skew = m['mu11']/m['mu02']
 | 
			
		||||
    M = np.float32([[1, skew, -0.5*SZ*skew], [0, 1, 0]])
 | 
			
		||||
    img = cv.warpAffine(img, M, (SZ, SZ), flags=cv.WARP_INVERSE_MAP | cv.INTER_LINEAR)
 | 
			
		||||
    return img
 | 
			
		||||
 | 
			
		||||
class StatModel(object):
 | 
			
		||||
    def load(self, fn):
 | 
			
		||||
        self.model.load(fn)  # Known bug: https://github.com/opencv/opencv/issues/4969
 | 
			
		||||
    def save(self, fn):
 | 
			
		||||
        self.model.save(fn)
 | 
			
		||||
 | 
			
		||||
class KNearest(StatModel):
 | 
			
		||||
    def __init__(self, k = 3):
 | 
			
		||||
        self.k = k
 | 
			
		||||
        self.model = cv.ml.KNearest_create()
 | 
			
		||||
 | 
			
		||||
    def train(self, samples, responses):
 | 
			
		||||
        self.model.train(samples, cv.ml.ROW_SAMPLE, responses)
 | 
			
		||||
 | 
			
		||||
    def predict(self, samples):
 | 
			
		||||
        _retval, results, _neigh_resp, _dists = self.model.findNearest(samples, self.k)
 | 
			
		||||
        return results.ravel()
 | 
			
		||||
 | 
			
		||||
class SVM(StatModel):
 | 
			
		||||
    def __init__(self, C = 1, gamma = 0.5):
 | 
			
		||||
        self.model = cv.ml.SVM_create()
 | 
			
		||||
        self.model.setGamma(gamma)
 | 
			
		||||
        self.model.setC(C)
 | 
			
		||||
        self.model.setKernel(cv.ml.SVM_RBF)
 | 
			
		||||
        self.model.setType(cv.ml.SVM_C_SVC)
 | 
			
		||||
 | 
			
		||||
    def train(self, samples, responses):
 | 
			
		||||
        self.model.train(samples, cv.ml.ROW_SAMPLE, responses)
 | 
			
		||||
 | 
			
		||||
    def predict(self, samples):
 | 
			
		||||
        return self.model.predict(samples)[1].ravel()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def evaluate_model(model, digits, samples, labels):
 | 
			
		||||
    resp = model.predict(samples)
 | 
			
		||||
    err = (labels != resp).mean()
 | 
			
		||||
 | 
			
		||||
    confusion = np.zeros((10, 10), np.int32)
 | 
			
		||||
    for i, j in zip(labels, resp):
 | 
			
		||||
        confusion[int(i), int(j)] += 1
 | 
			
		||||
 | 
			
		||||
    return err, confusion
 | 
			
		||||
 | 
			
		||||
def preprocess_simple(digits):
 | 
			
		||||
    return np.float32(digits).reshape(-1, SZ*SZ) / 255.0
 | 
			
		||||
 | 
			
		||||
def preprocess_hog(digits):
 | 
			
		||||
    samples = []
 | 
			
		||||
    for img in digits:
 | 
			
		||||
        gx = cv.Sobel(img, cv.CV_32F, 1, 0)
 | 
			
		||||
        gy = cv.Sobel(img, cv.CV_32F, 0, 1)
 | 
			
		||||
        mag, ang = cv.cartToPolar(gx, gy)
 | 
			
		||||
        bin_n = 16
 | 
			
		||||
        bin = np.int32(bin_n*ang/(2*np.pi))
 | 
			
		||||
        bin_cells = bin[:10,:10], bin[10:,:10], bin[:10,10:], bin[10:,10:]
 | 
			
		||||
        mag_cells = mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]
 | 
			
		||||
        hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]
 | 
			
		||||
        hist = np.hstack(hists)
 | 
			
		||||
 | 
			
		||||
        # transform to Hellinger kernel
 | 
			
		||||
        eps = 1e-7
 | 
			
		||||
        hist /= hist.sum() + eps
 | 
			
		||||
        hist = np.sqrt(hist)
 | 
			
		||||
        hist /= norm(hist) + eps
 | 
			
		||||
 | 
			
		||||
        samples.append(hist)
 | 
			
		||||
    return np.float32(samples)
 | 
			
		||||
 | 
			
		||||
from tests_common import NewOpenCVTests
 | 
			
		||||
 | 
			
		||||
class digits_test(NewOpenCVTests):
 | 
			
		||||
 | 
			
		||||
    def load_digits(self, fn):
 | 
			
		||||
        digits_img = self.get_sample(fn, 0)
 | 
			
		||||
        digits = split2d(digits_img, (SZ, SZ))
 | 
			
		||||
        labels = np.repeat(np.arange(CLASS_N), len(digits)/CLASS_N)
 | 
			
		||||
        return digits, labels
 | 
			
		||||
 | 
			
		||||
    def test_digits(self):
 | 
			
		||||
 | 
			
		||||
        digits, labels = self.load_digits(DIGITS_FN)
 | 
			
		||||
 | 
			
		||||
        # shuffle digits
 | 
			
		||||
        rand = np.random.RandomState(321)
 | 
			
		||||
        shuffle = rand.permutation(len(digits))
 | 
			
		||||
        digits, labels = digits[shuffle], labels[shuffle]
 | 
			
		||||
 | 
			
		||||
        digits2 = list(map(deskew, digits))
 | 
			
		||||
        samples = preprocess_hog(digits2)
 | 
			
		||||
 | 
			
		||||
        train_n = int(0.9*len(samples))
 | 
			
		||||
        _digits_train, digits_test = np.split(digits2, [train_n])
 | 
			
		||||
        samples_train, samples_test = np.split(samples, [train_n])
 | 
			
		||||
        labels_train, labels_test = np.split(labels, [train_n])
 | 
			
		||||
        errors = list()
 | 
			
		||||
        confusionMatrixes = list()
 | 
			
		||||
 | 
			
		||||
        model = KNearest(k=4)
 | 
			
		||||
        model.train(samples_train, labels_train)
 | 
			
		||||
        error, confusion = evaluate_model(model, digits_test, samples_test, labels_test)
 | 
			
		||||
        errors.append(error)
 | 
			
		||||
        confusionMatrixes.append(confusion)
 | 
			
		||||
 | 
			
		||||
        model = SVM(C=2.67, gamma=5.383)
 | 
			
		||||
        model.train(samples_train, labels_train)
 | 
			
		||||
        error, confusion = evaluate_model(model, digits_test, samples_test, labels_test)
 | 
			
		||||
        errors.append(error)
 | 
			
		||||
        confusionMatrixes.append(confusion)
 | 
			
		||||
 | 
			
		||||
        eps = 0.001
 | 
			
		||||
        normEps = len(samples_test) * 0.02
 | 
			
		||||
 | 
			
		||||
        confusionKNN = [[45,  0,  0,  0,  0,  0,  0,  0,  0,  0],
 | 
			
		||||
         [ 0, 57,  0,  0,  0,  0,  0,  0,  0,  0],
 | 
			
		||||
         [ 0,  0, 59,  1,  0,  0,  0,  0,  1,  0],
 | 
			
		||||
         [ 0,  0,  0, 43,  0,  0,  0,  1,  0,  0],
 | 
			
		||||
         [ 0,  0,  0,  0, 38,  0,  2,  0,  0,  0],
 | 
			
		||||
         [ 0,  0,  0,  2,  0, 48,  0,  0,  1,  0],
 | 
			
		||||
         [ 0,  1,  0,  0,  0,  0, 51,  0,  0,  0],
 | 
			
		||||
         [ 0,  0,  1,  0,  0,  0,  0, 54,  0,  0],
 | 
			
		||||
         [ 0,  0,  0,  0,  0,  1,  0,  0, 46,  0],
 | 
			
		||||
         [ 1,  1,  0,  1,  1,  0,  0,  0,  2, 42]]
 | 
			
		||||
 | 
			
		||||
        confusionSVM = [[45,  0,  0,  0,  0,  0,  0,  0,  0,  0],
 | 
			
		||||
          [ 0, 57,  0,  0,  0,  0,  0,  0,  0,  0],
 | 
			
		||||
          [ 0,  0, 59,  2,  0,  0,  0,  0,  0,  0],
 | 
			
		||||
          [ 0,  0,  0, 43,  0,  0,  0,  1,  0,  0],
 | 
			
		||||
          [ 0,  0,  0,  0, 40,  0,  0,  0,  0,  0],
 | 
			
		||||
          [ 0,  0,  0,  1,  0, 50,  0,  0,  0,  0],
 | 
			
		||||
          [ 0,  0,  0,  0,  1,  0,  51, 0,  0,  0],
 | 
			
		||||
          [ 0,  0,  1,  0,  0,  0,  0,  54, 0,  0],
 | 
			
		||||
          [ 0,  0,  0,  0,  0,  0,  0,  0, 47,  0],
 | 
			
		||||
          [ 0,  1,  0,  1,  0,  0,  0,  0,  1, 45]]
 | 
			
		||||
 | 
			
		||||
        self.assertLess(cv.norm(confusionMatrixes[0] - confusionKNN, cv.NORM_L1), normEps)
 | 
			
		||||
        self.assertLess(cv.norm(confusionMatrixes[1] - confusionSVM, cv.NORM_L1), normEps)
 | 
			
		||||
 | 
			
		||||
        self.assertLess(errors[0] - 0.034, eps)
 | 
			
		||||
        self.assertLess(errors[1] - 0.018, eps)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    NewOpenCVTests.bootstrap()
 | 
			
		||||
							
								
								
									
										40
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/python/test/test_goodfeatures.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/python/test/test_goodfeatures.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
 | 
			
		||||
# Python 2/3 compatibility
 | 
			
		||||
from __future__ import print_function
 | 
			
		||||
 | 
			
		||||
import cv2 as cv
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
from tests_common import NewOpenCVTests
 | 
			
		||||
 | 
			
		||||
class TestGoodFeaturesToTrack_test(NewOpenCVTests):
 | 
			
		||||
    def test_goodFeaturesToTrack(self):
 | 
			
		||||
        arr = self.get_sample('samples/data/lena.jpg', 0)
 | 
			
		||||
        original = arr.copy()
 | 
			
		||||
        threshes = [ x / 100. for x in range(1,10) ]
 | 
			
		||||
        numPoints = 20000
 | 
			
		||||
 | 
			
		||||
        results = dict([(t, cv.goodFeaturesToTrack(arr, numPoints, t, 2, useHarrisDetector=True)) for t in threshes])
 | 
			
		||||
        # Check that GoodFeaturesToTrack has not modified input image
 | 
			
		||||
        self.assertTrue(arr.tostring() == original.tostring())
 | 
			
		||||
        # Check for repeatability
 | 
			
		||||
        for i in range(1):
 | 
			
		||||
            results2 = dict([(t, cv.goodFeaturesToTrack(arr, numPoints, t, 2, useHarrisDetector=True)) for t in threshes])
 | 
			
		||||
            for t in threshes:
 | 
			
		||||
                self.assertTrue(len(results2[t]) == len(results[t]))
 | 
			
		||||
                for i in range(len(results[t])):
 | 
			
		||||
                    self.assertTrue(cv.norm(results[t][i][0] - results2[t][i][0]) == 0)
 | 
			
		||||
 | 
			
		||||
        for t0,t1 in zip(threshes, threshes[1:]):
 | 
			
		||||
            r0 = results[t0]
 | 
			
		||||
            r1 = results[t1]
 | 
			
		||||
            # Increasing thresh should make result list shorter
 | 
			
		||||
            self.assertTrue(len(r0) > len(r1))
 | 
			
		||||
            # Increasing thresh should monly truncate result list
 | 
			
		||||
            for i in range(len(r1)):
 | 
			
		||||
                self.assertTrue(cv.norm(r1[i][0] - r0[i][0])==0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    NewOpenCVTests.bootstrap()
 | 
			
		||||
							
								
								
									
										13
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/python/test/test_knearest.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/python/test/test_knearest.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
import cv2 as cv
 | 
			
		||||
 | 
			
		||||
from tests_common import NewOpenCVTests
 | 
			
		||||
 | 
			
		||||
class knearest_test(NewOpenCVTests):
 | 
			
		||||
    def test_load(self):
 | 
			
		||||
        k_nearest = cv.ml.KNearest_load(self.find_file("ml/opencv_ml_knn.xml"))
 | 
			
		||||
        self.assertFalse(k_nearest.empty())
 | 
			
		||||
        self.assertTrue(k_nearest.isTrained())
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    NewOpenCVTests.bootstrap()
 | 
			
		||||
							
								
								
									
										171
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/python/test/test_letter_recog.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								3rdparty/opencv-4.5.4/modules/ml/misc/python/test/test_letter_recog.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,171 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
The sample demonstrates how to train Random Trees classifier
 | 
			
		||||
(or Boosting classifier, or MLP, or Knearest, or Support Vector Machines) using the provided dataset.
 | 
			
		||||
 | 
			
		||||
We use the sample database letter-recognition.data
 | 
			
		||||
from UCI Repository, here is the link:
 | 
			
		||||
 | 
			
		||||
Newman, D.J. & Hettich, S. & Blake, C.L. & Merz, C.J. (1998).
 | 
			
		||||
UCI Repository of machine learning databases
 | 
			
		||||
[http://www.ics.uci.edu/~mlearn/MLRepository.html].
 | 
			
		||||
Irvine, CA: University of California, Department of Information and Computer Science.
 | 
			
		||||
 | 
			
		||||
The dataset consists of 20000 feature vectors along with the
 | 
			
		||||
responses - capital latin letters A..Z.
 | 
			
		||||
The first 10000 samples are used for training
 | 
			
		||||
and the remaining 10000 - to test the classifier.
 | 
			
		||||
======================================================
 | 
			
		||||
  Models: RTrees, KNearest, Boost, SVM, MLP
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
# Python 2/3 compatibility
 | 
			
		||||
from __future__ import print_function
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
import cv2 as cv
 | 
			
		||||
 | 
			
		||||
def load_base(fn):
 | 
			
		||||
    a = np.loadtxt(fn, np.float32, delimiter=',', converters={ 0 : lambda ch : ord(ch)-ord('A') })
 | 
			
		||||
    samples, responses = a[:,1:], a[:,0]
 | 
			
		||||
    return samples, responses
 | 
			
		||||
 | 
			
		||||
class LetterStatModel(object):
 | 
			
		||||
    class_n = 26
 | 
			
		||||
    train_ratio = 0.5
 | 
			
		||||
 | 
			
		||||
    def load(self, fn):
 | 
			
		||||
        self.model.load(fn)
 | 
			
		||||
    def save(self, fn):
 | 
			
		||||
        self.model.save(fn)
 | 
			
		||||
 | 
			
		||||
    def unroll_samples(self, samples):
 | 
			
		||||
        sample_n, var_n = samples.shape
 | 
			
		||||
        new_samples = np.zeros((sample_n * self.class_n, var_n+1), np.float32)
 | 
			
		||||
        new_samples[:,:-1] = np.repeat(samples, self.class_n, axis=0)
 | 
			
		||||
        new_samples[:,-1] = np.tile(np.arange(self.class_n), sample_n)
 | 
			
		||||
        return new_samples
 | 
			
		||||
 | 
			
		||||
    def unroll_responses(self, responses):
 | 
			
		||||
        sample_n = len(responses)
 | 
			
		||||
        new_responses = np.zeros(sample_n*self.class_n, np.int32)
 | 
			
		||||
        resp_idx = np.int32( responses + np.arange(sample_n)*self.class_n )
 | 
			
		||||
        new_responses[resp_idx] = 1
 | 
			
		||||
        return new_responses
 | 
			
		||||
 | 
			
		||||
class RTrees(LetterStatModel):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.model = cv.ml.RTrees_create()
 | 
			
		||||
 | 
			
		||||
    def train(self, samples, responses):
 | 
			
		||||
        #sample_n, var_n = samples.shape
 | 
			
		||||
        self.model.setMaxDepth(20)
 | 
			
		||||
        self.model.train(samples, cv.ml.ROW_SAMPLE, responses.astype(int))
 | 
			
		||||
 | 
			
		||||
    def predict(self, samples):
 | 
			
		||||
        _ret, resp = self.model.predict(samples)
 | 
			
		||||
        return resp.ravel()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class KNearest(LetterStatModel):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.model = cv.ml.KNearest_create()
 | 
			
		||||
 | 
			
		||||
    def train(self, samples, responses):
 | 
			
		||||
        self.model.train(samples, cv.ml.ROW_SAMPLE, responses)
 | 
			
		||||
 | 
			
		||||
    def predict(self, samples):
 | 
			
		||||
        _retval, results, _neigh_resp, _dists = self.model.findNearest(samples, k = 10)
 | 
			
		||||
        return results.ravel()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Boost(LetterStatModel):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.model = cv.ml.Boost_create()
 | 
			
		||||
 | 
			
		||||
    def train(self, samples, responses):
 | 
			
		||||
        _sample_n, var_n = samples.shape
 | 
			
		||||
        new_samples = self.unroll_samples(samples)
 | 
			
		||||
        new_responses = self.unroll_responses(responses)
 | 
			
		||||
        var_types = np.array([cv.ml.VAR_NUMERICAL] * var_n + [cv.ml.VAR_CATEGORICAL, cv.ml.VAR_CATEGORICAL], np.uint8)
 | 
			
		||||
 | 
			
		||||
        self.model.setWeakCount(15)
 | 
			
		||||
        self.model.setMaxDepth(10)
 | 
			
		||||
        self.model.train(cv.ml.TrainData_create(new_samples, cv.ml.ROW_SAMPLE, new_responses.astype(int), varType = var_types))
 | 
			
		||||
 | 
			
		||||
    def predict(self, samples):
 | 
			
		||||
        new_samples = self.unroll_samples(samples)
 | 
			
		||||
        _ret, resp = self.model.predict(new_samples)
 | 
			
		||||
 | 
			
		||||
        return resp.ravel().reshape(-1, self.class_n).argmax(1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SVM(LetterStatModel):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.model = cv.ml.SVM_create()
 | 
			
		||||
 | 
			
		||||
    def train(self, samples, responses):
 | 
			
		||||
        self.model.setType(cv.ml.SVM_C_SVC)
 | 
			
		||||
        self.model.setC(1)
 | 
			
		||||
        self.model.setKernel(cv.ml.SVM_RBF)
 | 
			
		||||
        self.model.setGamma(.1)
 | 
			
		||||
        self.model.train(samples, cv.ml.ROW_SAMPLE, responses.astype(int))
 | 
			
		||||
 | 
			
		||||
    def predict(self, samples):
 | 
			
		||||
        _ret, resp = self.model.predict(samples)
 | 
			
		||||
        return resp.ravel()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MLP(LetterStatModel):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.model = cv.ml.ANN_MLP_create()
 | 
			
		||||
 | 
			
		||||
    def train(self, samples, responses):
 | 
			
		||||
        _sample_n, var_n = samples.shape
 | 
			
		||||
        new_responses = self.unroll_responses(responses).reshape(-1, self.class_n)
 | 
			
		||||
        layer_sizes = np.int32([var_n, 100, 100, self.class_n])
 | 
			
		||||
 | 
			
		||||
        self.model.setLayerSizes(layer_sizes)
 | 
			
		||||
        self.model.setTrainMethod(cv.ml.ANN_MLP_BACKPROP)
 | 
			
		||||
        self.model.setBackpropMomentumScale(0)
 | 
			
		||||
        self.model.setBackpropWeightScale(0.001)
 | 
			
		||||
        self.model.setTermCriteria((cv.TERM_CRITERIA_COUNT, 20, 0.01))
 | 
			
		||||
        self.model.setActivationFunction(cv.ml.ANN_MLP_SIGMOID_SYM, 2, 1)
 | 
			
		||||
 | 
			
		||||
        self.model.train(samples, cv.ml.ROW_SAMPLE, np.float32(new_responses))
 | 
			
		||||
 | 
			
		||||
    def predict(self, samples):
 | 
			
		||||
        _ret, resp = self.model.predict(samples)
 | 
			
		||||
        return resp.argmax(-1)
 | 
			
		||||
 | 
			
		||||
from tests_common import NewOpenCVTests
 | 
			
		||||
 | 
			
		||||
class letter_recog_test(NewOpenCVTests):
 | 
			
		||||
 | 
			
		||||
    def test_letter_recog(self):
 | 
			
		||||
 | 
			
		||||
        eps = 0.01
 | 
			
		||||
 | 
			
		||||
        models = [RTrees, KNearest, Boost, SVM, MLP]
 | 
			
		||||
        models = dict( [(cls.__name__.lower(), cls) for cls in models] )
 | 
			
		||||
        testErrors = {RTrees: (98.930000, 92.390000), KNearest: (94.960000, 92.010000),
 | 
			
		||||
         Boost: (85.970000, 74.920000), SVM: (99.780000, 95.680000), MLP: (90.060000, 87.410000)}
 | 
			
		||||
 | 
			
		||||
        for model in models:
 | 
			
		||||
            Model = models[model]
 | 
			
		||||
            classifier = Model()
 | 
			
		||||
 | 
			
		||||
            samples, responses = load_base(self.repoPath + '/samples/data/letter-recognition.data')
 | 
			
		||||
            train_n = int(len(samples)*classifier.train_ratio)
 | 
			
		||||
 | 
			
		||||
            classifier.train(samples[:train_n], responses[:train_n])
 | 
			
		||||
            train_rate = np.mean(classifier.predict(samples[:train_n]) == responses[:train_n].astype(int))
 | 
			
		||||
            test_rate  = np.mean(classifier.predict(samples[train_n:]) == responses[train_n:].astype(int))
 | 
			
		||||
 | 
			
		||||
            self.assertLess(train_rate - testErrors[Model][0], eps)
 | 
			
		||||
            self.assertLess(test_rate - testErrors[Model][1], eps)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    NewOpenCVTests.bootstrap()
 | 
			
		||||
		Reference in New Issue
	
	Block a user