Unicodeのすべての文字を1ページで


この記事で作るもの:Unicode 6.0のすべての文字を1ページで (PDF, 23MB)

4327377368ヨハネス・ベルガーハウゼン, シリ・ポアランガン『世界の文字と記号の大図鑑 ー Unicode 6.0の全グリフ』(研究社, 2014)の著者はUnicode 6.0の全109242文字2時間30分かけて見るビデオの作者ですか。今度は1024ページの書籍。「Decodeunicode」で画像検索すると原著が出てきますが、楽しみですね。(追記:世界の文字と記号の大図鑑

「Unicodeのすべての文字を印刷した本って、前にもなかったっけ?」と思って本棚を探したのですが、勘違いでした。

0321480910頭に浮かんだのはThe Unicode Consortium『The Unicode Standard, Version 5.0』(Addison-Wesley Professional, 2006)(文献リストあり、索引なし)だったのですが、この本は、(1) The Unicode Standard、(2) Code Charts (PDF)から漢字を除いたもの、(3) Han Radical-Stroke Index (PDF)という構成でした。つまり、漢字はコードポイント順に一つずつではなく、Han Radical-Stroke Indexという形で掲載されているだけでした。

Unicode 5.0より後は、紙媒体ではないようですが、たとえば6.0について同じことをするなら、 (1) The Unicode Standard (PDF)、(2) Code Charts (PDF)、(3) Han Radical-Stroke Index (PDF)を使うことになるのでしょう。(Code Chartsには漢字も含まれているので、「文字の一覧(番号順)」が欲しいだけならCode Chartsだけで十分です。)

これらの資料もいいのですが、こういうのは、自分でもちょっとやってみたいところです。例えば、Unicodeの全文字を1ページに、なんてことも、自分で作れるようになればできます。

というわけで、必要なデータをEnumerated Versions of The Unicode Standardから探して作ろうとしたら、これがなかなか面倒でした。

Unicode 6.0の全文字は、UnicodeData.txtに載っているはずですが、この第1列をHTMLの数値文字参照に置き換えるだけでは終わりません。

UnicodeData.txtには、CJK統合漢字など、1行1文字になっていない部分があります。それを補うのは面倒なので、Unicode 5.1以降で導入されたUnicode Character
Database in XML
を使うことにします。このXMLファイルは、char要素1個が1文字に対応します。

XMLファイルには、印刷できない文字?も含まれているので、それを除外しなければなりません。Unicode 6.0のコードポイントは109449個ありますが、そのうちGraphic Characterは109242個です(参照)。『世界の文字と記号の大図鑑』の109242文字というのはこれのことなのでしょう。Graphic Characterの定義General_Category ValuesThe Unicode Standard Chapter 2 General Structureの「Table 2-3. Types of Code Points」を見ると、char要素のgc属性値がCから始まるものとZl, Zpになっているものは除外しなければならないことがわかります。(異体字セレクタのような、明らかに印刷不能な文字が残るのですが、とりあえずはそのままにします。それを使う異体字もここでは数えません。)

というわけで、ちょっとスクリプトを書いて、Unicode 6.0の文字の一覧を作ります。

こんなHTMLファイルです。このファイルは、Unicodeの文字を数値文字参照で書いてあるだけのものなので、文字を実際に表示できるかどうかは環境によります。Noto花園明朝などを入れた環境で、Firefox 31とChrome 36を試したところ、FirefoxはUnicode 6.0のすべての字形を表示できたようですが、Chromeはぜんぜんだめでした(目視以外の確認法がわかりません)。

Windows上のFirefoxでAdobe PDFに印刷した結果が冒頭のPDFファイルです。

完成に必要な無料フォントを列挙する(あるいはもっとよい方法の提案)という自由研究を、どこかの小学生がやってくれることを期待します。

関連:Unicodeのすべての文字を1回ずつ使って絵を描く

追記:The Unicode Map Projectがすばらしいです。

MathematicaのClusteringComponentsの困ったところ


Mathematica 9.0, 10.0, 10.1, 10.2, 10.3, 10.4.1, 11.2, 11.3 for Microsoft Windows (64-bit)と10.0.0 for Linux ARM (32-bit)でのことです。

Mathematicaには、階層的クラスタリングができる関数が3つ用意されています。FindClustersAgglomerateClusteringComponentsです。

FindClustersにはバグがありました。(FindClustersのバグは11で解決)

Agglomerateにはバグがあります。

バグではありませんが、ClusteringComponentsにも困ったところがあります。データをn個のクラスタに分けたいと思ってClusteringComponents[array,n]としても、できるクラスタがnより少ないことがあるのです。マニュアルには「最高でn個のクラスタを求める」とあるので、nより少ないのはバグでは無いのですが、ちょうどn個のクラスタを作りたいときに使えないのは困ります。

次のコードで再現できます。

data = Import["https://gist.github.com/taroyabuki/4996086/raw/be3b2d537a51b803790fa1149cc714663a8b6ee9/clustering_test_data2.csv"];

Length[Union[ClusteringComponents[data, 13, 1, DistanceFunction -> EuclideanDistance, Method -> "Optimize"]]]
(* 12 *)

13個のクラスタを作りたかったのですが、できたクラスタは12個でした。

データをシャッフルしてからならうまくいきます。

Length[Union[ClusteringComponents[RandomSample@data, 13, 1, DistanceFunction -> EuclideanDistance, Method -> "Optimize"]]]
(* 13 *)

というわけで、階層的クラスタリングをしたいときはRを使うのがよさそうです(参考)。

フリーソフトウェアで風景から歩行者を消す方法(FFmpeg, ImageMagick)


先日「風景から歩行者を消す手軽な方法」をMathematicaで実装したのですが、「なんでMathematica? 持ってないし。高いじゃん」という意見があったので、フリーソフトウェアを使う方法を紹介しましょう。「風景から歩行者が消えていく様子」が要らないならこれで十分かも知れません。(Raspberry PiのMathematicaなら無料なのですが、非力なのでこの話には使いにくいでしょう。)

Ubuntuで試します。(WindowsでもFFmpegとImageMagickを入れればできるかもしれません。)

sudo apt-get install libav-tools imagemagick

ffmpegで動画を画像に分解し、convertでまとめます。(Ubuntu 14.04ではffmpegavconvに置き換えてください。)

ffmpeg -i movie.mov -f image2 %d.png
convert -evaluate-sequence mean *.png mean.jpg

meanmedianに置き換えれば平均ではなく中央値を使うようになりますが、処理時間がかなり増えます。

風景から歩行者が消えていく様子


先日紹介した「風景から歩行者を消す手軽な方法」は、動画の画素ごとに時間について平均をとると動いているものを消せるという話でした。

この方法について、(1)平均ではなく中央値や最頻値を使った方がいいのではないか、(2)シャッターを開きっぱなしにするのと同じではないかと言われたので、お答えしようと思います。(ネタを引きずるのはよくないのですが。)

(1)については、やっていることの意味からすればその通りです。しかし、中央値や最頻値は平均に比べて計算負荷が高いので(前記事の追記も参照)、動画という重いデータを扱う際には、そこにこだわるべきではないと思います。簡単なものをまず試し、できたらそれでよしとするわけです。例えば、ウェブカメラの画像を取得するCurrentImage[]を使って、先の話のリアルタイム版を作れるのですが、平均でやるなら次のように簡単です(Mathematica)。

t = 1;
accumu = ImageData[CurrentImage[]];
Dynamic[Refresh[Image[accumu/t], TrackedSymbols -> {t}]]
(*ここに動画が表示される*)
While[True,
  accumu += ImageData[CurrentImage[]];
  t++;
  Pause[0.1]];

いいウェブカメラがあれば、下のような動画が見られるはずです。(実時間だと速くてよくわからないので、最初の5秒を30秒に引き延ばしたのが冒頭の動画です。)

これを中央値や最頻値でやろうとすると、すぐにメモリがなくなるでしょう。最頻値の場合は数値の揺らぎの程度(あるいは数値を丸める必要の有無)も確認しなければなりません。

(2)の方法は知らなかったのですが、上のような動画を作るのはちょっと面倒なのではないでしょうか。

風景から歩行者を消す手軽な方法


固定したカメラで撮った動画で、画素ごとに時間について平均を取れば、(適当な速度で)動くものを消せます。Mathematicaだとこんな感じです。(参照:フリーソフトウェアを使う方法

Export["result.jpg",
 Image[Mean[Map[ImageData,
    Import["movie.mov", "ImageList"]]]]]

おまけ:フレームの平均を計算していく過程(最初の5秒を30秒で)
詳細:風景から歩行者が消えていく様子(リアルタイム版)

追記:画質的には平均ではなく中央値や最頻値を使った方がいいかもしれませんが、「手軽」ではなくなります。「平均でもできるんだ」という「手軽」さの実例だと理解していただければと思います。

中央値:MeanMedianに置き換えるだけで試せますが、計算時間・消費メモリともに増大します。平均なら約90秒で終わるこの動画(1280x720x372フレーム)の処理に約450秒かかります。消費メモリは2倍くらいになるようです(Core i7 4700MQ、メモリ16GB、Windows 7 64bit、Mathematica 9.0.1)。

最頻値:中央値と同様、計算負荷が高くなります。数値の揺らぎも心配です。Mathematicaの最頻値(Commonest[])は戻り値がリストなので、コードの書き換えも面倒です。

カメラからの入力を「手軽」にリアルタイム処理する場合にも、やはり平均を使うのがいいでしょう。