NP11にDebianをインストールする

NP11が壊れてしまったのでDebian9.1.0を再インストールする。
NP11にはPlaxtor の3M-PLEXTOR PX-256M6Sを取り付けてある。
インストールの大まかな流れは以下の通り
1.DebianのサイトよりNET INSTALL 用のISOイメージ(CD-ROM作成用)をダウンロードする。
2.Rufus2.16pを使いISOイメージを8GのUSBメモリーに書き込む。
3.BIOSメニューにてUSBメモリを優先ブートデバイスに設定する。
4.マシンをリブートしUSBメモリに格納されたCD-ROMイメージからインストール作業を進める。つまり、USBメモリをCD-ROMドライブの用に働かせることで、インストール作業をすすめる。
5.インストール作業中の使用言語はUSA,UTF-8にする。インストール後にコンソールでの文字化けを防げる
6.インストール後、rootになって通常使用する一般ユーザーをsudoグループに加える
adduser sudo
7.postgresqlをインストールする
sudo apt-get install postgresql

問題集からプリントを作成するためにGimpとpython-fuを使ってみた。

 約2年前、「本の電子化を補助するためにGimppython-fuを使ってみた。」という記事を書いたがあまりに日本語情報が少ないためか、python-fuというキーワードでリンク先に指定されているようだ。

 最近は、自分のためというより子供のためGimppython-fuを使っている。うちの子供は中学生なのだが、いつも一回、問題を解いたきりでお終い。できても、できなくてもそれっきりという教材が多い。
これでは、定着できるはずもない。

そこで、問題集をスキャンしてgimpで編集してプリント化することを思いついたのだが、やはりページ数が多くて、見開きで1枚のプリントを作成するだけでも同じことの繰り返し。この手間が大変なのだ。

そこで、以前使ったgimppython-fuの組み合わせでなんとかしようと思い立った次第である。

 ご多分にもれず、python-fuを手なずけるには苦労したが、すったもんだのあげくにやっと動くものができたのでメモ書きしておく。

このコードを働かせるための条件は、以下の通りである。
条件から外れるとうまく動かない可能性がある。

  1. スキャンデータはjpg形式で日本語の入らないフォルダとファイル名で保存する。(例えば'C:\2in1\tmp074.jpg')
  2. ファイル名は半角英字からなる文字部(例えば'tmp')の後に3桁の数値部(例えば'001')と'.jpg'という規則で付ける
  3. 数値部はできればページ番号に合わせるとあとから参照しやすい。
  4. 数値部はフォルダー内でユニーク(単一値)でなければならない。

以下にコードが扱うデータとその機能の概略説明する

スキャン元は過去問集で横書きのページ振り(左ページがページ番号小)が採用されている。
縦書きの国語の問題が混じっているがページの番号は横書き方式が縦書き部にも適用されている。
画像データはページ番号をファイル名に含んでいる。
コードは使用者にデータフォルダのパスと'.jpg'というファイルエクステンション、処理のスタートページとエンドページの入力を求める。
コードスタートページの値からファイル名を計算し見開き分の二つの画像データを合成する。
合成後に単色化とスプラインカーブで画像のボケを減少させる。
左ページのファイル名のエクステンションの前に'w'を付加した名前でデータを保存する。

私が使っているgimp上での作動条件としては以下のものがある。
ユーザー名をOillerとするとコードを置く場所は
   C:\Documents and Settings\Oiller\.gimp-2.8\plug-ins
Gimpのメニューにスタートポイントが作成されるがその位置は
   メニューバー/PyScripts/My 7th python-fu
Gimpのメニューバー上では、何か画像が表示されていないと自作のメニューにフォーカスが移動できないので作動させる前に何か無関係な画像を読み込ませることが必要

コード例:example7.py

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


# This tells Python to load the Gimp module 
from gimpfu import *
import os, glob

control_points = [0,0, 200,100, 234,234, 255,255]

def get3degit(num):
  s = '000'+str(num)
  p = len(s)-3
  r = s[p:]
  return r

# create an output function that redirects to gimp's Error Console
def gprint( text ):
   pdb.gimp_message(text)
   return 

def past2_2images_in_1(start_page, end_page):
  pages = 
  pagestext = '['
  for i in range(int(start_page), int(end_page), 2):
    j = i + 1
    page = 
    page.append(get3degit(i))
    page.append(get3degit(j))
    pagetext = '['+get3degit(i)+','+get3degit(j)+']'
    #gprint(pagetext)
    pages.append(page)
    pagestext = pagestext + pagetext + ','
  pagestext = pagestext.rstrip(',')+']'
  #gprint(pagestext)
  return pages

def combine2in1(my_dir, my_ext, my_taple):
  #右ページのファイル名を作成する(ワイルドカードを含む)
  Right_key = my_dir+'\*'+my_taple[1]+my_ext

  #該当するファイルのリストを得る
  Right_files = glob.glob(Right_key)
  #gprint(Right_key+':'+Right_files[0])

  #イメージファイルのロード
  Right_image = pdb.gimp_file_load(Right_files[0], '')
  Right_image_width = Right_image.width

  #イメージを表示する
  Right_disp = pdb.gimp_display_new(Right_image)

  #アクティブレイヤーを変数Right_default_layerに代入する
  Right_default_layer = pdb.gimp_image_get_active_layer(Right_image)

  #すべてを選択する
  pdb.gimp_selection_all(Right_image)

  #クリップボードにコピーする
  non_empty = pdb.gimp_edit_copy(Right_default_layer)

  #右イメージの表示を終了する
  pdb.gimp_display_delete(Right_disp)

  #サーチキーとなるファイル名を作成する。(ワイルドカードを含む)
  Left_key = my_dir+'\*'+my_taple[0]+my_ext

  #該当するファイルのリストを得る
  Left_files = glob.glob(Left_key)

  #リストの先頭のファイル名を得る
  Left_file = Left_files[0]
  #gprint(Left_key+':'+Left_file)

  #左ページのイメージをロードする
  Left_image = pdb.gimp_file_load(Left_file, '')
  Left_width = Left_image.width

  #左イメージを表示する
  Left_disp = pdb.gimp_display_new(Left_image)

  #左イメージのアクティブレイヤーを変数に代入する
  Left_default_layer = pdb.gimp_image_get_active_layer(Left_image)

  #クリップボードの内容を貼り付けると
  #貼り付けたものはフローティングかつアクティブレイヤーになる
  floating_layer = pdb.gimp_edit_paste(Left_default_layer, False)

  #フローティングレイヤーの位置決めをする
  pdb.gimp_layer_set_offsets(floating_layer, Left_image.width, 0)

  #フローティングレイヤーを通常のレイヤーに変換する
  pdb.gimp_floating_sel_to_layer(floating_layer)

  #新しいキャンバスの幅と高さを計算する
  new_width = Left_image.width + Right_image_width
  new_height = Left_image.height

  #キャンバスの大きさを拡張する
  pdb.gimp_image_resize(Left_image, new_width, new_height, 0, 0)

  #ビジブルなレイヤーを統合する
  pdb.gimp_image_merge_visible_layers(Left_image, EXPAND_AS_NECESSARY)

  #左イメージのアクティブレイヤーを変数に代入する
  Left_default_layer = pdb.gimp_image_get_active_layer(Left_image)

  #デフォルトレイヤーを指定して脱色する
  pdb.gimp_desaturate(Left_default_layer)

  #デフォルトレイヤーにトーンカーブを適用する
  pdb.gimp_curves_spline(Left_default_layer, HISTOGRAM_VALUE, 8, control_points)

  #保存ファイル名を作成する
  name = Left_file.rsplit('.')
  SaveName = name[0]+'w.'+name[1]
  pdb.gimp_file_save(Left_image, Left_default_layer, SaveName, SaveName)

  #イメージを閉じる
  pdb.gimp_display_delete(Left_disp)

  return



# This is the function that will perform actual actions
def my_script_main_function(image, drawable, directory, ext, suffix, start_value, end_value) :
  combi_list = past2_2images_in_1(start_value,end_value)
  if os.path.exists(directory):
    for taple in combi_list:
      combine2in1(directory, ext, taple)
  else:
    pdb.gimp_message("No such directory: %s" %(directory))
  return

# This is the plugin registration function
# I have written each of its parameters on a different line 
register(
  "script07",    
  "This program combine 2 images into the one image",   
  "This script does nothing and is extremely good at it",
  "Oiller", 
  "Placed on Public Domain", 
  "November 2013",
  "/PyScripts/My 7th Python-Fu", 
  "*", 
  [
    (PF_DIRNAME, "directory", "Directory", 'C:\\2in1'),
    (PF_STRING, "ext", "File extension, including dot", '.jpg'),
    (PF_STRING, "suffix", "Suffix for sharped file", "_a"),
    (PF_INT, 'start_value', 'Start page number is ', 74),
    (PF_INT, 'end_value', 'End page number is ', 75)
  ], 
  [],
  my_script_main_function,
)

main()

参考にしたサイトへのリンク

python-fuの紹介(英語)
http://www.exp-media.com/content/extending-gimp-python-python-fu-plugins-part-1

GIMP python 仕様書(英語)
http://www.gimp.org/docs/python/index.html

音読をやらせてみた。

音読をやらせてみた。

用意した教材は教科書の本文をネイティブの人が読んだCD。
これをWAVに落とし音声を加工した。
つまり、お手本の後に子供が読む時間を空けるために無音を挿入したのだ。
加工したのは3レッスン分、1回読むのに約6分かかる。
子供が英語の読みに充てられる時間は1日20分と踏んでいるので3回まわせる。

やらせてみると、やはりモタモタして追いつけない。
教科書を目で追いながら聞くのにまだ慣れないようだ。
1つの文を読む回数が3回では慣れるまでにならない。
回数を増やすためには、充てる時間を増やすか、文の量を減らすかしなければならない。
うちの子の場合はそんなに集中力がないので文の量を減らす方向で試すことにした。

中学生の子供にどうやって英語を教えるか

子供、中学2年生の英語の成績が思わしくないのでなんとかしたいと思ったわけだが、家庭でできることを考える途中プロセスをメモ書きする。

直接的な動機は、1年生の期末テストの英語の成績が50点台であったこと。
今後のことを考えると手をいれないと大変まずい。
とはいってはみても、自分も英語が得意なわけではなくどうやって教えればいいかから考えなければならない。

まず、いろいろ情報を集めてみると
1.音読
2.文法
3.英作文
の三分野をバランスよくやらないとだめらしい。
ところがいまどきの英語の教科書は「聞ける、話せる」の要素を増やしているようではあるが、英語教科に割り当てられる時間の制約を考えるとそもそも「時間的に無理」に見えてしまう。

「聞ける、話せる」を公立の中学校の教室で実現するには今の3倍とか4倍ぐらいの教師をつけない無理ではなかろうかと思う。
後は、コンピューターを高度に使った英語学習支援システムを開発するとか。
 現状では、国際的に通用する人材を育てようという気持ちはあるのだが、人件費を投入できないので「聞ける、話せる」が実現できていないと思われる。

英語のテストの点数の分布を見たことがあるが、見事に2コブラクダの形をしている。右側の高得点の山は、多分塾とか家庭教師とか通信教育とか学校以外の学習をしているグループで左側の低得点の山は学校のみで学習しているグループだと読んだ。他の教科ではこんなあからさまな違いは出ないことからすると、公立中学校の英語教授法はまだまだ改善余地が大きいといえるのだろう。

で、うちの子供をどうするかだが、クラブ活動もしており塾通いは現実的でないので家庭学習でなんとかする方向でいくことにした。

親が、マンツーマンで教えられればいいのだがそんな実力はないのでネットで探した英語ソフトや市販の教材を組み合わせでしのぐことに決めた。

まずは、教えるというより学習のスタイルだが、ALLINONEという「読み、聞く、書く」を一つの文例集でこなすやり方があると知った。
これは、教わる側の都合というより教材を作る立場からするととても楽できるのでこれでいくことにする。
また、子供の都合からは授業で触れるものを使えば負担が少なくできるので教科書書やワークなどから教材を作ることにした。
暗記もので評判がいいソフトは「ハイル」と「PSS7」だが、出来合いの問題集では中学生というレベルに合わない。
結局、これらのソフトで使う問題集については学習進度や目的に合わせて自作することにした。ALLINONEタイプで使う文例の網羅性については教科書やワークのみでは不安があるので『本多式中学英語マスター短文英単語』も加えることにする。問題作成に余裕があればだが、名詞の部分を他の単語にいれかえたバージョンも作りたい。
 最後に、文法だがこれだけは誰かが教えなければ文法というものがあることにすら気がつくはずがないので私が教えることにした。
使う教材はわかりやすさで『トコトンていねいな英文法レッスン』、網羅性の確保で『くもんの中学英文法―中学1~3年 基礎から受験まで』を海図(チャート)として選んだ。

本の電子化を補助するためにGimpとpython-fuを使ってみた。

python-fuはpythonで作成したスクリプトGimpを自動化するための仕組みだ。
そんなことに手を出した訳は、本をスキャナーで取り込んで電子化してやろうと目論んだのだが、スキャナーの扱いが下手なのか取り込んだデータのコントラストが弱くて見るに耐えない。
印刷してみてもぼやけた感じでこれでは使えないという印象だ。

なんとかならないかとGIMPでいろいろとなぶっていたら、「トーンカーブの調整」というのが具合がいい。
紙面の凹凸による薄墨のような暗さも除去できるし、ぼやけた字の輪郭もはっきりする。
ただし、700ページにも及ぶスキャンデータをいちいち手作業で変換するのは苦行でしかない。

そこで、誰かがどこかで書いていた「GIMPではスクリプトが使える」という記事についての記憶をたよりに調べてみるとscript-fuというのとpython-fuというのが見つかった。
しかし、script-fuはLispの流れをくむらしく私には読めない。
かろうじてpythonは少しだけかじったことがあるのでこちらでいくことにしたが、これまた日本語の情報が少なく困ったもんだ。

すったもんだの挙句、やっと動くものが出来たのでメモがきしておく。
ホストはWindowsXP pro搭載機を使った。
全体の流れとしては
1.python2.5のインストール(他のバージョンの使用可否は未確認)
2.python-fuが依存するパッケージのインストール
3.GIMPのインストール(インストール時にのみpython-fuの使用登録が可能なようだ。……未確認)
4.スクリプトを作成しGIMPインストールディレクトリ配下のplug-insディレクトリに置く
5.GIMPを立ち上げフィルターメニューに現れるスクリプト名をクリックするとスクリプトが実行される。

my-sharp.py (ほぼ下記のITプロ記事内で紹介されているスクリプトのコピペです。)

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

from gimpfu import *
import os, glob

def do_sharp_batch(dirname, ext, suffix):
  if os.path.exists(dirname):
    fnames = [f for f in glob.glob(os.path.join(dirname, '*'+ext))
               if suffix not in f]
    control_points = [0,0, 160,0, 240,255, 255,255]
    for fname in fnames:
      new_filename = fname[:0-len(ext)]+suffix+ext
      img = pdb.gimp_file_load(fname, '')
      pdb.gimp_curves_spline(img.layers[0], HISTOGRAM_VALUE, 8, control_points)
      pdb.gimp_file_save(img, img.active_layer, new_filename, '')
  else:
    pdb.gimp_message("No such directory: %s" %(dirname))

register(
  "sharp-batch", "Batch image sharper", "", "Yasushi Masuda, Oiller",
  "Placed on Public Domain", "2010", "SharpBatch", "",
  [(PF_DIRNAME, "directory", "Directory", os.getcwd()),
   (PF_STRING, "ext", "File extension, including dot", '.png'),
   (PF_STRING, "suffix", "Suffix for sharped file", "_sharp")],
  [],
  do_sharp_batch, menu="/Xtns/MySharp")

main()

python-fuのインストールについてはITpro下記を参考にした。

  http://itpro.nikkeibp.co.jp/article/COLUMN/20090218/324989/

gimp_curves_splien()の使い方については下記を参考にした。

  http://forum.meetthegimp.org/index.php/topic,42.0.html

上記記事を書いていただいた方には感謝を表明します。

Windowsからpythonを使って外部サーバ上のPostgreSQLに接続する

Windowsから外部のPostgreSQLサーバにpycopg2を使って接続する

準備
 python2.6をインストール
 psycopg2 for Winをインストール
  http://www.stickpeople.com/projects/python/win-psycopg/psycopg2-2.2.1.win32-py2.6-pg8.4.3-release.exe

テストスクリプト

# coding:shift_jis

import psycopg2
   
try:
    conn = psycopg2.connect(database="telphone", user="dbuser", host = "192.168.0.1", port = 5432,  password="dbpass");
    print "Connected\n"
except:
    print "Can not connect\n"

cur = conn.cursor()
sql = """select num,name from tel_person where name is not null limit 200"""
cur.execute(sql)
rows = cur.fetchall()
for row in rows:
  print row[0],':',unicode(row[1],"EUC_JP")

svn logに続けて--vervoseスイッチを使うとさらに詳細情報が表示される

[oiller@myserver sesame]$ svn log day.txt
------------------------------------------------------------------------
r2 | oiller | 2010-01-04 13:08:01 +0900 (月, 04  1月 2010) | 1 line

初めての更新
------------------------------------------------------------------------
r1 | oiller | 2010-01-04 10:05:16 +0900 (月, 04  1月 2010) | 1 line

import Sesame project
------------------------------------------------------------------------
[oiller@myserver sesame]$ svn log --verbose day.txt
------------------------------------------------------------------------
r2 | oiller | 2010-01-04 13:08:01 +0900 (月, 04  1月 2010) | 1 line
変更のあったパス:
   M /sesame/trunk/day.txt

初めての更新
------------------------------------------------------------------------
r1 | oiller | 2010-01-04 10:05:16 +0900 (月, 04  1月 2010) | 1 line
変更のあったパス:
   A /sesame
   A /sesame/trunk
   A /sesame/trunk/day.txt
   A /sesame/trunk/number.txt

import Sesame project
------------------------------------------------------------------------