karpa’s ― 非行非善 このページをアンテナに追加 RSSフィード

2017年11月24日

「日本古典籍字形データセットをかんたんに分類してくれるPythonスクリプト」の結果を(手で)修正した量の統計を出すスクリプト 10:23 「日本古典籍字形データセットをかんたんに分類してくれるPythonスクリプト」の結果を(手で)修正した量の統計を出すスクリプトを含むブックマーク 「日本古典籍字形データセットをかんたんに分類してくれるPythonスクリプト」の結果を(手で)修正した量の統計を出すスクリプトのブックマークコメント

#!/usr/bin/perl

use 5.012;

use strict;
use warnings;
use utf8;

use Cwd;
use FindBin;

use Data::Dumper;

require "$FindBin::Bin/clgr.pl";

my $wd = Cwd::getcwd();
my @directories = clgr::scan_dir($wd);

say join ",", 'Mat', 'U+ID', 'Total', 'Err', 'Err%', 'Orig No C', 'Mod No C', 'Diff';

for my $dir (@directories) {
  my @path = clgr::gen_path($dir);
  my $csv = clgr::read_csv($dir);
  my $data = clgr::cluster($csv);

  my %stat = ();
  my $i = 0;
  my %c_no = ();

  for my $c (@$data) {
    $c_no{mod}{$i}++;
    for my $item (@$c){
      $stat{$i}{$item->[1]}++;
      $c_no{org}{$item->[1]}++;
    }
    $i++;
  }
  my @stat_keys = sort keys %stat;
  my $error_no = 0;
  my $total = 0;

  for my $stat_key (@stat_keys) {
    my $cluster_max = 0;
    my $cluster_total = 0;
    my @original_stat_keys = sort keys %{$stat{$stat_key}};
    for my $original_stat_key (@original_stat_keys) {
      $cluster_total += $stat{$stat_key}{$original_stat_key};
      $cluster_max = $stat{$stat_key}{$original_stat_key} > $cluster_max ? $stat{$stat_key}{$original_stat_key} : $cluster_max;
    }
    $total += $cluster_total;
    $error_no += $cluster_total - $cluster_max;
  }

  my $orig_no_c = scalar keys %{$c_no{org}};
  my $mod_no_c = scalar keys %{$c_no{mod}};
  # 'Mat', 'U+ID', 'Total', 'Err', 'Err%', 'Orig No C', 'Mod No C', 'Diff b/w Orig & Mod No C'
  say join ",", $path[-3], $path[-1], $total, $error_no, sprintf("%.2f", $error_no / $total * 100), $orig_no_c, $mod_no_c, abs($orig_no_c - $mod_no_c);
#  warn Dumper($data, \%stat);
#  last;
}
トラックバック - http://d.hatena.ne.jp/karpa/20171124

2017年11月23日

「日本古典籍字形データセットをかんたんに分類してくれるPythonスクリプト」の結果を修正してHTMLに再出力するスクリプト 01:36 「日本古典籍字形データセットをかんたんに分類してくれるPythonスクリプト」の結果を修正してHTMLに再出力するスクリプトを含むブックマーク 「日本古典籍字形データセットをかんたんに分類してくれるPythonスクリプト」の結果を修正してHTMLに再出力するスクリプトのブックマークコメント

#!/usr/bin/perl

use 5.012;

use strict;
use warnings;
use utf8;

use Cwd;
use FindBin;

use Data::Dumper;

require "$FindBin::Bin/clgr.pl";

my $now = time();

my $wd = Cwd::getcwd();
my @directories = clgr::scan_dir($wd);

for my $dir (@directories) {
    my @path = clgr::gen_path($dir);
    my $html_file = "$path[-3]/$path[-3]_mod.html";
    my $csv_file = "$path[-3]/$path[-3].csv";
    if (not -e $html_file or (stat $html_file)[9] < $now) {
        open my $html_fh, ">", $html_file or die $html_file;
        print $html_fh clgr::regen_html_header();
    }
    if (not -e $csv_file or (stat $csv_file)[9] < $now) {
        open my $csv_fh, ">", $csv_file or die $csv_file;
        print $csv_fh clgr::regen_csv_header(); 
    }

    my $data = clgr::read_csv($dir);
    my $cluster = clgr::cluster($data);
    my $html = clgr::regen_html($path[-1], "$wd/$path[-3]", $cluster);
    my $csv = clgr::regen_csv($path[-1], $path[-3], $cluster);
    open my $html_fh, ">>", $html_file or die $html_file;
    print $html_fh $html;
    open my $csv_fh, ">>", $csv_file or die $csv_file;
    print $csv_fh $csv;
}

clgr.pl

#!which perl

package clgr;

use strict;
use warnings;
use utf8;
use File::Spec;
use Image::Size qw/html_imgsize/;

my @kana = (
    'U+3042', 'U+3044', 'U+3046', 'U+3048', 'U+304A', 'U+304B',
    'U+304C', 'U+304D', 'U+304E', 'U+304F', 'U+3050', 'U+3051',
    'U+3052', 'U+3053', 'U+3054', 'U+3055', 'U+3056', 'U+3057',
    'U+3058', 'U+3059', 'U+305A', 'U+305B', 'U+305C', 'U+305D',
    'U+305E', 'U+305F', 'U+3060', 'U+3061', 'U+3062', 'U+3064',
    'U+3065', 'U+3066', 'U+3067', 'U+3068', 'U+3069', 'U+306A',
    'U+306B', 'U+306C', 'U+306D', 'U+306E', 'U+306F', 'U+3070',
    'U+3072', 'U+3073', 'U+3075', 'U+3076', 'U+3078', 'U+3079',
    'U+307B', 'U+307C', 'U+307E', 'U+307F', 'U+3080', 'U+3081',
    'U+3082', 'U+3084', 'U+3086', 'U+3088', 'U+3089', 'U+308A',
    'U+308B', 'U+308C', 'U+308D', 'U+308F', 'U+3090', 'U+3091',
    'U+3092', 'U+3093'
);

sub scan_dir {
    my $dir = shift;
    $dir .= '/' if $dir !~ m!/\z!ms;
    my @dirs = ();
    opendir(my $dh, $dir) or die $dir;
    while (my $rdir = readdir($dh)) {
        next if $rdir =~ /\A\.+\z/ms;
        if (-d $dir . $rdir) {
            if (grep {$_ eq $rdir} @kana) {
                push @dirs, $dir . $rdir;
            }
            else {
                my @subdir = scan_dir($dir . $rdir);
                push @dirs, @subdir;
            }
        }
    }
    return @dirs;
}

sub read_csv {
    my $dir = shift;
    my @csv = ();
    $dir =~ m!/(U[^/]+)\z!ms;
    my $file = $1 . ".csv";
    open my $fh, "$dir/$file" or die "$dir/$file";
    my $head = 0;
    while(my $line = <$fh>) {
        next if not $head++;
        chomp $line;
        $line =~ tr/"//d;
        warn $& if $line =~ /[^\.,\/\+\_A-Za-z0-9]/;
        my @split = split ',', $line;
        if (not $split[2] and $split[0]) {
            $split[2] = $split[0];
        }
        push @csv, \@split;
    }
    return \@csv;
}

sub cluster {
    my $csv = shift;
    my @cluster = ();
    for my $array (@$csv) {
        push @{$cluster[$array->[2]]}, [$array->[1], $array->[0], $array->[3]]; # $cluster{<mod cl>} = [<seq>, <org cl>, <path>]
    }
    @cluster = sort { scalar(@$b) <=> scalar(@$a) } map { [ sort { $a->[0] <=> $b->[0] } @$_ ] } grep { $_ } @cluster;
    return \@cluster;
}

sub regen_html_header {
    return <<EOF;
<html><head><style>span.nobr{white-space:nowrap;}</style></head><body>
EOF
}

sub regen_html {
    my $uni = shift;
    my $html_dir = shift;
    my $cluster = shift;
    my $html = "<h1>$uni</h1>\n";
    my $i = 1;
    for my $c (@$cluster) {
        $html .= "<h2>Cluster $i: " . scalar(@$c) . " items</h2>\n";
        $html .= "<p>";
        for my $item (@$c) {
            my $img_loc = File::Spec->rel2abs($item->[2], $html_dir);
            my $size = html_imgsize($img_loc);
            $html .= qq(<span class="nobr"><img src="$item->[2]" $size>$item->[0]</span> );
        }
        $i++;
        $html .= "</p>\n";
    }
    return $html;
}

sub regen_csv_header {
    return join(',', 'mat', 'u', 'cluster', 'counts') . "\n";
}

sub regen_csv {
    my $uni = shift;
    my $mat = shift;
    my $cluster = shift;
    my $csv = '';
    my $i = 1;
    for my $c (@$cluster) {
        $csv .= join ',', $mat, $uni, $i, scalar @$c;
        $csv .= "\n";
        $i++;
    }
    return $csv;
}

sub gen_path {
    my $basedir = shift;
    return File::Spec->splitdir($basedir);
}

1;
トラックバック - http://d.hatena.ne.jp/karpa/20171123

2017年11月20日

日本古典籍字形データセットをかんたんに分類してくれるPythonスクリプト 14:20 日本古典籍字形データセットをかんたんに分類してくれるPythonスクリプトを含むブックマーク 日本古典籍字形データセットをかんたんに分類してくれるPythonスクリプトのブックマークコメント

#!/usr/bin/python3
# coding: utf-8

#
# Usage: Run on the directory just above where the Dataset of PMJT Character Shapes
# (http://codh.rois.ac.jp/char-shape/) is downloaded
#

from pathlib import Path
from time import time

from PIL import Image
from pyclustering.cluster.xmeans import xmeans
from pyclustering.cluster.center_initializer import kmeans_plusplus_initializer

ext = '.jpg'

kana = [
    'U+3042', 'U+3044', 'U+3046', 'U+3048', 'U+304A', 'U+304B',
    'U+304C', 'U+304D', 'U+304E', 'U+304F', 'U+3050', 'U+3051',
    'U+3052', 'U+3053', 'U+3054', 'U+3055', 'U+3056', 'U+3057',
    'U+3058', 'U+3059', 'U+305A', 'U+305B', 'U+305C', 'U+305D',
    'U+305E', 'U+305F', 'U+3060', 'U+3061', 'U+3062', 'U+3064',
    'U+3065', 'U+3066', 'U+3067', 'U+3068', 'U+3069', 'U+306A',
    'U+306B', 'U+306C', 'U+306D', 'U+306E', 'U+306F', 'U+3070',
    'U+3072', 'U+3073', 'U+3075', 'U+3076', 'U+3078', 'U+3079',
    'U+307B', 'U+307C', 'U+307E', 'U+307F', 'U+3080', 'U+3081',
    'U+3082', 'U+3084', 'U+3086', 'U+3088', 'U+3089', 'U+308A',
    'U+308B', 'U+308C', 'U+308D', 'U+308F', 'U+3090', 'U+3091',
    'U+3092', 'U+3093', 'U+309D', 'U+309E', 'U+30B5', 'U+30C4',
    'U+30CB', 'U+30F6'
        ]

basedir = Path.cwd()
now = time()

def detect_dirs(scandir=None)->list:
    '''
    detecting which directories would be scanned,
    which should be listed in the kana list
    '''
    if not scandir:
        scandir = Path(basedir)
    dirs = []
    for component in scandir.iterdir():
        if component.name in kana:
            dirs.append(component)
        elif component.is_dir():
            dirs += detect_dirs(component)
    return dirs

def scan_dir(scandir)->list:
    '''
    scanning the size of images
    it will dig a single-level of sub-directories
    '''
    if not scandir.is_dir():
        return []
    files = []
    scan_base = scandir.parts[-1]

    for f in sorted(scandir.iterdir()):
        if f.is_dir():
            for sf in sorted(f.iterdir()):
                if sf.name.endswith(ext) and sf.is_file():
                    files.append(is_img(sf))
        elif f.name.endswith(ext) and f.is_file():
            files.append(is_img(f))

    return files

def is_img(filename: str)->list:
    '''
    detect whether it is image file or not
    '''
    return [filename, img_size(filename)]

def img_size(filename: str)->list:
    '''
    return the size of images
    '''
    img = Image.open(filename, 'r')
    return list(img.size)

def calc_xmeans(files: list)->list:
    '''
    calculate the x-kernels
    '''
    sample = []
    for f in files:
        sample.append(f[1])

    if len(sample) < 15:
        amount = 1
    elif len(sample) > 50:
        amount = 3
    else:
        amount = 2

    xm_c = kmeans_plusplus_initializer(sample, amount).initialize()
    xm_i = xmeans(sample, xm_c, ccore=True)
#    xm_i = xmeans(sample, xm_c, ccore=False)    # Use this line on Darwin, and pray

    xm_i.process()
    clusters = xm_i.get_clusters()

    clgr = []

    j = 0
    for c in clusters:
        container = []
        for i in c:
            container.append([j, i, files[i]])
        clgr.append(container)
        j += 1

    return clgr

def export(data: list, directory)->None:
    '''
    export to html and csv calculated classifications
    '''
    export_csv = directory / (directory.parts[-1] + '.csv')
    export_html = Path(directory / '../../').resolve() / (directory.parts[-3] + '.html')
    if export_html.exists() and export_html.stat().st_mtime < now:
        with export_html.open(mode='w') as exh:
            exh.write('<html><head><style>span.nobr{white-space:nowrap;}</style></head><body>')

    with export_csv.open(mode='w') as exc:
        exc.write(','.join(['cluster no','seq','mod cluster no','file name']) + '\n')
        for c in data:
            for i in c:
                exc.write(','.join([str(i[0]), str(i[1]),'',\
                        str(item[2][0].relative_to(export_html.parent)) + '\n')

    with export_html.open(mode='a') as exh:
        exh.write('<h1>' + str(directory.parts[-1]) + '</h1>\n')
        exh.write('<p>The number of clusters: ' + str(len(data)) + '</p>\n')
        i = 0
        for c in data:
            i += 1
            exh.write('<h2>Cluster ' + str(i) + '</h2>\n')
            exh.write('<p>')
            for item in c:
                exh.write('<span class="nobr"><img src="' +\
                        str(item[2][0].relative_to(export_html.parent)) +\
                        '" width="' + str(item[2][1][0]) + '" height="' +\
                        str(item[2][1][1]) + '">' + str(item[1]) + '</span> ')
            exh.write('</p>\n')

dirs = detect_dirs()

for directory in sorted(dirs):
    dir_scan = scan_dir(directory)
    xm_clusters = calc_xmeans(files=dir_scan)
    export(data=xm_clusters, directory=directory)
トラックバック - http://d.hatena.ne.jp/karpa/20171120

2017年08月28日

pptx2md 16:24 pptx2mdを含むブックマーク pptx2mdのブックマークコメント

#!/usr/bin/python
#coding: utf-8

import sys
from pptx import Presentation

if __name__ == '__main__':
  prs = Presentation(sys.argv[1])
  
  c = 1
  for slide in prs.slides:
    print("# Slide " + str(c))
    s = 1
    for shape in slide.shapes:
      if not shape.has_text_frame:
        continue
      if s == 1:
        print("## " + shape.text_frame.paragraphs[0].text + "\n")
      else:
        for paragraph in shape.text_frame.paragraphs:
         print("  " * (paragraph.level) + "*"),
         print(paragraph.text)
      s = s + 1
    if slide.has_notes_slide:
      print("\n"),
      print(slide.notes_slide.notes_text_frame.text + "\n")
    c = c + 1

必要があって。

トラックバック - http://d.hatena.ne.jp/karpa/20170828

2017年01月25日

Perlregex? 21:24 Perlのregex?を含むブックマーク Perlのregex?のブックマークコメント

no titleを見て,Perl 5だとどうなるんだらうと書いてみた。ちなみに,perl 5.18.2とruby 2.0.0p648。

use strict;
use warnings;
use feature qw/ say /;
use Time::HiRes qw/ time /;

for my $n (5 .. 12) {
  my $s = "username\@host" . ".abcde" x $n . ".";
  my $start = time();
  say $s;
  say $s=~ /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/ms;
  say(length($s) . ': ' . (time - $start));
}

結果としては,

time perl test.pl

44: 0.000130891799926758

50: 0.0001068115234375

56: 0.000277042388916016

62: 0.000208139419555664

68: 0.000213861465454102

74: 0.000242948532104492

80: 0.00024104118347168

86: 0.000189065933227539

real	0m0.028s
user	0m0.017s
sys	0m0.008s
time ruby test.rb
nil
"44: 0.068262"
nil
"50: 0.385222"
nil
"56: 1.905355"
nil
"62: 9.483776"
nil
"68: 46.55787"
nil
"74: 230.308585"
nil
"80: 1156.772055"

real	24m5.527s
user	23m57.498s
sys	0m2.997s

といったところ。既知の結果ではありとくに云ふべきことないけれど,試してみるとほんとにぜんぜん違ふのは驚いた。

トラックバック - http://d.hatena.ne.jp/karpa/20170125