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
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
名刺交換
名刺交換
スマホ同士で名刺交換するアプリ。
bluetoothやwifiで交換すると設定が難しいため、スマホ・カメラとディスプレイで名刺交換。
スマホ同士が向き合わないと交換できない事が一つのセキュリティになる。
双方の交換完了後にデータが有効になる。
画像では正しく伝わらない可能性がある為、エンコードした上で送付する。
えっ?QRコードで良いって?
それだと写真をとると誰でも分かってしまう。セキュリティを考慮し、リアルタイムでないと交換できない仕組みとする。
交換後にデータをコピーすれば良いって?
データに属性情報を付けてトラッキングができる様にする?
コピーされても、出元が分かるとなれば安易なコピーをしない可能性がある。
スマホ
スマホのアプリは、面倒と言う話もあるため、先ずはPC環境で確認。
エンコード
フリーのOCRを探してから考える。
あるいはイメージをそのまま送る?
DL framework
Deep Learning Framework
一つの調査結果をここに。
2018段階で利用者が多い順に
- Tensorflow
- Caffe
- Keras
- PyTorch
- Theano
- torch
- mxnet
- ontk, chainer
Kerasはtensorflow, CNTK, Theano, MXNetの上に構築されており、同列に比較できない。
なお、kerasはgoogle, PyTorchはFacebookがサポートしている。
IntelもOpenVinoをリリースしているが、今後上位に組み込めるかは、今後次第。
KDnuggets Survey
ref
LVMの修復
LVMの復旧
LVMを復旧する場合、下記の流れで復旧を進める。
- pv復旧
- vg復旧
- fs復旧
pv復旧は、lvmのpvを復旧する。vg復旧はボリュームグループ復旧。最後にfs ファイルシステム復旧。
ここでlvmのlvが出てきていないが、vgが復旧されれば、vg管理下のlvも復旧する為、lv個別の復旧作業は不要である。
関連する主なコマンドは下記の通り。
- cat /proc/partitions
- pvscan
- pvcreate -uuid xxx /dev/yyy
- vgcfgrestore VG
- vgscan
- vgchange -ay VG
- e2fsck -y /dev/VG/LV
lvm構成ディスクが一つ故障
複数ディスクで構成するlvmで、一つのディスクが故障した場合。
pv復旧
- cat /proc/partitionsにより、パーティション確認、pvscan, pvdisplay等により、故障ディスクのuuidを確認。
- 新ディスク插入
- 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 復旧
- vgcfgresrote VG
- vgscan
- vgchange -ay VG
fs 復旧
- e2fsck -y /dev/VG/LV
- mount
データ復旧
- データを別のディスクにコピー等。
障害の程度によっては 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
参考
ximagesrc in gstreamer
x11の画面を切り取るgstreamer plugin
ximagesrcはxからイメージを切り出すプラグイン。これを使って、モールスのデモを作成する。
x上でモールス信号を表示し、映像からモールスを復号する。
簡単だと思ったら、煩雑な処理が多く、作るかどうかは別途検討する。ここでは実現方法の検討まで。
全体の流れは
- テキストファイルをモールス変換
- モールスをウインドウに表示
- 表示されたイメージをモールス化
- モールスを復号し、テキスト表示
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で受け取れる。ここからモールスを認識する。
全体の流れは、
- オン/オフ判別
- 符号変換、短点、長点、符号間、文字間、語間判別
- 文字変換
- 語変換
- 文変換
- 終了判定
オンオフ判別は、イメージ全体の和が閾値以上かどうかで判別。
短点、長点判別は、オン時間で判別。
符号間他の休符は、オフ時間で判別。
時間関係は後で動的処理に変更する事を前提に文内で動的に変わって良い変数とする。
短点の長さを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の結果を元にオン・オフ判断する。
実際には揺れがある為、閾値等で調整する。
まとめ
オン・オフ判別は、動体検知も良いが、インテグラルでも可能かもしれない。
しかし、閾値が背景により変動するため、動体検知を使い閾値を規格化し、環境影響を排除する方法もある。
送受信のどちらか、あるいは双方が移動している場合、背景も動き、更なる検討の余地がある。
ref
サイズ
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
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をステップバイステップ試行
全体の流れ
- 単一サーバ上でxdmx/xephyr試行
- 2サーバ上でxephyr/xdmx
- 片側を素のXに置き換え。
- 両側を素の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.