「psd2waifu2x」ソースコード

これらのソースコードは改変などは基本的に自由に行ってもらって構いません。
ただ、改善や機能追加等をして頂けた場合は、僕自身興味がありますのでコメント欄などにご一報いただけると幸いです。


psd2wife.py


#coding:utf-8

from psd_tools import PSDImage
import os, copy, subprocess, datetime, glob, sys
from configparser import ConfigParser

class PSDPaser:
    def __init__(self, dir_psd, dir_cfg = os.path.join(os.path.dirname(__file__), "psd2wife.ini"), safe_mode = True):
        self.config = ConfigParser()

        self.config.read(dir_cfg, "utf-8")
        self.wf_scale = float(self.config.get("waifu", "wife_scale"))
        self.dir_safe = self.config.get("save", "safety")

                
        self.dir_psd = dir_psd
        self.psd = PSDImage.open(dir_psd)

        self.psd_all = [i for i in self.psd.descendants()]
        
        if safe_mode:
            self.dir_save_base  = os.path.join(self.dir_safe, datetime.datetime.today().strftime("%Y%m%d_%H%M_%S"))
        else:
            self.dir_save_base = self.dir_psd.replace(".psd", "")
        self.dir_save_pics  = os.path.join(self.dir_save_base, "result") 
        
        list_file_name = []
        
        structure = []
        structure_all = []
        structure_hrchy = []
        
        structure_safe = []
        structure_safe_all = []
        structure_safe_hrchy = []
        psd_setting=[[str(int(self.psd.width * self.wf_scale)), str(int(self.psd.height * self.wf_scale))]]
        
        print("「{}」\nに.psdの各レイヤーを画像に変換します。".format(self.dir_save_pics))
        for psd_elem_num, psd_elem in enumerate(self.psd_all):
            if str(psd_elem.parent.name) == "Root":
                structure = []
                
            loop=0
            structure = []
            structure_safe = []
            
            psd_group = copy.deepcopy(psd_elem.parent)
            while psd_group.is_group():
                loop+=1
                structure.append(psd_group.name)
                if str(psd_group.name) != "Root":
                    psd_group = psd_group.parent
                else:
                    break
            try:
                structure.remove("Root")
            except:
                pass
                
            file_name = psd_elem.name
            list_file_name.append(file_name)
            
            if safe_mode:
                for i in structure:
                    if structure_all.count(i) == 0:
                        structure_all.append(i)
                    structure_safe.append("Group_{}".format(str(structure_all.index(i)+1)))
                for i in structure_safe:
                    if structure_safe_all.count(i) == 0:
                        structure_safe_all.append(i)
            
            if structure_hrchy.count(structure) == 0 and structure != []:
                structure_hrchy.append(structure)
                
                structure_safe_hrchy.append(structure_safe)
                
            if safe_mode:                
                structure = structure_safe
                file_name = "layer_{}".format(str(psd_elem_num+1))
                
            os.makedirs(os.path.join(self.dir_save_pics, *structure[::-1]), exist_ok=True)
            dir_save = os.path.join(self.dir_save_pics, *structure[::-1], file_name + ".png")
            psd_setting.append([dir_save, str(int(psd_elem.offset[0] * self.wf_scale)), str(int(psd_elem.offset[1] * self.wf_scale)), "_".join([*structure[::-1], file_name]), str(int(psd_elem.is_visible())), structure[0] if structure != [] else "this_is_base_group"])
            if not psd_elem.is_group():
                try:
                    layer = psd_elem.topil()
                    layer.save(dir_save)
                except:
                    print("{}は保存されませんでした。".format(psd_elem.name))
                    
        self.gimp_structure_all = "[\"{}\"]".format("\",\"".join(structure_all))
        self.gimp_structure_hrchy = "[{}]".format(",".join(["[\"{}\"]".format("\",\"".join(i)) for i in structure_hrchy]))
        self.gimp_structure_safe_all = "[\"{}\"]".format("\",\"".join(structure_safe_all))
        self.gimp_structure_safe_hrchy = "[{}]".format(",".join(["[\"{}\"]".format("\",\"".join(i)) for i in structure_safe_hrchy]))
        
        self.gimp_file_name = "[\"{}\"]".format("\",\"".join(list_file_name[::-1]))
                
        print("変換終了")
        str_ = "\n".join([",".join(i) for i in psd_setting])
        self.dir_save_setting = self.dir_save_pics+".txt"
        with open(self.dir_save_setting, "wt") as f:
            f.write(str_)

        
    def waifu_run(self):
        dir_waifu = self.config.get("waifu", "directory")
        try:
            cmd="\"{}\" -i \"{}\" -s {} {}".format(dir_waifu, self.dir_save_pics, str(self.wf_scale),self.config.get("waifu", "setting"))
        except:
            cmd="\"{}\" -i \"{}\" -s {}".format(dir_waifu, self.dir_save_pics, str(self.wf_scale))
        print("「{}」を実行します。しばらく時間が借るので放置してください。".format(cmd))
        subprocess.call(cmd)
        
    def gimpImportCommand(self):
        dir_converted = glob.glob(self.dir_save_pics+"*"+ os.sep)
        os.rename(self.dir_save_pics, self.dir_save_pics+"_preWaifu2x")
        os.rename(dir_converted[1], dir_converted[0])
        
        dir_save_gimp_cmd = os.path.join(self.dir_save_base, "gimp_cmd.txt") 
        dir_save_gimp = self.dir_save_setting.replace(".txt", ".xcf")
        gimp_cmd='''import codecs
dir_txt = r"{}"
dir_save = r"{}"

structure_all = {}
structure_hrchy = {}
structure_safe_all = {}
structure_safe_hrchy = {}

gimp_file_name = {}

with codecs.open(dir_txt, 'r', 'utf-8', 'ignore') as f:
    im_setting = f.read()

list_ims = [i.split(",") for i in im_setting.split("\\n")]
image = gimp.Image(int(list_ims[0][0]), int(list_ims[0][1]), RGB)

list_group=[pdb.gimp_layer_group_new(image) for i in structure_safe_all]

for i in range(len(list_group)):
    #list_group[i].name = structure_safe_all[i]
    list_group[i].name = structure_all[i]

base_group = []
list_hierarchy = []
for i in range(len(structure_safe_hrchy)):
        if len(structure_safe_hrchy[i])>1:
            list_hierarchy.append(structure_safe_hrchy[i])
        else:
            base_group.append(structure_safe_hrchy[i])

base_group = base_group[::-1]
list_hierarchy = list_hierarchy[::-1]
for  i in range(len(base_group)):
    image.add_layer(list_group[structure_safe_all.index(base_group[i][0])], i)


list_remove = []
for i in range(len(list_hierarchy)):
    test = list_hierarchy[i][::-1]
    if len(test)>1:
        for j in range(len(test)-1):
            check=[test[j+1], test[j]]
            if not check in list_remove:
                list_remove.append(check)
                group_check = [list_group[structure_safe_all.index(check[0])], list_group[structure_safe_all.index(check[1])]]
                pdb.gimp_image_insert_layer(image, group_check[0], group_check[1], i)
                print(check)

gimp.Display(image)

for num_setting in range(len(list_ims[1:][::-1])):
    layer_setting = list_ims[1:][::-1][num_setting]
    try:
        layer = pdb.gimp_file_load_layer(image, layer_setting[0])
        layer.set_offsets(int(layer_setting[1]), int(layer_setting[2]))
        layer.name = gimp_file_name[num_setting]
        pdb.gimp_drawable_set_visible(layer, int(layer_setting[4]))
        
        key = layer_setting[5].replace("\\r","")
        gimp.message(key)
        if key == "this_is_base_group":
            image.add_layer(layer, num_setting)
        else:
            pdb.gimp_image_insert_layer(image, layer, list_group[structure_safe_all.index(key)], num_setting)

    except:
        pass

drawable = pdb.gimp_image_get_active_layer(image)
pdb.gimp_xcf_save(0, image, drawable, dir_save, dir_save)

gimp.Display(image)

'''.format(self.dir_save_setting, dir_save_gimp, self.gimp_structure_all, self.gimp_structure_hrchy, self.gimp_structure_safe_all, self.gimp_structure_safe_hrchy, self.gimp_file_name)


        with open(dir_save_gimp_cmd,"w",encoding="utf-8") as gimp_file:
            gimp_file.write(gimp_cmd)
        subprocess.run("explorer {}".format(self.dir_save_base))



if __name__=="__main__":
    print("グループ名が重複しているとバグが発生して正常に変換できません。\n手動でPSDファイルを編集して、グループ名が重複しないようにリネームしてください。\n(例: 「Group」→「Group #1」)")
    print("もしくは1度Gimpでpsdファイルを開き、再エクスポートしてください。\n重複が自動で解決されます。")
    dir_psd = input("waifu2xで変換したい.psdファイルをD&DしてEnterを押してね!")
    psdp = PSDPaser(dir_psd)
    psdp.waifu_run()
    psdp.gimpImportCommand()

psd2wife.ini


[save]
safety=G:\Dev_Doc\gimp
[waifu]
directory   = O:\files\waifu2x-caffe\waifu2x-caffe-cui.exe
wife_scale  = 2.0

psd2waifu2x配布・サポート(?)ページ

こんにちは、鐵火卷です。

このページは先日公開いたしました「psd2waifu2x」の配布、サポートページとなっています。

配布

「psd2waifu2x」は以下のonedriveよりダウンロード可能です。
https://1drv.ms/u/s!AsMZ4BamVPJEgTMsrM3wn266tDUT

また、別ページのソースコードをコピペして使用してください。

動作環境

windows (10でのみチェック)
Python 3.x系列 (3.7でのみチェック)
Gimp (インストール版でのみチェック)
waifu2x-coffee

使い方

動画を参照してください。

サポート

困ったことがあれば、コメント欄に記載していただければと思います。
ただし、以下の内容についてはお答え出来かねます。

・動作確認など(特に、このスペックで動作しますか?といった質問)
・GUI作って!
 → 初学者なので現状は無理です。数年後 or 別の人に頼んでください。
・ポータブルにしてほしい!
 →ironpythonとgimpのポータブルとかでも行けるんですかね?誰か検証してください。
・Gimpのpython上ですべて完結すればいいのでは?
 →gimpで日本語のファイルとディレクトリを扱えるようにする手段をだれか教えてください…

FAQ?

Q1. グループ名が被っているとGimpでの再構成でエラーが出る
A1. Gimpで一度.psdファイルを開き、.psdとしてエクスポートしてください。
Gimpは同じ名前のグループ、レイヤーを作成することが出来ません。
ですので、.psdファイルを開くだけで自動的にリネームしてくれます。

Q2. Gimpでレイヤーが読み込まれない
A2. 保存先として設定したディレクトリに非アスキー文字が含まれているためです。
ディレクトリに半角英数しか含まれていないことを再度確認してください。
場合によっては半角スペースもエラーの原因かもしれません。

Q3. Pythonのプログラムでエラーが出る。
A3. それ、Pythonの2.x系列じゃないよね?
あと、要求されるモジュールもインストールしてね。
場合によってはpipのアップデートが出来てないのかも?

Blender2.8のPythonにモジュール類を簡単に移行するには

こんにちは、鉄火巻です。

前の記事では、Blender内のPythonにモジュールをインストールする方法を紹介しました。

ここでは、通常のPyhtonで使っているモジュールをBlenderに移行するとき、バージョンなどを指定しながらいちいち移していく面倒を解決する方法です。
といっても、よくあるやり方です。

手順

これはシンプル。まずは、通常のpythonの環境から各種モジュールのバージョンを記載したテキストファイルを生成しましょう。

python -m pip freeze > requirement.txt

生成先は指定できるので、取り出しが面倒であれば、直接Blenderのあるフォルダに生成してあげましょう。

python -m pip freeze > "O:\files\blender-2.80.0-git.99d4321feff6-windows64\2.80\python\bin\requirement.txt"

次に、cd, cd/dなどで移動して、

cd/d  
O:\files\blender-2.80.0-git.99d4321feff6-windows64\2.80\python\bin

pipからインストールしましょう。
前の記事でも書きましたが、Blender側からモジュールを読み込むには–userのオプションが必須です。

 python.exe -m pip install -r requirements.txt --user 

以上です。特に難しいってわけではなさそうだね。

それでは、鉄火巻でした。

Blenderに搭載されているPythonにpipを導入しよう(Windows10, ポータブル版)

こんにちは、鉄火巻です。

最近Blenderを触っているんですが、外部のモジュールをどうしても使いたいのでpipを導入しようと思います。といっても、参考サイトとやってることは同じだし、特に変なことはしていません。

手順

以下をcmdで実行しましょう。管理者権限はあった方がいいんじゃないかな? Blender2.8を使用しているため、ディレクトリはProgramfileではありません。いわゆるポータブル版です。 インストーラーを使ってインストールすればProgramfileのどこかに同じようなフォルダがあるでしょう。

 "O:\files\blender-2.80.0-git.99d4321feff6-windows64\2.80\python\bin\python.exe" -m ensurepip

すると以下のようにpipとsetuptoolsがインストールされます。ただし古いバージョンです。

C:\WINDOWS\system32>"O:\files\blender-2.80.0-git.99d4321feff6-windows64\2.80\python\bin\python.exe" -m pip list
Package Version
---------- -------
pip 10.0.1
setuptools 39.0.1

ですので、以下のようにそれぞれアップデートしてあげましょう。これも特に変わったことではありません。

 "O:\files\blender-2.80.0-git.99d4321feff6-windows64\2.80\python\bin\python.exe" -m pip install --upgrade setuptools pip

これで最低限pipはインストールできました。pythonから環境を移行するときは以下のように主環境でrequests.txtを生成してやればよいでしょう。

この辺のモジュール(https://qiita.com/haminiku/items/5187713bba6cb30532bf)を入れておくと便利でしょう。

注意) –userのオプションが必要

pipの触り方は以上のように、Blender内のpythonを直接たたけばよいのですが、以下のようにモジュールをインストールすると、Blenderからimportする時にエラーを吐きます。

".../python.exe" -m pip install [module name]

調べたところ、インストールには–userのオプションが必要です。面倒ですが、毎回、以下のようにインストールしましょう。

 ".../python.exe" -m pip install [module name] --user

参考

https://www.kunihikokaneko.com/dblab/cg/bpypip.html

https://blenderartists.org/t/how-to-install-python-packages-with-pip-blender-2-8/1142721/3

余談

当たり前ですけど、以下からpythonのバージョンは確認可能です。

 "O:\files\blender-2.80.0-git.99d4321feff6-windows64\2.80\python\bin\python.exe" -V

多分ですけど、主環境と同じpythonが入るみたいですね(ポータブルだからかな?)。僕の環境では3.7.0って返ってきました。


以上です。pipがあれば開発が捗りますね。 必要なモジュールが入れば開発の幅は一気に広がりますね。

それでは、鉄火巻でした。

関連記事

pythonで感情分析に入門

こんにちは、クロガネです。

皆さん、ネットを徘徊していて書いてある文章にどんな感情が込められているのか?ということが気になったことはないでしょうか?

まあ、文学に精通している人であれば言葉の表現のみで大体わかるんでしょうけど、僕の場合は特に文学的な部分は触れずに育ってしまったので言葉に堪能ではありません。

とはいえ、感情を読み取ることは人間生活において重要であることは変わりありません。

ということで、辞書を活用して単語の意味から自動で込められた上辺の感情を読み取ろう、というのを、今回Pythonで進めていきます。勿論、人工知能ではありません。

Pythonのインストールまでは割愛です。こちら(http://oita.oika.me/2018/05/03/python3-mecab-on-windows/)を参考にして必要なものをどんどんインストールしておきましょう。

概要

ML-Askというものを利用して、感情表現辞典を元に文字列の含まれる感情表現を抽出、評価します。

ML-AskにはMeCabが必要だそうなので、

MeCabのインストール ② 辞書をNEologd辞書に変更 ③ ML-Askのインストール

の手順で進みます。

また、ここではWindows10 64bit環境で進めていきます。

MeCabのインストール

Pythonは64bitなのでここからダウンロードして、64bit版をインストール。これはページにも書いてありますが公式ビルドのものではありません。ただ、出来るだけ簡単に導入したいのでこれを使います。

問題点は辞書がUTF-8なのでコマンドプロンプトなどから利用する場合に文字化けしまくります。ほかの用途で使うなら向かないかも???

注)32bit版のPythonを使用しているなら公式からダウンロードして利用出来ます。

実行して、そのままインストールしていきます。特にバンドルウェアなどはなさそう(多分)。

インストールできたら、 C:\Program Files\MeCab\bin にPATHを通す。

上手くいかない場合は、C:\Program Files\MeCab\binにある実行ファイルを直接指定しても実行自体は可能。

あと、再起動をかければどうにかなる。

最低限の動作チェック

環境変数の登録が上手くいかなくても、直接実行ファイルを叩いてあげれば動いているかどうかはチェックできる。 文字コード的な問題で文字化けするのでその辺はいったん気にしないでおこう。

Python のMeCabラッパーをインストールする。

ここからが本命。mecab-python-windowsというPythonのラッパーをインストールする。これでPythonからMeCabを操作できるようになる。

インストールはpipから実行すればよい。仮想環境の切り替えなどは適宜行えばよいので割愛。

  pip install mecab-python-windows

すんなり入った。

そのままipythonで動作チェックしてみる。

  import MeCab
m = MeCab.Tagger("-Ochasen")
print(m.parse("すもももももももものうち"))

問題無く動作することを確認。例文も参考元からそのままだね。

NEologd 辞書を導入

標準の辞書の制度がそこまでよくないらしい。そのため、精度をよくするために別の辞書であるNEologd辞書を導入しておく。

この部分は実はいらない、ここから少し面倒になるので割愛してよい。

NEologd辞書のビルドがLinux環境でしかできないらしい。ここで、Linux機を導入するのも面倒なので、Linux環境がない人はWindows Subsystem for Linux(WSL)を使用する必要がある。なので、まずはWSLのUbuntuをインストールしていきます。

参考: https://qiita.com/ChenZheChina/items/42f1fcc763e88cb02cca

まずはWSLの使用許可

これは管理者権限ありのPowerShellで以下のコマンドを実行すればよい。

  Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

ちなみに、アイコンを右クリックすれば「管理者権限で実行」が出てくる。

以下のような画面が出てくるので少し待つ。

すると再起動を求められるので、ここで再起動。

WSL用のUbuntuをインストール

導入自体は簡単。Microsoft Storeでインストールする。「Ubuntu」って検索すれば出てくる。

容量もそんなに食いません。容量が足りない場合は適当に要らないものを消すか、…というかそんなに容量が足りない状態でPC使うなよ(笑)って感じですな。ストレージの交換かディスクのクリーンアップでもしておきましょう。

インストールが終わればポップアップが出てきます。

インストールが終われば起動します。普通にスタートメニューに登録されます。

初回起動時はUbuntuのシステムのインストールから始まるようです。少し待ちましょう。

まずはユーザーネームとパスワードを設定します。これが終わればubuntuを利用できるようになります。これらのユーザーネームとパスワードは任意のものでよいです。

WSLのUbuntuでのインストールの下準備

実は、ビルドの準備はまだ終わらないんだ。とはいえ、以下の手順でやっていけば恐らく正常にインストールできるはず。時間がちょっとかかるけどね。以下はWSLのUbuntuのターミナル内での作業。

まずはaptのアップデートとupgradeをかませておく。

  sudo apt update
sudo apt upgrade

この辺りでいきなりエラーが出まくるので、恐らく、リポジトリを日本サーバーに変更することで解決される?? 以下を実行することで僕の環境では解決した。その後、aptのアップデートなどを再度試してエラーが出ないことを確認。https://qiita.com/Aruneko/items/c79810b0b015bebf30bb

  sudo sed -i -e 's%http://.*.ubuntu.com%http://ftp.jaist.ac.jp/pub/Linux%g' /etc/apt/sources.list

後のNEologdのビルドでエラーが出るのを避けるため、build-essentialを再インストールしておく。ビルド時にmake is not found.というエラーが出た場合、「build-essential」の再インストールが必要だそうだ。というか何もせず進めたら出た。http://zaka-think.com/linux/ubuntu/ubuntu-make-error/

  sudo apt install --reinstall build-essential

ただ、上の日本サーバーに切り替えをしておかないとここで躓くのでやっておこう。

gitをインストールする必要があるので、以下でインストール。

  sudo apt-get install git

gitと入力すると、各種コマンドについての説明が出てるので恐らく問題ない?

  git

また、gitの初期設定も行う…ってのはいらなかった。逆に、GitHubにいってアカウントを作っておこう。これはググってwebサイトに行ってね。

  git config global user.name [任意のユーザ名]
git config global user.email [任意のユーザ名]

NEologd辞書のビルドとmecab関連のインストール

gitがインストールできたので、mecab関連をインストールしていきます。この手順が不要かどうかは試していない…。まあ、入れておきましょう。

  sudo apt install mecab
sudo apt install libmecab-dev
sudo apt install mecab-ipadic-utf8

次に、gitを用いてNEologd辞書をインストールしていきます。この時にgithubのユーザーネームとパスワードが必要になります。入力して問題がなければ、インストールされる容量が結構あるのでじっくりと待ちましょう。約350MBです。

回線速度というか、よくわからない何かがボトルネックになっているかと。1Mbpsは出ていなかった…。

  git clone https://github.com/neologd/mecab-ipadic-neologd.git

ダウンロードが済んだら、移動してビルドしましょう。上記手順をすべてこなしていれば恐らく正常にインストールできるはず。僕は上記手順のみでできた。

  cd mecab-ipadic-neologd
sudo bin/install-mecab-ipadic-neologd

NEologd辞書をWindows側の移す

ビルドされた辞書をWindows側に移していきます。

Ubuntu側のNEologd辞書は/usr/lib/mecab/dic/mecab-ipadic-neologd/にある…?\usr\lib\x86_64-linux-gnu\mecab\dicじゃね? 僕の環境では後者の場所にありました。

これをWindows側のC:\Program Files\MeCab\dic\ipadic-neologd\にコピーすればよい。こんな感じ?まあ、多分フォルダ名まで変更する必要はなかったかと。

注) コピーについて

多分、WSLのUbuntu側から操作してコピーできるかもしれないけど、面倒なので直接取りに行く。

Ubuntuのフォルダは、%LOCALAPPDATA%\Packages\内にある。Windows側のエクスプローラーに直接入れて叩けば飛んでくれる。

その中から、CanonicalGroupLimited.UbuntuonWindows_[謎の文字列]というフォルダを見つけて、「LocalState」→「tootfs」と順に移動していけばUbuntu内のファイルにアクセスできる。

「mecab-ipadic-neologd」フォルダの場所の例は以下。[ユーザー名]と[謎の文字列]はたぶん人によって違う。

C:\Users\[ユーザー名]\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_[謎の文字列]\LocalState\rootfs\usr\lib\x86_64-linux-gnu\mecab\dic\mecab-ipadic-neologd\

参考: https://qiita.com/keita44_f4/items/4fffda7048b2c3554f14

mecabが指定している辞書の位置を変更する

最後に、C:\Program Files\MeCab\etc\mecabrc (拡張子無しのファイルだよ)をテキストエディタで開いて、6行目のdicdir = $(rcpath)\..\dic\ipadic

  dicdir =  $(rcpath)\..\dic\ipadic-neologd

に書き換えます。

注意事項として、テキストエディタ側に管理者権限がないとこのファイルは書き換えができないので要注意。

動作チェック

再度、以下で確かめてみる。

  import MeCab
m = MeCab.Tagger("-Ochasen")
print(m.parse("すもももももももものうち"))

????

微妙?もっと長い文章で試しておいた方がいいかもね。

WSLでのコピペ

注意、WSLの画面にコマンドをコピペするにはCtrl+Vでは(多分)できません。ただ、左上のアイコンをクリックするとメニューが出てくるので、ここから貼り付けます。

ML-Askを導入

これでようやく感情分析に入ることが出来ます。以下を参考にしてML-Askを導入していきましょう。

参考: https://qiita.com/yukinoi/items/ef6fb48b5e3694e9659c?utm_source=stock_summary_mail&utm_medium=email&utm_term=kwtsh365&utm_content=ML-Ask%E3%81%A7%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%AE%E6%84%9F%E6%83%85%E5%88%86%E6%9E%90&utm_campaign=stock_summary_mail_2018-12-29

インストール

以下からインストール

  pip install pymlask

問題無くインストールできた。

動作確認

  from mlask import MLAsk
emotion_analyzer = MLAsk()
emotion_analyzer.analyze('彼のことは嫌いではない!(;´Д`)')

最低限動いてくれているようだ。ぱちぱち。おめでとう。

今回出来るようになったことのまとめ

出来るようになったのは形態素解析と感情分析

  import MeCab
from mlask import MLAsk

string="近年では、親愛の情を込めて友人、知人や親族にも贈るお歳暮へと少しずつ変化してきているようです。"

m = MeCab.Tagger("-Ochasen")
print(m.parse(string)

emotion_analyzer = MLAsk()
emotion_analyzer.analyze(string)

結果はこんな感じ。

最後に

これで、形態素解析+感情分析が一応出来るようになりました。ここから、ML-Askの使い方を学んでいけば、最低限の感情分析を出来るようになるかと。

適当にモジュールを使って、何かしらのパラメーターを取り出して言えたらいいなー、って感じだね。

まあ、人工知能的なものではないので、辞書をカスタムしないと精度はよくならないので、この辺はGoogleとかIBMとかMicrosoftとかの感情分析の方がちゃんとパラメーターを取り出せるんだろうけどね。

こっちの方がお金はかからないのでいいね。

それでは、クロガネでした。

termcolorでPythonのprint文に色を付けよう!

こんにちは、鉄火巻です。

プログラムを作っていて、結果の表示やデバック用にprint()をよく利用しています。

しかし、コマンドプロンプトの真っ黒な画面に白文字のみ表示されているため、なんとなくおもしろみがありません。
とはいえ、コマンドプロンプト自体の色やフォントの色を変えるもの違うし…

、と探していたらちょうどいいモジュールを見つけました!

termcolorというモジュールをインストールすると、出力に色を付けることが出来るようです!
pypi: https://pypi.org/project/termcolor/

termcolorの導入

というわけで、さっそく導入していきましょう!

「termcolor」というモジュールをpipからインストールします。

  pip install termcolor

以上でOKです!簡単だね。

Let’s 試用!

ipython上で確認していきましょう。

使い方は、文字列の入った変数に色付けをして新しい変数に入れる、といった感じですかね?

  import termcolor
print(termcolor.colored("a","red"))

以下のようにしても問題なく使えます。こっちの方が短くていいね。

  from termcolor import colored
print(colored("ai", "red"))

すると以下のように色が付く。

これで装飾できました。ぱちぱち。

….

と思ったけど、プログラムに意気揚々と組み込むと上手くいきません。

Windows向けの解決策

どうやらWindowsでは「colorama」というモジュールもインストールする必要があるようです。

参考: https://stackoverflow.com/questions/21858567/why-does-termcolor-output-control-characters-instead-of-colored-text-in-the-wind

読んでみたところ、文字コードの問題CP932ちゃんは自己主張がつよいですね~。

以下のように「colorama」というモジュールを追加でインストールします。

  pip install colorama

また、coloramaを初期化する必要があるので、import辺りに同時に突っ込んでおきましょう。多分、初期化さえされていればどこもよいのでしょう?

  from termcolor import colored, cprint
import colorama
colorama.init()
cprint("aa", "red")

ipythonでなくともちゃんと色付けされて出力出来ることが確認できました!

おめでとう。

大まかな色付けの仕方

色付けの仕方には、cprint()と、colored()の2通りがあります。

基本的に使い方は一緒で、「 cprint() = print() + colored() 」なだけですね。

文字列の一部や、変数に入れた文字列を色付けするときにcolored()の方を使えばいいってかんじですかね?

  cprint("{string}", "{text colors}", "{text highkights}", attrs=["{attributes}"])

例:

※エラー文的にも、「 cprint() = print() + colored() 」はあっているみたいですね。適当にエラーを吐かせると、以下のように表示されます。

  print((colored(text, color, on_color, attrs)), **kwargs)

使える色

色のリストは上記pypiのページにあります。上記から引用。
詳細は上記pypiに行きましょう。

Text colors:

grey

red

green

yellow

blue

magenta

cyan

white

Text highlights:

on_grey

on_red

on_green

on_yellow

on_blue

on_magenta

on_cyan

on_white

Attributes:

bold

dark

underline

blink

reverse

concealed

※attributesはwindows環境ではreverseしか利用できないことに注意。どのattributeがどの環境で利用できるかは、上記pypiのサイトに書いてあります。

上でやったけど、reverseも効いてなくね?謎だね。

一部を色付け

以下のようにしたら一部を無理やり色付けできる。多分簡単な方法はあると思うけど、正直これで問題無く使用できます。

  print(colored("[loop{0}]: ".format(self.looptimes), "red"),"Finish load lib")

まとめ

今回はコマンドプロンプトに色を付けることが出来るようになる「termcolor」を紹介しました。うまく使えば結果の視認性も上昇かもしれないですね。

ただし、Windowsユーザーの方は一緒に「colorama」も導入する必要があるので注意が必要です。若干冗長的になります。


以上です。これで味気のないコマンドプロンプトの画面を煌びやかにすることが出来るようになりました!おめでとう!

ただ、毎回、importするたびに初期化も書いてあげないといけないのが難点ですね。

とはいえ、装飾したほうが他人に渡すときは見やすくていいかもね。
もちろん、配色にもよると思うけど。

それでは、鉄火巻きでした。

Notepad++から直接Pythonを実行しよう!


こんにちは、鉄火巻です。

Notepad++は個人的にとても気に入っているエディタです。
かなり軽量で便利です。今時少ないメモリ2GBのWindows10機でももたつくことなく動かすことが出来るので貴重なエディタです。

エディタはいろいろあるのでNotepad++が一概にいいわけではありません。
知り合いにGENIEをすすめ勧められたこともあります。F5で保存&実行が可能なのはとても便利に思いました。
ちょっと揺らいだんですけど、Notepad++で関数名や変数を選択すると全部ハイライトしてくれるのはとても便利で捨てられない要素です。

というわけで、そういったNotepad++の弱点を塞いでいきましょう。
Notepad++から、直接Pythonを実行できるように設定します。

と思ったんですが以外にドキュメントがありません。

幸い、転用可能に思われるドキュメントはいくつかあったことと、知り合いの助けがあって実行できるようになりました。ということで共有していこうと思います。

概要

Notepad++には「ファイル名を指定して実行」という機能があります。この機能を利用して
仮想環境も利用できる応用的な手法です。

batファイルを作る

いきなりコードを掲載します。適宜、ファイル名を書き換えて使用してください。僕は「npp_python.bat」で登録しました。「Python.bat」や「cmd.bat」はよくないといううわさを聞いたことがあるので避けた方が賢明なようです。

@echo off
python %~f1
pause

また、venvの仮想環境を設定したい場合は以下のように指定しましょう。仮想環境を呼び出すときと同じ手順です。

@echo off
call c:\work\pywork\envs\expenv\Scripts\activate.bat
python %~f1
call deactivate
pause

また、個人的に、「pause」部分を以下のように変更すると便利です。

timeout 10

プログラムの終了後の10秒後、もしくは何かのキーを押すと自動でコマンドプロンプトの画面が閉じられます。開きっぱなしになることを防ぐことが出来ます。まあ、毎回閉じればいいんですがね…。

ともあれ、エラーコードを読むにしても30秒くらいに設定しておけば問題ないとは思います。

.batファイルをNotepad++から呼び出す

次にNotepad++側の設定をしていきましょう。
「設定(R)」→「ファイル名を指定して実行(F5)」に以下を記入します。

(.batファイルのディレクトリ) "$(FULL_CURRENT_PATH)"

入力したらこんな感じ。

「(.batファイルのディレクトリ)」部分は、「c:\work\npp_python.bat」のように、上記.batファイルのディレクトリを指定します。例えば、「c:\work\」に先ほど作成した.batファイルがある場合は以下のようになります。

c:\work\npp_python.bat "$(FULL_CURRENT_PATH)"

また、「”$(FULL_CURRENT_PATH)”」との間に半角スペースが必要です。

このまま実行してみて問題無く実行されることを確かめましょう。

問題無く実行されたら、先ほどの「ファイル名を指定して実行(F5)」のウィンドウを再度開き、ショートカットキーに設定しておきましょう。
下図の赤枠部分をクリックして、

僕は以下のように「Ctrl+F5」に登録しました。ショートカットキーは競合しなければどのように設定しても問題ないので、お好みで。既定のショートカットキーも変更できるので不要なものを削除してから登録してみてもいいかもしれません。
また、「Python」などのように何のショートカットキーなのかが分かりやすい名前も登録しておきましょう。

そうすれば、次回以降は「Ctrl+F5」を押すことで、開いているPythonのコードをNotepad++から直接実行することができるようになります。

ぱちぱち。

仕組みについて

これでめでたく実行できるようになりました。ただ、投げっぱなしもよくないので、可能な範囲で解説していきます。

Notepad++の設定

まず、Notepad++側の設定から。簡潔に言えば、Notepad++で開いているファイルのフルパスを.batファイルに渡します。

(.batファイルのディレクトリ) "$(FULL_CURRENT_PATH)"

「ファイル名を指定して実行(F5)」は名前の通り、ファイル名を指定して実行することが可能です。なので、関連付けさえされていれば何でも実行させることが出来ます。勿論.exeファイルも実行できます。

「”$(FULL_CURRENT_PATH)”」部分は、Notepad++の「ファイル名を指定して実行(F5)」のウィンドウを開いたときに使用していたタブのフルパスが入るようです。

例えば、「helloworld.py」をNotepad++で開いていた場合、「”$(FULL_CURRENT_PATH)”」部分に「helloworld.pyのフルパス」が入ることになります。「helloworld.py」を「c:\work\」に保存していた場合、「c:\work\helloworld.py」が渡されていることになります。

また、この時、”$(FULL_CURRENT_PATH)”が、作成した.batファイルの第1引数に渡されることになります。

.batファイルの仕組み

基本的に、ただの.batファイルです。詳しい方は何でもできます。
以下を解説していきましょう。

@echo off
python %~f1
pause

といっても、説明する部分は「python %~f1」位しかありません。これも.batファイルでは普通のことですが、ほかは普遍的すぎるので省略します。

「python %~f1」は、普段、「python helloworld.py」とかやって.pyファイルを開くことと同じです。

ミソは「%~f1」部分です。これは、「第1引数をファイル位置として受ける」という意味です。

もともと、「%1」で第1引数の入る場所を指定できます。例えば、「~.bat aaa」として、「echo %1」としておけばコマンドプロンプトの画面に「aaa」と表示されるはずです。

ただし、「%1」のままでは文字列として扱われ、ファイル位置として扱われません。少なくとも、僕の環境では「%1」のままではPythonのコードをNotepad++で実行できませんでした。

ここを「%~f1」とすると、第1引数をファイル位置として扱ってくれます。

前述のように、Notepad++の「ファイル名を指定して実行(F5)」で.batファイルに「”$(FULL_CURRENT_PATH)”」を第1引数として渡しているので、この.batの第1引数に開いているファイルのフルパスが渡されます。

例えば、先ほどの例だと、2行目部分が「python c:\work\helloworld.py」と同じになります。これで、問題なく実行できるようになります。

まとめ

どうでしたか?実行できるようになりましたか?
まあ、プラグインで一発で解決するらしいですけどね。
とはいえ、ここに書いてある内容をコピペすれば問題なく実行できるようになるはずです。

ただし、GENIEのように「保存&実行」が出来ているわけではありません。
そのあたりは、適宜「Ctrl+s」を押してから「Ctrl+F5」を押しましょう。押すボタンが1つ増えるだけです。
逆に保存しないと変更前のファイルが実行されるので要注意です。

これで便利なNotepad++が一層便利になりました。
個人的にとても気に入っているので今後もNotepad++民として使い続けたいですね。

それでは、鉄火巻でした。

Android端末上でもPython3を動かすことが出来る「Pydroid 3」

こんにちは、鉄火巻です。

Pythonの勉強をちょっとだけやっています。
ただ、開発環境がPCに限られているので、家でしか実行できないという部分が問題でした。

そこで見つけたのがPyroid 3です。

play.google.com

「Pydroid 3」で何が出来るのか

これはオフラインで動くPython 3.6にIDEのようです。
僕自身が把握できている特徴としては、

といったところでしょうか。

端的にまとめると、僕程度の素人であれば大抵のことは出来ると思われます。

インストール

GooglePlayで「pydroid」と検索すれば「Pydroid 3 – Educational IDE for Python 3」というアプリが出てきます。
play.google.com

普通にインストールします。
f:id:kurogane-games:20180926001731p:plain
容量は41.85MBでした。意外と軽量。

Android 4.4以上に対応しているので、それより古い端末では利用できません。
とはいえ、4.4 KitKatはリリース日が2013年10月31日なので、今時の端末であればそもそも気にする必要はないでしょう。
古い端末を再利用するときだけ気を付けてください。

ちなみにアイコンはこんな感じ。
f:id:kurogane-games:20180926002316p:plain

起動するとインストールが始まります。
しばらく待ちましょう。
f:id:kurogane-games:20180926002530p:plain

また、C++IDEをインストールしてみてね、って出てきます。
f:id:kurogane-games:20180926002516p:plain
多分、インストールはしなくてもいいと思われます。

インストールが終わればIDEの画面が姿を現します。
普通のエディタとおおよそ同じですね。
f:id:kurogane-games:20180926002636p:plain

Hello World“してみる

まずは”Hello World“をしてみましょう。
単純に、

print("Hello world")

で実行します。

実行するときは右下の黄色の再生ボタン(▶)を押しましょう。
実行すると、コンソール画面に切り替わります。
ちゃんとprint()文が働いてくれていますね。
f:id:kurogane-games:20180926003003p:plain

今回はこの辺で。
次回はpipを使ったパッケージのインストール、外部ファイルの読み込みなどを試してみたいと思います。

それでは、鉄火巻でした。

python-pptxインストール直後にエラーが出たときの対処法

こんにちは、鉄火巻です。

 

今回はプログラミング系の記事。

python-pptxインストール直後にエラーが出たときの対策を書こうとと思います。

概要

 PythonからPowerPointファイルを生成しようとしたらいきなりエラーを吐きました。

まずはインストール 

pip install python-pptx

次に下のGetting Startedの「Hello World! example」の実行でエラーがいきなり出ました。
Getting Started — python-pptx 0.6.13 documentation

エラー1「lxmlモジュール」

ImportError: cannot import name 'etree' from 'lxml'

これは以下を実行したら改善(?)した。

pip install lxml -U

バージョンとかの問題だったのかな?

エラー2つ目「Pillowモジュール」

上記の「lxml」モジュールの問題が解決したら次に以下の問題が出た。

ImportError: No module named Image

同じくアップグレードをかけても解決しなかったので、再インストールを試みたら問題無くGetting Startedの「Hello World! example」が実行できた。

pip uninstall Pillow
pip install Pillow

これは何が問題だったのかは不明。
少なくとも、Python自体を再インストールしたら改善した、ってのをweb上で見つけたので、代わりにモジュールを再インストールしてみたらうまくいった。

これで問題無くPythonからPowerPointファイルを生成できるようになりました。

ぱちぱち。

それでは、鉄火巻でした。