2020年2月24日月曜日

雑記いろいろ


  • 自動翻訳機

父に頼まれて、電子手帳と自動翻訳機を買いに行きまして、Arrows Hello を買ったのですよ。
(ちなみに、安定のポケトークにしなかったのは3年目以降の使用料とオフライン使用ができないから。)
事前に電子翻訳機の翻訳率は6割程度と知っていたのですが、割と翻訳してくれます。
あと、地味に凄いのがカメラで取り込んだ画像の自動翻訳。縦書きでも翻訳してくれるんですよアレ。
新聞が中国語になったりするのは地味に感動します。
未来が着てますね。


  • ジャンク

秋葉原の tokka バザールで Thikpad X230T が1.3万ほどで出てますね。
Blender 使いとしては Linux を入れてモデリング~リギングまではコレ1台で行ける良機種。
Fn 同時押しテンキー入力と、アキュポインタ、3ボタンパッドまでついているのでモデリングしやすいです。
…なのですが。
良く見ると、tokka さんデジタイザペンを付けてないのですよ。それじゃ売れないと思うな。
2in1 中央ヒンジの宿命で重量がかさみ1.8kgもあるので持ち歩きには向きません。
また、同じく中央ヒンジの HP Elite Book とダダ被りしてます(ちなみに私は Elite Book 2760p ユーザー)。
趣味として持っておきたい人向けですかね。


  • HP と言えば、Envy x360 13-ar0000 シリーズ

以前、コスパでぶっちぎりと書いた Lenovo ideapad C340 に唯一対抗できる 2in1 じゃないでしょうか?
Ryzen 5 3500U モデルで比較すると値段が4万円増しの10万円しますが…重量が400g軽い1.28でこちらは完全に持ち歩き可能。
地味に気にしていたのがメモリで、全オンボードの為、シングルチャンネルか?と思ったのですが、ちゃんと2枚実装のデュアルでした。Ryzen は intel の Core シリーズと比較して、シングルコアで遅く、多コア動作で早いという特性があるのでメモリ実装がシングルだと intel 以上に差がでます。特に画像処理系のソフトで。
※4/9追記
どうやら Envy x360 の13インチ版は排熱がうまく行っていないようで、熱により処理速度の低下が起こるそうですね。排熱しようとすると今度は大型化する訳で…トレードオフが難しい所ですね


  • やっぱりウィルスの影響で…

秋葉のパーツ価格が上がっています。中国の工場が稼働できないという事が直撃しているんですね。
恐らく、Lenovo 等の PC メーカーも出荷が遅れる事態が出てくると思われます。
本来なら、新入学/入社キャンペーンが張られるこの時期ですが、動きが鈍いです。
あと、PC授業の義務化に伴う子供向けPCが出始めていますが…コレ、子供向けじゃなくて子供だましだよ。
eMMC のパソコンに Win10 なんか入れたらアップデートが地獄だよ?学校の保守担当者が過労で倒れるのが目に見えるようですが、先ずは文科省の人間にパソコンを理解できるように教育した方が良いのでは?


  • 技術といえば

突如ニコ動で祭りが始まったAIきりたん。歴史が変わった感じがします。未来が着てますね。
ただ、ウチのニコ動、去年の中辺りからシークバー詐欺がでて再生が酷いんですよね…。別窓でホームページを見ている時が特に酷く、別窓でネットアクセスすると止まるので「作業用動画」を流しながら作業もできない。
Ryzen 5 2600 なんですけど、メモリ16GBなんですけど、光ギガ通信の回線使ってるんでけど!有料会員なんですけど!!
…劣化復活したニコると言い、どうしてニコ動は劣化して行くんですかね?もちろん、時代に合わせて画質や音質を上げては来ているのですが、再生できない動画サイトって論外だと思います。
いっそ初心に立ち返って、YouTube にコメント付けるサービスにでもなってしまえば良いのではないでしょうか。

2020年2月19日水曜日

Python+Kivy 地獄編 無意味なアプリを作って地獄の扉を開けてみる


…四の五の言わずに先ずは出来上がったモノなんですけどね。

※例によって Linux Mint 19.2 + Python2.7 です
画面下の方に見えるのは以前作ったカラーを決めるGUI群。中央に見えるのは解りづらいですが、ディレクトリ検索。上に見えるのは Blender をパク…リスペクトしたファイル作成GUI。
しかして、「CREATE」ボタンを押すと…
指定した色の15x15ドットの24ビットカラーの四角いBMPファイルができるだけ。
しかもエラー処理も書いてないから、上書き禁止フォルダに書き込もうとすると落ちる等バグは放置してます。

何かの役に立つアプリを作る気は毛頭なくて、
Python でバイナリファイルを作る処理を組む
Bitmap ファイルの扱い方を思い出す
という目標と後述する目的の足掛かりとして作成しました。

コード

## make bmp ##

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.slider import Slider

from kivy.uix.floatlayout import FloatLayout

import os
from os.path import join,isdir

from kivy.uix.filechooser import FileChooserIconView
from kivy.uix.filechooser import FileChooserListView

### Input Directory
#class DirectoryChooser(FileChooserListView):
class DirectoryChooser(FileChooserIconView):
    def is_dir(self,directory,filename):
        self.parent.parent.t1.text = directory
        return isdir(join(directory,filename))

class BoxSelectFile(BoxLayout):
    orientation='vertical'
    def __init__(self,**kwargs):
        super(BoxSelectFile,self).__init__(**kwargs)
        self.dc =DirectoryChooser(size_hint_y=1)
        self.dc.filters=[self.dc.is_dir]
        self.add_widget(self.dc)

### Input FileName
class BtSave(Button):
    def on_press(self):
        self.parent.parent.MakeFile()

class BoxSaveFileName(BoxLayout):
    orientation='horizontal'
    def __init__(self,**kwargs):
        super(BoxSaveFileName,self).__init__(**kwargs)
        self.t1 = TextInput(text='',size_hint_x=5,multiline=False)
        self.l1 = Label(text='.bmp',size_hint_x=2)
        self.b1 = BtSave(text='CREATE',size_hint_x=3)

        self.add_widget(self.t1)
        self.add_widget(self.l1)
        self.add_widget(self.b1)

### Input Color Value
class TxiColor(TextInput):
    def on_text_validate(self):
        value = int(self.text)
        if value <= self.parent.max and value >= self.parent.min:
            self.parent.SetValue(value)
        self.parent.ReDraw()

class SlColor(Slider):
    def on_touch_up(self,touch):
        value = int(self.value)
        self.parent.SetValue(value)
        self.parent.ReDraw()

class BoxColor(BoxLayout):
    def __init__(self,**kwargs):
        super(BoxColor,self).__init__(**kwargs)
        self.SetUp('',0,100)

    def SetUp(self,text,min,max):
        self.tName = text
        self.min = min
        self.max = max
        self.value = min

        self.clear_widgets()
        self.orientation='horizontal'

        self.l1 = Label(text=self.tName,size_hint_x=1)
        self.s1 = SlColor(min=self.min,max=self.max,value=self.value,size_hint_x=7)
        self.t1 = TxiColor(text=str(self.value),size_hint_x=2,multiline=False)

        self.add_widget(self.l1)
        self.add_widget(self.s1)
        self.add_widget(self.t1)

    def SetValue(self,value):
        self.value = value

    def ReDraw(self):
        self.s1.value = self.value
        self.t1.text = str(self.value)

### BMP File cotrol
class BMPFileControl():
    def __init__(self,size_w,size_h):
        # 24bit Color Only
        self.header = bytearray(range(54))
        self.padding = (4-(size_w*3)%4)%4
        self.w = size_w
        self.h = size_h

        imagesize = int(size_w*3 + self.padding)*size_h
        filesize = int(54 + imagesize)

        # FILE HEADER
        # 'BM'
        self.header[0] = 'B'
        self.header[1] = 'M'
        # FileSize
        self.header[2] = filesize & 0xff
        self.header[3] = (filesize >> 8) & 0xff
        self.header[4] = (filesize >> 16) & 0xff
        self.header[5] = (filesize >> 24) & 0xff
        # Reserved1
        self.header[6] = 0
        self.header[7] = 0
        # Reserved2
        self.header[8] = 0
        self.header[9] = 0
        # Offset
        self.header[10] = 54
        self.header[11] = 0
        self.header[12] = 0
        self.header[13] = 0

        # INFO HEADER
        # DIB header size
        self.header[14] = 40
        self.header[15] = 0
        self.header[16] = 0
        self.header[17] = 0
        # image w
        self.header[18] = size_w & 0xff
        self.header[19] = (size_w >> 8) & 0xff
        self.header[20] = (size_w >> 16) & 0xff
        self.header[21] = (size_w >> 24) & 0xff
        # image h
        self.header[22] = size_h & 0xff
        self.header[23] = (size_h >> 8) & 0xff
        self.header[24] = (size_h >> 16) & 0xff
        self.header[25] = (size_h >> 24) & 0xff
        # planes
        self.header[26] = 0
        self.header[27] = 0
        # Bits per Pixel
        self.header[28] = 24 # 24bit Color Only
        self.header[29] = 0
        # Compression
        self.header[30] = 0
        self.header[31] = 0
        self.header[32] = 0
        self.header[33] = 0
        # Imagesize
        self.header[34] = imagesize & 0xff
        self.header[35] = (imagesize >> 8) & 0xff
        self.header[36] = (imagesize >> 16) & 0xff
        self.header[37] = (imagesize >> 24) & 0xff
        # Resolution W
        self.header[38] = 0
        self.header[39] = 0
        self.header[40] = 0
        self.header[41] = 0
        # Resolution H
        self.header[42] = 0
        self.header[43] = 0
        self.header[44] = 0
        self.header[45] = 0
        # Palette
        self.header[46] = 0
        self.header[47] = 0
        self.header[48] = 0
        self.header[49] = 0
        # Essential Color
        self.header[50] = 0
        self.header[51] = 0
        self.header[52] = 0
        self.header[53] = 0

    def MakeBMPFile(self,filepath,r,g,b):
        with open(filepath,'wb') as f:
            data = self.header
            pixel = [chr(b),chr(g),chr(r)]
            linedata = pixel*self.w
            for p in range(self.padding):
                linedata.append(0x00)
            mapdata = linedata*self.h
            data.extend(mapdata)
            f.write(data)

class Display(BoxLayout):
    orientation='vertical'
    def __init__(self,**kwargs):
        super(Display,self).__init__(**kwargs)

        self.t1 = TextInput(text="",size_hint_y=1,multiline=False,readonly=True)
        self.add_widget(self.t1)

        self.boxSave = BoxSaveFileName(size_hint_y=1)
        self.add_widget(self.boxSave)

        self.boxFile = BoxSelectFile(size_hint_y=15)
        self.add_widget(self.boxFile)

        self.boxR = BoxColor(size_hint_y=1)
        self.boxR.SetUp('R',0,255)
        self.add_widget(self.boxR)

        self.boxG = BoxColor(size_hint_y=1)
        self.boxG.SetUp('G',0,255)
        self.add_widget(self.boxG)

        self.boxB = BoxColor(size_hint_y=1)
        self.boxB.SetUp('B',0,255)
        self.add_widget(self.boxB)

    def MakeFile(self):
        txtFilepath=self.t1.text+'/'+self.boxSave.t1.text+self.boxSave.l1.text
        print(txtFilepath)

        bmp = BMPFileControl(15,15)
        bmp.MakeBMPFile(txtFilepath,self.boxR.value,self.boxG.value,self.boxB.value)

class MainApp(App):
    def build(self):
        layout = Display()
        return layout

if __name__=='__main__':
    MainApp().run()


自覚しているので最初に書いてしまうと、ツッコミ所は BMPFileControl クラスです。冗長ってレベルじゃねーぞ。
VC++で BMP 取り扱いクラスを書いていた時はヘッダー構造体を作って、コレを継承するクラスを書いた後、this ポインタにヘッダ構造体ポインタをキャストしてファイル出力に直接流していた記憶がうっすらあるのですが…
慣れていないせいなのでしょうけど python でバイナリファイルを扱おうとすると非常に面倒ですね。
時代の流れで、データサイズを明示したり、ポインタ渡しなどメモリアドレスを直接触れさせる処理を隠蔽していった流れが悪い方に出てしまったように感じるのは私が古い人間だからでしょうか?
4バイト数値をいちいちビットシフトしているのはビッグエンディアン系のCPUも考えると悪くは無いと考えているのですがどうでしょう?

10数年ぶりに Bitmap を取り扱うアプリを作って、大分いろいろ忘れてますね…パディングってなんだっけ?とか、1画素の色の並びをRGBにして失敗したりとか(正解はBGRの順。大昔のハードウェアの都合だったハズ)。

あと、いい加減 Python 3 系にしろと言われそうですが、Linux mint (というか ubuntu)と Blender と kivy の FileChooser が対応してくれない事には身動きとれません。どうにかできる地力も無いですし。


  • さて、コレの何処が地獄なのよ?

昔々、20代後半~30くらいでゲーム会社でプログラマーをやっていた頃、髪の毛がザラザラ抜けた仕事が二つありまして、一つは社内ゲーム開発用エフェクトツールを作っていた時、もう一つはテクスチャファイルコンバータを作っていた時なのですよ。
31で引退して以来髪の毛が減っていない事から(注:増えてもいない)、アレは毛根に厳しい仕事だったなと今でも思うのですが、モデリングがある程度片付いてきたのでテクスチャ用の BMP→S3TC(DXTC)コンバータに再挑戦しようかなと思いまして、その足掛かりとして作りました。
…まあ、正直そんなに乗り気では無かったのですが、購入するとすごく高いんですよ、あのコンバータ。みんな貧乏が悪いんや。


  • 最後に

今回 python kivy について検索していたら Google 先生の日本の検索上位にこのページが出た事があったのですよ。物を書いている以上、読まれているのは構わないのですが…
閲覧数10回以下
… python + kivy で物作ってる日本人は絶滅種なのでは?と不安になりました。

2020年2月12日水曜日

Python+Kivy 備忘録 スライダー、テキストボックス連動編

半年ぶりですね。
思い出して、作って、忘れて、又思い出すというとんでもなく生産性の悪い事をしております。
…だから備忘録が必要な訳で、私は間違っていない…ハズ。
今回はそこそこ汎用性のありそうな、ラベル、スライダー、テキストボックスのセットを作りまして、スライダーとテキストボックスの連動を行ってみたのですが…
検索すると判ると思いますが、kv ファイルを用いたサンプルはネット上にあったのですが、例によって python オンリーが無くてですね、結構試行錯誤してようやく動いたのですが…

コード

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.slider import Slider
from kivy.uix.floatlayout import FloatLayout

### Input Color Value
class TxiColor(TextInput):
    def on_text_validate(self):
        value = int(self.text)
        if value <= self.parent.max and value >= self.parent.min:
            self.parent.SetValue(value)
        self.parent.ReDraw()

class SlColor(Slider):
    def on_touch_up(self,touch):
        value = int(self.value)
        self.parent.SetValue(value)
        self.parent.ReDraw()

class BoxColor(BoxLayout):
    def __init__(self,**kwargs):
        super(BoxColor,self).__init__(**kwargs)
        self.SetUp('',0,100)

    def SetUp(self,text,min,max):
        self.tName = text
        self.min = min
        self.max = max
        self.value = min

        self.clear_widgets()
        self.orientation='horizontal'

        self.l1 = Label(text=self.tName,size_hint_x=1)
        self.s1 = SlColor(min=self.min,max=self.max,value=self.value,size_hint_x=7)
        self.t1 = TxiColor(text=str(self.value),size_hint_x=2,multiline=False)

        self.add_widget(self.l1)
        self.add_widget(self.s1)
        self.add_widget(self.t1)

    def SetValue(self,value):
        self.value = value

    def ReDraw(self):
        self.s1.value = self.value
        self.t1.text = str(self.value)

class Display(BoxLayout):
    orientation='vertical'
    def __init__(self,**kwargs):
        super(Display,self).__init__(**kwargs)

        self.boxR = BoxColor(size_hint_y=1)
        self.boxR.SetUp('R',0,255)
        self.add_widget(self.boxR)

        self.boxG = BoxColor(size_hint_y=1)
        self.boxG.SetUp('G',0,255)
        self.add_widget(self.boxG)

        self.boxB = BoxColor(size_hint_y=1)
        self.boxB.SetUp('B',0,255)
        self.add_widget(self.boxB)

class MainApp(App):
    def build(self):
        layout = Display()
        return layout

if __name__=='__main__':
    MainApp().run()


実行結果※ python2.7 Linux Mint 19.2 上のものです

キモが BoxColor クラスなのは見れば判ると思うのですが…不可解な部分が有るんですよね。
ソレが変色させた部分。
実は普通に BoxColor に再描画処理を書いて子クラスから呼ばせる方法で作っていたのですが、どうしてもエラーが出る為、苦し紛れに書いたら動いてしまったのですよ。
ReDraw 関数の中身は見ての通り、各子クラスのメンバー変数に値を入れているだけです。…私の頭が古いせいか、子クラスのメンバー変数に直接値を代入するだけでも保守性が心配になるのですが…
どうして再描画されたのか?そもそも再描画のタイミングとは?動きはしたものの疑問がいっぱいです。

2020年2月5日水曜日

拳を作る

半年ぶり3度目。ついでに書いてしまうと初回は17年の11月です…製作が遅すぎる。
人間の指は開くと外側に、閉じると内側に集まるものでして、コレを表現するために指に捻じれ(ロール値)を入れていました。
※黄色の線のように指にロール値を入れて、赤線のように開閉するように調整している
ただ、左右反転を行うにあたってロール値が入っているといろいろと面倒なのでロール値を全て0にリセット、ロール値を前提としてた指の動きがおかしくなった所が前回までのお話。

先ず最初の作業として、各指の第一関節を直接角度を入力する方法から、ターゲット追従型に変えました。
※指の先端の先に見えるのがターゲット
で、次に人差し指、薬指、小指に関しては掌の中にある第一関節の根元の骨「中手骨」を追加。さらに中手骨のわずかな開閉を行う「骨間筋」を作り、中手骨を動かす事にしました。
骨間筋の収縮は各指先の先端が開閉方向に動いたときにストレッチするボーンを作りココから係数をとっています。
…とは言え本当にわずかにしか中手骨は開閉しませんが。

中手骨が八の字から平行になっていくのが判るでしょうか?

親指の付け根に肉が足りないような気もしますが、ほぼ指の隙間が無く拳が握れています。
ひとまずこれにて拳は一旦〆として次に行こうと思います。

2020年2月1日土曜日

諸々雑記


  • 昨年末に載せていた宝くじですが、結論から言うと大ハズレでした。

電源は入るのですがBIOS画面が出ない。
考えられる可能性はCPUが壊れている、BIOSが飛んでいる、マザーボード内蔵グラフィックが死んでいる等で、マザーボードのアンプ回路のみ無事である訳ですが…。
…外付けビデオボードを刺しても起動しなかった為、グラフィックの線は無くなりまして、はてコレを使うかと言うと…多分修理しようとすると新品より高くなりますね。
正月を挟んだので初期不良期間すら過ぎてしまって完全にゴミです。

ちなみに、ベストな状態は?というと当然完動品であるというのは最低条件ですが…
コレ、セット商品の抜き取り品だと踏んでいたのですよ。
で、1151はWindows10専用世代のボードですから、10のインストーラを使ってアクティベーションが通っていればそのまま使って、
CPU交換→ゲーミング用にしようかなと。駄目なら内蔵グラフィックのみで linux 機に。
Win10のアップデートはとっても主記憶装置に負荷をかけるので、HDDは絶対ダメなのは当然ですが、M.2SSDが載るならM.2にOSを入れるべきだと思います。ハイ。
ギルティギアの新作までにはゲーミングPCを用意したいのですけどねえ。
当ブログPVの7割はジャンク系記事だったりするのですが…今年はジャンクはあんまり手を出せない、というか節約しないといけないのです。


  • イベント終って

結局、イベントはその後あ号の攻略中に秋霜と平戸を取得して、残り時間をE3でコメットの熟練度を上げて終了。
…豪運ではあるのだけど、E2で石垣が取れるのをすっかり忘れていました。というわけで、石垣以外の全ての艦が揃いました。

なんだか色々と新しい任務が増えましたが…要するにウィークリーやマンスリーと並行して解けって事でして、フラグ管理がひたすら面倒くさいです。
数百もある任務の計算を母港に帰る度にやらせる訳にもいかないので、6個以下しか同時選択できないのでしょうけど…うーん。
そして、地味に面倒なのが六水の任務。どうもクウォータリーらしいのですけどね…
睦月型を遠征専用としていまして、同時ケッコンしてレベルを横並びにしていた関係で睦月、如月が出せません。
という事で、弥生と卯月を出しているのですが…ケッコン前で耐久24、ケッコン後で28のド直球の4n艦。
悲惨なのが6-4と6-5。夕張+弥生、卯月で攻略しなくてはならないのですが、火力にならない上に食らったら即大破の罰ゲームみたいな任務です。…いや、睦月、如月改二で揚陸車両載せれば良い訳で、セルフ縛りプレーしているから悪いのですが。


  • 以前 PSO2 は Ep3 で引退と書いていたのですが、 Ep2 でした。

アニメ見て気づきました。クーナの話の次辺りで引退したハズです。
アニメを見る限りだと案外悪くないものなんですけどねえ…コレがこのあと、学園コメディー、なんちゃってアメリカ、どういうわけか対戦艦大和、中世ファンタジーに遷移したっていうのだから字面だけで迷走感が半端ないです。


  • 半月ぶりにアッシュアームズのWikiを見たら…

新キャラ3機追加、新スキン追加、新システム追加、AI修正?(被害が出やすくなったという反応があるんですが)だそうで、更新速度がすごいですね。このペースで行くと半年後にはキャラクター数が100を突破するのでは?
以前から大量にいるスキルが説明と違う連中は修正されつつある(説明文を修正)そうですが、すでにCVが居ないキャラクターも出始めていて、キャラ追加の節操のなさが足を引っ張りそう。
…画集を出版するまで頑張って欲しいのですけどね。
新キャラのパーシングを見てぜかまし枠かな?と思ったら中の人まで同じで笑いました。