qshinoの日記

Powershell関係と徒然なこと

opencv videowriter

opencvで動画ファイル作成

opencv での動画作成

import numpy as np
import cv2 

cap = cv2.VideoCapture(0) 

# Define the codec and create VideoWriter object 

fourcc = cv2.VideoWriter_fourcc(*'XVID')

out = cv2.VideoWriter('out.avi',fourcc, 10.0, (320,240)) 

while(cap.isOpened()): 

  ret, frame = cap.read() 
  if ret==True: 
      frame = cv2.flip(frame,0) 

      # write the flipped frame   
      out.write(frame) 

      cv2.imshow('frame',frame)

      if cv2.waitKey(1) & 0xFF == ord('q'):
          break 
  else: 
      break 

# Release everything if job is finished cap.release() 
out.release() 
cv2.destroyAllWindows()

ref

http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_gui/py_video_display/py_video_display.html

python 定時作業

定時作業

signalに呼んでもらう。

import time,  signal

def foo( signum, frame ):
    print(time.time())

if ( '__main__' == __name__):

    interval_1st = 0.1 # seconds
    interval_after1st = 0.1 # seconds

    signal.signal(signal.SIGALRM, foo)
    signal.setitimer(signal.ITIMER_REAL, interval_1st, interval_after1st) 

  it = 10

    while ( it > 0 ):
        signal.pause() # until signal
        it-=1


    # Stop timer
    signal.setitimer(signal.ITIMER_REAL, 0)
    signal.signal( signal.SIGALRM, sgnal.SIG_DFL )

OS

os機能を使うため、フル機能はunix系OSのみ対応。 windowsは一部対応。

ref

https://docs.python.org/ja/3/library/signal.html

https://qiita.com/miminashi/items/50a4f0906ab8f18b105d

名刺交換

名刺交換

スマホ同士で名刺交換するアプリ。

bluetoothwifiで交換すると設定が難しいため、スマホ・カメラとディスプレイで名刺交換。

スマホ同士が向き合わないと交換できない事が一つのセキュリティになる。

双方の交換完了後にデータが有効になる。

画像では正しく伝わらない可能性がある為、エンコードした上で送付する。

えっ?QRコードで良いって?

それだと写真をとると誰でも分かってしまう。セキュリティを考慮し、リアルタイムでないと交換できない仕組みとする。

交換後にデータをコピーすれば良いって?

データに属性情報を付けてトラッキングができる様にする?

コピーされても、出元が分かるとなれば安易なコピーをしない可能性がある。

スマホ

スマホのアプリは、面倒と言う話もあるため、先ずはPC環境で確認。

エンコード

フリーのOCRを探してから考える。

あるいはイメージをそのまま送る?

DL framework

Deep Learning Framework

DLのフレームワーク綺羅星の如くあり、何を使うか迷う。

一つの調査結果をここに。

2018段階で利用者が多い順に

  1. Tensorflow
  2. Caffe
  3. Keras
  4. PyTorch
  5. Theano
  6. torch
  7. mxnet
  8. ontk, chainer

Kerasはtensorflow, CNTK, Theano, MXNetの上に構築されており、同列に比較できない。

なお、kerasはgoogle, PyTorchはFacebookがサポートしている。

IntelもOpenVinoをリリースしているが、今後上位に組み込めるかは、今後次第。

KDnuggets Survey

f:id:qshino:20190616193805j:plain

ref

https://deepsense.ai/keras-or-pytorch/

LVMの修復

LVMの復旧

LVMを復旧する場合、下記の流れで復旧を進める。

  1. pv復旧
  2. vg復旧
  3. fs復旧

pv復旧は、lvmのpvを復旧する。vg復旧はボリュームグループ復旧。最後にfs ファイルシステム復旧。

ここでlvmのlvが出てきていないが、vgが復旧されれば、vg管理下のlvも復旧する為、lv個別の復旧作業は不要である。

関連する主なコマンドは下記の通り。

  1. cat /proc/partitions
  2. pvscan
  3. pvcreate -uuid xxx /dev/yyy
  4. vgcfgrestore VG
  5. vgscan
  6. vgchange -ay VG
  7. e2fsck -y /dev/VG/LV

lvm構成ディスクが一つ故障

複数ディスクで構成するlvmで、一つのディスクが故障した場合。

pv復旧

  1. cat /proc/partitionsにより、パーティション確認、pvscan, pvdisplay等により、故障ディスクのuuidを確認。
  2. 新ディスク插入
  3. pvcreate -uuid 故障ディスクuuid /dev/新ディスク

pvcreateの際の注意点。

下記メッセージが表示されたら、

Read-only locking type set. Write locks are prohibited. Can't get lock for ...

/etc/lvm/lvm.conf の下記記述の値を1に変更。

locking_type = 4

また、-restoreなんちゃらとメッセージがでたら、

/etc/lvm/archive/... ファイルを指定する。

vg 復旧

  1. vgcfgresrote VG
  2. vgscan
  3. vgchange -ay VG

fs 復旧

  1. e2fsck -y /dev/VG/LV
  2. mount

データ復旧

  1. データを別のディスクにコピー等。

障害の程度によっては e2fsckで復旧できない可能性がある。lvの先頭ディスクが故障した場合、fsのinodeが失われるため、復旧は困難である。

その様な場合は、立ち上がるosとvgnameが衝突しない様にvgnameを変更し、別osで起動。その後os上のfsckにて復旧。rescue mode等のfsckは、機能が低い場合があり、通常os上のツールで試すことも有効。

vgcfgrestoreに失敗すると、以降の処置には進めない。uuid一致pvを準備したにも関わらず、vgcfgrestoreに失敗するのは致命的である。lvmのauto backup機能がオフにされていたり、meta dataのセクタに障害があった場合など。

補足

lvmでは、meta data を/etc/lvm/backup, /etc/lvm/archiveに保管している。また、全ディスクにmeta dataを保持し、auto backup機能により、meta.dataが最新に保たれる。よって、一つのディスクが残っていれば、meta dataは生きている。meta dataがあれば、pvを準備する事でvgcfgrestoreによる復旧が可能である。

補足その2

元々の構成

HWRaidカードが刺さっており、一つの物理玉を一つの論理玉=vdとしてOSに見せている。LVMは2つのvdをcentos vg、残り一つのvdからopt vgを構成する。まとめると次の構成。

centos vg は、vd1,2にまたがる。centos vgからroot lvが切り出されている。

opt vg は、単独ディスクのvg。

vd1-3はそれぞれ単玉のvirtual diskで、vdはそれぞれ一つの物理玉で構成。

最後に

ディスクが来るまで少しの時間だけバックアップを怠ったツケが、こんな所で回ってくるなんて・・・。

osが上がらずgrubで止まった時

下記参照。

http://qshino.hatenablog.com/entry/2019/04/25/195622

参考

https://www.novell.com/coolsolutions/appnote/19386.html

ximagesrc in gstreamer

x11の画面を切り取るgstreamer plugin

ximagesrcはxからイメージを切り出すプラグイン。これを使って、モールスのデモを作成する。

x上でモールス信号を表示し、映像からモールスを復号する。

簡単だと思ったら、煩雑な処理が多く、作るかどうかは別途検討する。ここでは実現方法の検討まで。

全体の流れは

  1. テキストファイルをモールス変換
  2. モールスをウインドウに表示
  3. 表示されたイメージをモールス化
  4. モールスを復号し、テキスト表示

1,2,4は作るだけ。今回のメインは3.イメージのモールス化。

また、モールスは時間で長短の符号が変わるが、pcは時間に対して厳密な精度を出しにくいため、送受信共に時間的なバラツキの取り扱いが煩雑になる。

時間の同期処理を適宜盛り込むか、受信側で何らかの意味的適合処理を盛り込むか。意味的適合処理を入れるためには、文脈認識やその為の辞書の様な仕組みが必要になり、実装範囲が拡大する。

今回は意味的適合処理は考慮しない。

イメージのモールス化

イメージの取得はgstreamerのximagesrcを使う。切り取ったイメージをopencvで処理し、短点、長点、符号間、文字間、語間を認識し、モールス化する。

image切り取り

受信の入口はイメージ。先ずはイメージの切り取り方から。

image切り取りは、ximagesrcのstartx, starty, endx, endyを指定する。

# init

x=233
y=24 
w=$((x + 800 -1)) 
h=$((y + 480 -1))

# launch

 gst-launch-1.0 -e \
 ximagesrc display-name=:1 \
show-pointer=false startx=${x}\
 starty=${y} endx=${w} endy=${h} \
 ! videoconvert ! videoscale \
! video/x-raw, framerate=25/1, width=1920, height=1080, \
pixel-aspect-ratio=1/1, \
method=lanczos \
 ! fbdevsink sync=false 

切り取り範囲

切り取りには範囲を指定する。この範囲を取得する方法。

xlsclients : xクライントリスト

xprop : プロパティ

xwininfo : window info

lsclients -l 出力例

# xlsclients -l 
Window 0x180000d: 
  Command: /usr/X11R6/bin/kterm       
  Instance/Class: kterm/KTerm 
Window 0x1200001: 
  Name: MozillaFirefox-bin 
  Command: /usr/lib/mozilla-firebird/MozillaFirefox-bin 
  Instance/Class: MozillaFirefox-bin/MozillaFirefox-bin 
Window 0x2d0000d: 
  Name: xine Icon 
  Name: kterm 
  Command: /usr/bin/xine 
  Instance/Class: xine/Xine 

xlsclient -l出力から、idとnameを取得し、対象の名前のwindowを選択し、xwininfo -id xx によりsizeを取得する。

取得したsizeをximagesrcに指定する。

ref

https://www.hackinglinuxexposed.com/articles/20040608.html

opencv

ximagesrc出力をopencvで受け取り、イメージから、モールスを認識する。

opencvでのイメージの受け取り方。appsinkで受ける。

import cv2 

cap = cv2.VideoCapture("videotestsrc ! videoconvert ! appsink") 

while True:
  ret, img = cap.read() 
  if not ret: 
    break 

  cv2.imshow("",img)

  key = cv2.waitKey(1)
  if key==27: 
    #[esc] key
    break 

ref

https://qiita.com/stnk20/items/242e400853579d511ea3

モールス認識

さて、ココまででイメージをopecvで受け取れる。ここからモールスを認識する。

全体の流れは、

  1. オン/オフ判別
  2. 符号変換、短点、長点、符号間、文字間、語間判別
  3. 文字変換
  4. 語変換
  5. 文変換
  6. 終了判定

オンオフ判別は、イメージ全体の和が閾値以上かどうかで判別。

短点、長点判別は、オン時間で判別。

符号間他の休符は、オフ時間で判別。

時間関係は後で動的処理に変更する事を前提に文内で動的に変わって良い変数とする。

短点の長さをsとすると、符号間はs, 長点は3s, 文字間は3s, 語間は7s, 終了は、終了コードまたはx s 最低x=20s程度とする。

符号変換は、再変換に対応する為、オン・オフ判別データを暫く(x 文程度)保持する。

保持するオン・オフデータは、一定の長さのリングバッファとする。要素は下記のオン・オフとその長さとする。

(オン・オフ、長さ、ch)

オン・オフ判別はタイムアウトを持ち、タイムアウトの場合、オフデータ、あるいはオンデータが続く場合がある。

ch は今後の拡張用で、複数チャネル対応時に使用する。Imageを領域分割、あるいは色で分割した場合等。今は0を入れる。

時刻

モールスの長短点判別には時間がキーとなる。pythonで作るとして、どの時計を使うかを検討する。

  • time.time()
  • time.process_time()
  • time.perf_counter()
  • time.clock()
  • time.monotonic()

とりあえず、5種類ある。環境毎に調べて適切な物を利用する。

ref

https://qiita.com/takeopy/items/170d0e1ddbf02ef9fbb9

オン・オフ判別再び

オン・オフ判別を動体検知で。

import numpy as np

 import cv2
 cap = cv2.VideoCapture('vtest.avi')

 #動体検出器の生成

 fgbg = cv2.createBackgroundSubtractorMOG2() 

while(1): 
    #動画を1フレーム読み込む
    ret, frame = cap.read()

    #「Escが押される」または「動画フレームがない場合」終了 
    k = cv2.waitKey(30) & 0xff
    if k == 27 or not ret: break 

    #動体、背景、影に分ける

    fgmask = fgbg.apply(frame)   

    cv2.imshow('frame',fgmask) 

cap.release() 
cv2.destroyAllWindows()

ref

https://www.tech-tech.xyz/background-subtraction2.html

サイズとintegral

最初にサイズを調べる。

import cv2 
import sys 

if __name__ == "__main__": 

    img = cv2.imread("lena.jpg",    
    cv2.IMREAD_UNCHANGED)

    # 画像ファイルの読み込みに失敗したらエラー終了
    if img is None:
        print("Failed to load image file.") 
        sys.exit(1) 

    # カラーとグレースケールで場合分け
    if len(img.shape) == 3: 
        height, width, channels = img.shape[:3] 
    else: 
        height, width = img.shape[:2]    
        channels = 1 

    # 取得結果(幅,高さ,チャンネル数,depth)を表示 

    print("width: " + str(width))     
    print("height: " + str(height)) 
    print("channels: " + str(channels)) 
    print("dtype: " + str(img.dtype))

次に、integralで総和を求める。integralは元の配列より、w,h共に1大きな配列を返す。つまり、sum(x,y)は、srcの(x0..x-1,y0..y-1)の和を返す。

よって、画素の総和は sum(w,h)の値になる。sum(w-1,h-1)では無いことに注意。 また、チャネル単位の和のため、カラーの場合は、チャネルの総和がイメージの総和となる。

性能が課題になる場合は、見直す。

#-*- coding:utf-8 -*-
import cv2 
import numpy as np 

def main(): 
    # 入力画像を読み込み
    img = cv2.imread("input.jpg") 

    # グレースケール変換
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) 

    # 画素値を表示
    print("gray=\n", gray)

    # 積分画像の作成 
    integral = cv2.integral(gray) 

    # 画素値を表示 
    print("integral=\n", integral) 


if __name__ == "__main__": 
    main()

基本的には、integralの結果を元にオン・オフ判断する。

実際には揺れがある為、閾値等で調整する。

まとめ

オン・オフ判別は、動体検知も良いが、インテグラルでも可能かもしれない。

  1. インテグラ
  2. 閾値確認
  3. 変化検知
  4. データ出力

しかし、閾値が背景により変動するため、動体検知を使い閾値を規格化し、環境影響を排除する方法もある。

送受信のどちらか、あるいは双方が移動している場合、背景も動き、更なる検討の余地がある。

ref

サイズ

https://github.com/atinfinity/lab/wiki/%5BOpenCV-Python%5D%E7%94%BB%E5%83%8F%E3%81%AE%E5%B9%85%E3%80%81%E9%AB%98%E3%81%95%E3%80%81%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%AB%E6%95%B0%E3%80%81depth%E5%8F%96%E5%BE%97

integral

https://algorithm.joho.info/programming/python/opencv-integral-image-py/

xterm in tkinter

from Tkinter import *
 import os

root = Tk() 
termf = Frame(root, height=400, width=500) 
termf.pack(fill=BOTH, expand=YES)

wid = termf.winfo_id() 
os.system('xterm -into %d -geometry 40x20 -sb &' % wid)

 root.mainloop()

ref

https://stackoverflow.com/questions/7253448/how-to-embed-a-terminal-in-a-tkinter-application

opencv draw text

http://opencv.jp/cookbook/opencv_drawing.html

ref

https://mattintosh.hatenablog.com/entry/20161003/1475421469

xdmx/xephyr

xdmx / xephyr の試行

x11色々用に書いたら、長くなったので、別記事で。

xdmx/xephyr

xdmxはX Distributed Multihead X serverの略で、複数のXサーバを一つの大きなX画面に表示する。

xephyrはいわゆるxproxy、Xserverの表示を別のx serverのウインドウとして表示する。

今回はxdmx試行に当たり、個別にPC上のXサーバでの確認前にxephyrでxdmxを試し、使い方に慣れた後に、個別pcのxサーバに切り替えるステップを踏む。

xephyr経由でxdmxをステップバイステップ試行

全体の流れ

  1. 単一サーバ上でxdmx/xephyr試行
  2. 2サーバ上でxephyr/xdmx
  3. 片側を素のXに置き換え。
  4. 両側を素のXに置き換え。

firewallとxfs/x font serviveに注意する。xdmxでは全子サーバのフォントが一致する必要がある。また、キーボードやvtにも注意。

構成

  • s1 : 親。本サーバ接続のキーボード、マウスを利用する。
  • s2 : 子。セカンドモニタ。
  • d1, d2 : それぞれs1,s2上のX。s1:0, s2:0とも表記される。
  • e1,e2 : xephyr。
  • m1 : dmx multihead x server

Step 1. 単一サーバで試行

親サーバ上で実行する。

export DISPLAY=d1 # :0
xephyr  e1 -screen 600x400 # :1
xephyr  e2 - screen 600x400 # :2

xdmx m1 -display e1 -display e2 -input e1 +xinerama &

export DISPLAY=m1 
xterm &
twm &

Step 2. 2サーバのxephyr

xephyrを異なるサーバに表示し、xephyrをマルチヘッドする。

一つのxephyrの表示画面が異なるだけで、その他は同じ。

違いはe2起動ラインのみ。

export DISPLAY=d1 # :0
xephyr  e1 -screen 600x400 # :1
DISPLAY=d2 xephyr  e2 -screen 600x400  # ここを変更

xdmx m1 -display e1 -display e2 -input e1 +xinerama &

DISPLAY=m1 xterm &

起動したxterm上でtwm &等。

e1のキーボードを使うため、-inputも変更不要。

Step 3. 親を素のサーバに

親のxephyr e1を起動せず、親画面d1をxdmxに指定する。

export DISPLAY=d1 # :0
# xephyr  e1 -screen 600x400 # :1 コメントアウト。
DISPLAY=d2 xephyr  e2 -screen 600x400  # ここを変更

xdmx m1 -display d1 -display e2 -input d1 +xinerama &  # ディスプレイとインプットを親d1に変更。

DISPLAY=m1 xterm &

起動したxterm上でtwm &等。

親Xの機能によっては動作しない場合がある。その場合は、xephyr経由の場合とログを比較しつつ、確認する。

解決が難しい場合は、xephyrのままでの運用も検討する。

Step 4. 親子共に素のX

export DISPLAY=d1 # :0

# xephyr削除

xdmx m1 -display d1 -display d2 -input d1 +xinerama &  # ディスプレイを子d2に変更。

DISPLAY=m1 xterm &

起動したxterm上でtwm &等。

注意事項

子を利用する場合、下記のxfs/font serviceのポートを開く。xdmcpを使用する際は、xdmcp portも開く。

ポート177 udp xdmcp ポート7100 tcp xfs

課題

xephyrで試行した限り、-input を指定しない側のウインドウで入力ができない。

複数の-inputを指定すると、キー入力に対してランダムに思える文字が表示される。表示は複数モニタにスパンするが、入力がこれでは難しい。

Window Managerのxinerama対応が関係している?

twmを使ったのが悪い?

セカンド側の入力を何とかする方法があれば、誰か教えて欲しい。

もしかして、個別のノード単位のキー入力を期待している?

起動オプション

#!/bin/bash

HOST=banana 

# wait for 2nd screen 

LOOP="-1" 

while [ $LOOP -ne 0 ] do 
    sleep 5  </dev/tcp/$HOST/6000  

  echo "Waiting for $HOST: $?"       
  LOOP="$?" 
done 

sudo chown -R pi:pi /home/pi 

xauth -b quit 

#xhost + 

startx -- /usr/bin/Xdmx :1 -display :0 -display $HOST:0 -norender -noglxproxy -ignorebadfontpaths +xinerama -param XkbModel pc105 -param XkbLayout de

rasphberrypi

https://www.raspberrypi.org/forums/viewtopic.php?t=228426

その他

ショートカットキー

Ctrl-Alt-q will terminate the Xdmxserver in all modes.

Ctrl-Alt-g will toggle a server grab in console mode (a special cursor, currently a spider, is used to indicate an active server grab).

Ctrl-Alt-f will toggle fine-grain motion in console mode (a special cursor, currently a cross hair, is used to indicate this mode). If this mode is combined with a server grab, then the cursor will have 4 lines instead of only 2.

Ctrl-Alt-F1 through Ctrl-Alt-F12will switch to another VC in local (raw) mode.