Category Archives: Hack Space

NCWS——Naive Chinese Word Segmentation

Naive Chinese Word Segmentation,蠢萌的中文分词ww

嘛,这学期选了「信息检索」课,然后老师建议我们自己写一下中文分词,我以前遇到要分词的情况一般是用第三方的库,比如scws——Simple Chinese Word Segmentation。这是一个非常好用的库,速度也不错,还默认提供了PHP扩展的编译,使用的是词频词典,并辅以一定的规则识别来达到基本分词。关于scws具体的不再多说,可以去它的官网看看。

这里我只用了最简单的逆向最大匹配来分词,没有加入其他的规则,所以就只能说是naive了。然后需要说明的是词典使用的是scws的词库,然后转为了自己的格式,没有直接用scws的XDB。scws在其下载页面提供了一个XDB的导出工具,我这里是先将XDB导出为文本内容再进行处理的。(ncws只使用了来自scws的公开词库以及对应的词库导出工具)

效果如下(/ω\)

screenshot-ncws

Continue reading NCWS——Naive Chinese Word Segmentation

DPlayer for WordPress

中秋节还是稍前一些的时候,看完了《四月是你的谎言》,真的太棒了,后来还去coursera上看了古典音乐导论ww

然后昨天晚上在逛DIYGod的博客时,发现了这篇post,DPlayer – 最好看的弹幕播放器送给最好看的宫园薰,于是去看了github上的这个项目,DIYGod/DPlayer,又是有不少扩展,但是没有我用的WordPress的QAQ

袖子卷起来(明明穿的是短袖好么!),代码写起来~

先给你们看看最好看的弹幕播放器的效果吧~

Continue reading DPlayer for WordPress

在macOS Sierra及以上系统中为bilibili启用画中画功能

最新的macOS Sierra支持画中画播放了,虽然用的时候不多,现在也还不算特别好用,不过偶尔还是挺方便的,比如写代码的时候开着B站在后面放演唱会之类的,但是遇到精彩的部分却必须要跳回网页,稍微有点不爽呢……

B站最近也开始了HTML5播放器的公测,实现大概是一个video标签,再加上外面一个相同大小的div,div内应该是个svg,弹幕由js解析,并通过svg画出来。那么理论上来讲,使用了video标签的话,就是系统可以自行解码的视频,比如mp4,mov这类。B站上绝大多数要么是mp4,要么就是flv。如果某个视频只有flv的话,就没办法了。不过只要是mp4的话,就可以使用macOS Sierra的画中画播放。

Continue reading 在macOS Sierra及以上系统中为bilibili启用画中画功能

Magic Image(2)——Mathematical Model

上次试着用threshold的方式写(Magic image——Alpha Channel),虽然有那么些感觉了,但是最终的图像是二值化的,效果不好。

于是今天特意找了Alpha Blending的资料,根据wiki页面给出的公式:

$$\left\{\begin{aligned}
out_A &= src_A + dst_A(1-src_A)\\
out_{RGB} &= \frac{(src_{RGB}src_A + dst_{RGB}dst_A(1-src_A))}{out_A}\\
out_A &= 0 \implies out_{RGB} = 0
\end{aligned}\right.
$$

当我们的destination background不透明时,\(dst_A = 1\),于是有

$$\left\{\begin{aligned}
out_A &= 1\\
out_{RGB} &= src_{RGB}src_A + dst_{RGB}(1-src_A)
\end{aligned}\right.
$$

于是,根据我们的实际情况,对于合并后的图像I,给定背景B时,有如下等式:
$$\left\{\begin{aligned}
out_A &= 1\\
out_{G} &= I_{G}I_A + B_{G}(1-I_A)
\end{aligned}\right.
$$

Continue reading Magic Image(2)——Mathematical Model

Standard A* Search Algorithm in C++

在看了NTU的AI课程之后,试着用C++来实现了A*搜索算法。它的思想就是Avoid expanding paths that are already expensive.。标准的A*搜索算法描述如下:

给出带权无向图,初始顶点,目标顶点,以及evaulation function。Evalutaion function包括

  • g(n):为到达顶点n,当前已有的花费(cost so far to reach n)
  • h(n):一个 从任意顶点 到 目标顶点 的估计花费(estimated cost to goal from n)
  • f(n):从 初始顶点 到 目标顶点 的估计花费(estimated total cost from the starting node to goal through n)

f(n) = h(n) + g(n)

 

例如有三个地点A, B, C,它们之间的图如下

A —— B —— C

A —— B权重为30,B —— C权重为40,

A —— C的直线距离为50,但是并没有A——C这条边(即不能直接从A开始,只经过一条边就到达C)

现在,给出初始顶点为A,目标顶点为C,h(n)如下

h(A) = 50

h(B) = 40

h(C) = 0

在一开始,我们将A放入名为froniter的优先队列中,froniter按照f(n)的值升序排序。

那么我们有f(A) = h(A) + g(A)。h(A)是由用户直接给出的,等于50。g(A)是我们为了到达C,已有的花费,在这个例子中,可以理解为已经走过的路程,因为我们是一开始就在A,还没有开始走,所以g(A)为0。于是f(A) = h(A) + g(A) = 50 + 0 = 50

froniter中的数据如下:

current from g(current) h(current)
A A 0 50

Continue reading Standard A* Search Algorithm in C++

A simple EventEmitter in C++

EventEmitter coming with node.js is handy most of the time, and I implement this useful utility in C++ after finishing writing Functor. Yes, we need Functor to make it much more easier to write this fabulous utility. (Why don't you use lamdba? I'll talk about that later in this post)

It's extremely simple to use EventEmitter in node.js

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
    console.log('an event occurred!');
});
myEmitter.emit('event');

——https://nodejs.org/api/events.html

And the C++ version of EventEmitter need to be as easy as it is in node.js. As a matter of fact, this class made it.

#include <iostream>
#include <sstream>
#include <thread>
#include <vector>
#include "EventEmitter.hpp"

using namespace std;

class emitter : public EventEmitter {
};

int main(int argc, const char * argv[]) {
    emitter emitter;
    emitter.on("event", [&emitter](int data) {
        ostringstream osstream;
        osstream << "data: " << data << '\n';
        std::cout << osstream.str();
    });

    vector<thread> threads;
    for (int i = 0; i < 10; i++) {
        threads.emplace_back([&emitter, i]() {
            emitter.emit("event", i);
        });
    }

    for (auto &t : threads) t.join();
}

Continue reading A simple EventEmitter in C++

A simple EventEmitter in C++

node.js里面的EventEmitter非常好用,于是上次写完Functor之后,就顺理成章的写了这个EventEmitter,或者说,就是为了实现这个EventEmitter才写的Functor(后文会提到为什么要Functor,毕竟如果只看Functor本身的话,还不如直接用lamdba方便)。

在node.js中,使用EventEmitter非常简单,

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
    console.log('an event occurred!');
});
myEmitter.emit('event');

——https://nodejs.org/api/events.html

那么现在这个C++版的EventEmitter也必须做到这样简单易用,事实上,它也的确和node.js的使用方式类似。

#include <iostream>
#include <sstream>
#include <thread>
#include <vector>
#include "EventEmitter.hpp"

using namespace std;

class emitter : public EventEmitter {
};

int main(int argc, const char * argv[]) {
    emitter emitter;
    emitter.on("event", [&emitter](int data) {
        ostringstream osstream;
        osstream << "data: " << data << '\n';
        std::cout << osstream.str();
    });

    vector<thread> threads;
    for (int i = 0; i < 10; i++) {
        threads.emplace_back([&emitter, i]() {
            emitter.emit("event", i);
        });
    }

    for (auto &t : threads) t.join();
}

Continue reading A simple EventEmitter in C++