手写识别,50行R代码

标题当然是唬人的,不过代码真的是50行正好(不算注释和空行啊),可以玩简单的数字识别。玩法很简单,先把附加的RData文件加载到R空间中(就是load("train.RData")这句),然后调用函数guess(),会打开一个空白的图形窗口。按住鼠标左键画一个0到9范围内的数字,然后右击鼠标确认,R会把猜测的结果输出出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
library(grid);
getData = function()
{
    pushViewport(viewport());
    grid.rect();
    px = NULL;
    py = NULL;
    mousedown = function(buttons, x, y)
    {
        if(buttons == 2) return(invisible(1));
        eventEnv$onMouseMove = mousemove;
        NULL
    }
    mousemove = function(buttons, x, y)
    {
        px <<- c(px, x);
        py <<- c(py, y);
        grid.points(x, y);
        NULL
    }
    mouseup = function(buttons, x, y) {    
        eventEnv$onMouseMove = NULL;
        NULL
    }
    setGraphicsEventHandlers(onMouseDown = mousedown,
                             onMouseUp = mouseup);
    eventEnv = getGraphicsEventEnv();
    cat("Click down left mouse button and drag to draw the number,
		right click to finish.\n");
    getGraphicsEvent();
    dev.off();
    s = seq(0, 1, length.out = length(px));
    spx = spline(s, px, n = 500)$y;
    spy = spline(s, py, n = 500)$y;
    return(cbind(spx, spy));
}
 
traceCorr = function(dat1, dat2)
{
    cor(dat1[, 1], dat2[, 1]) + cor(dat1[, 2], dat2[, 2]);
}
 
# recogTrain = list();
# for(i in 1:10)
# {
#     recogTrain[[i]] = getData();
# }
# save(recogTrain, file = "train.RData");
 
load("train.RData");
guess = function(verbose = FALSE)
{
    test = getData();
    coefs = sapply(recogTrain, traceCorr, dat2 = test);
    num = which.max(coefs);
    if(num == 10) num = 0;
    if(verbose) print(coefs);
    cat("I guess what you have input is ", num, ".\n", sep = "");
}

有玩成功了的同志在评论里吼一嗓子啊(貌似4很难识别对),谢谢。

下载:train.RData
发表评论?

17 条评论。

  1. 不错不错,但貌似只识别单个数字?

    4和9不大灵光~~~

    说下方法嘛,貌似是求相关系数找最大的?

  2. 8稍写斜后,猜成了5. 其它都没什么问题。我看只能识别0到9,试了10,识别为0.是根据点的相对位置来识别?

  3. 训练集是不是应该去的更多点呢~这样就会更容易识别了。
    比如,可能由于手写习惯导致的0和6的难以区分,4和6,7和9~~

  4. 报错,什么原因……

    > guess()
    Error in setGraphicsEventEnv(which, as.environment(list(...))) :
    this graphics device does not support event handling

    • Ubuntu吗?
      如果是的话,在getData()的第一行加上X11(type = "Xlib"),并把if(buttons == 2)改成if(length(buttons) > 1)

      • OK~我写了4次8都被识别成了5 :oops: :evil:
        我发现无论字多小,多偏都能识别,看来不是用坐标值,根据什么值算的?没怎么用过spline……

  5. 怡然轩:手写识别,50行R代码 | R客 - pingback on 2011年12月18日 在 10:07
  6. 试过了,发现还是有很多辨别出现错误的,比如很多都会误判为4 6等等,相信这个跟每个人的写法以及它的识别方法还是有关联的

    • 对啊,哈哈,现在训练集里面只有我自己的笔迹,其实可以再补充一些的。不过反正这个只是一个演示,就没考虑那么多了。 :eek:

  7. 哈哈,太牛啦

发表评论


注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackbacks and Pingbacks: