シェルスクリプトマガジン

test

AWKでデジタル信号処理(Vol.82掲載)

投稿日:2023.01.25 | カテゴリー: コード

著者:斉藤博文

プログラミング言語「AWK」は、データストリーム(データの流れ)を逐次処理するのに適しています。本連載では、電子回路の分野でその特徴を生かし、シェルスクリプトを組み合わせてデジタル信号を処理します。第4回は「微分フィルタ」を使って目的の波形を取り出す方法を紹介します。

シェルスクリプトマガジン Vol.82は以下のリンク先でご購入できます。

図10 微分フィルタの差分方程式のAWKプログラム(dif.awk)

#! /usr/bin/gawk -f

BEGIN {
    # define number of order
    num_ord = num_ord ? num_ord : 31;

    # define length of ring buffers
    len_data_raw = num_ord + 1;
    len_data_dif = 1;

    # initialize ring buffers
    for (i = 0; i < len_data_raw; i++) {
        arr_data_raw[i] = 0.0;
    }
    for (i = 0; i < len_data_dif; i++) {
        arr_data_dif[i] = 0.0;
    }

    # initialize index of ring buffers
    idx_data_raw = 0;
    idx_data_dif = 0;

    # initialize number of data
    num_data_raw = 0;
}

{
    # add number of data
    num_data_raw++;

    # update index of ring buffers (write pointers)
    idx_data_raw = num_data_raw % len_data_raw;
    idx_data_dif = num_data_raw % len_data_dif;

    # clear number of data
    if (idx_data_raw == 0 && idx_data_dif == 0) {
        num_data_raw = 0;
    }

    # store input raw data
    val_data_raw = $0;
    arr_data_raw[idx_data_raw] = val_data_raw;

    # apply differential filter
    arr_data_dif[idx_data_dif] = dif(arr_data_raw, idx_data_raw, num_ord, len_data_raw);

    # print results
    print arr_data_dif[idx_data_dif];
}

# get value of ring buffer
function get_buffer(arr, idx, len) {
    if (idx < 0) {
        return arr[idx + len];
    }

    return arr[idx];
}

# differential filter
function dif(arr_x, idx_x, ord, len_x,      _ret, _half, i) {
    _ret = 0.0;
    _half = int((ord - 1) / 2);

    for (i = 0; i < ord; i++) {
        _ret += (_half - i) * get_buffer(arr_x, idx_x - i, len_x);
    }

    return _ret;
}

図12 群遅延を考慮したAWKプログラム(dif_gd.awk)

#! /usr/bin/gawk -f

BEGIN {
    # define number of order
    num_ord = num_ord ? num_ord : 31;

    # define group delay
    val_gd = int((num_ord - 1) / 2);

    # define length of ring buffers
    len_data_raw = num_ord + 1;
    len_data_dif = 1;

    # initialize ring buffers
    for (i = 0; i < len_data_raw; i++) {
        arr_data_raw[i] = 0.0;
    }
    for (i = 0; i < len_data_dif; i++) {
        arr_data_dif[i] = 0.0;
    }

    # initialize index of ring buffers
    idx_data_raw = 0;
    idx_data_dif = 0;

    # initialize number of data
    num_data_raw = 0;
}

{
    # add number of data
    num_data_raw++;

    # update index of ring buffers (write pointers)
    idx_data_raw = num_data_raw % len_data_raw;
    idx_data_dif = num_data_raw % len_data_dif;

    # clear number of data
    if (idx_data_raw == 0 && idx_data_dif == 0) {
        num_data_raw = 0;
    }

    # store input raw data
    val_data_raw = $0;
    arr_data_raw[idx_data_raw] = val_data_raw;

    # apply differential filter
    arr_data_dif[idx_data_dif] = dif(arr_data_raw, idx_data_raw, num_ord, len_data_raw);

    # print results
    print get_buffer(arr_data_raw, idx_data_raw - val_gd, len_data_raw), arr_data_dif[idx_data_dif];
}

# get value of ring buffer
function get_buffer(arr, idx, len) {
    if (idx < 0) {
        return arr[idx + len];
    }

    return arr[idx];
}

# differential filter
function dif(arr_x, idx_x, ord, len_x,      _ret, _half, _gain i) {
    _ret = 0.0;
    _half = int((ord - 1) / 2);

    _gain = 0.0;
    for (i = 0; i < ord; i++) {
        _gain += (_half - i)^2;
    }

    for (i = 0; i < ord; i++) {
        _ret += (_half - i) * get_buffer(arr_x, idx_x - i, len_x);
    }

    return _ret / _gain;
}

図14 係数の補正を加えた関数dif()

# differential filter
function dif(arr_x, idx_x, ord, len_x,      _ret, _half, _gain i) {
    _ret = 0.0;
    _half = int((ord - 1) / 2);

    _gain = 0.0;
    for (i = 0; i < ord; i++) {
        _gain += (_half - i)^2;
    }

    for (i = 0; i < ord; i++) {
        _ret += (_half - i) * get_buffer(arr_x, idx_x - i, len_x);
    }

    return _ret / _gain;
}

香川大学SLPからお届け!(Vol.82掲載)

投稿日:2023.01.25 | カテゴリー: コード

著者:谷﨑 勇太

 最近、さまざまな場面で「VTuber」が活躍しています。VTuberとは、2D/3Dアバターの表情や身体をリアルタイムに動かしながら動画配信をする人、あるいはそのアバターのことです。多くの場合は、カメラで人の動きを検知し、それをトレースするようにアバターを動かしています。今回は、私がPythonを使って作成した簡易VTuberシステムについて紹介します。

シェルスクリプトマガジン Vol.82は以下のリンク先でご購入できます。

図1 Webカメラの映像を読み取るためのベースコード

import cv2
camera = cv2.VideoCapture(0)
while True:
  ret,image = camera.read()
  image = cv2.cvtColor(image,BGR2RGB)
  cv2.imshow("frame", image)
  if cv2.waitKey(1) & 0xFF == ord('q'):
    break
camera.release()
cv2.destroyAllWindows()

図2 感情を検出するためのコード

from paz.pipelines import DetectMiniXceptionFER
pipeline = DetectMiniXceptionFER([0.1, 0.1])
output = pipeline(image)
if len(output["boxes2D"]) == 1:
  emotion = output["boxes2D"][0].class_name

図3 左右の目の縦横比の平均値を算出する関数の定義コード

import cv2
from imutils import face_utils
import dlib
face_detector = dlib.get_frontal_face_detector()
face_parts_detector = \
  dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
def face_landmark_find(img):
  eye = 10
  img_gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  faces = face_detector(img_gry, 1)
  for face in faces:
    landmark = face_parts_detector(img_gry, face)
    landmark = face_utils.shape_to_np(landmark)
    left_eye_ear = calc_ear(landmark[42:48])
    right_eye_ear = calc_ear(landmark[36:42])
    eye = (left_eye_ear + right_eye_ear) / 2.0
  return eye

図5 目の縦横比を計算する関数の定義コード

from scipy.spatial import distance
def calc_ear(eye):
  A = distance.euclidean(eye[1], eye[5])
  B = distance.euclidean(eye[2], eye[4])
  C = distance.euclidean(eye[0], eye[3])
  eye_ear = (A + B) / (2.0 * C)
  return eye_ear

図6 目の開閉を判定して処理を分岐させるコード

if w != 0:
  if eye < EYE_AR_THRESH:
    image = overlayImage(image,close,(x,y),(w,h))
  elif eye >= EYE_AR_THRESH:
    image = overlayImage(image,overlay,(x,y),(w,h))

図7 顔の座標と幅の情報を取得するコード

if len(output["boxes2D"]) ==1:
  x_min, y_min, x_max, y_max = output["boxes2D"][0].coordinates
  w,h = (x_max-x_min,y_max-y_min)
  x,y =x_min,y_min

図8 overlayImage ()関数の定義コード

import cv2
from PIL import Image
import numpy as np
def overlayImage(image, overlay, location, size):
  image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
  pil_image = Image.fromarray(image)
  pil_image = pil_image.convert('RGBA')
  overlay = cv2.cvtColor(overlay, cv2.COLOR_BGRA2RGBA)
  pil_overlay = Image.fromarray(overlay)
  pil_overlay = pil_overlay.convert('RGBA')
  pil_overlay = pil_overlay.resize(size)
  pil_tmp = Image.new('RGBA', pil_image.size, (255, 255, 255, 0))
  pil_tmp.paste(pil_overlay, location, pil_overlay)
  result_image = Image.alpha_composite(pil_image, pil_tmp)
  return cv2.cvtColor(np.asarray(result_image), cv2.COLOR_RGBA2BGRA)

図9 insert()関数の定義コード

import os
def insert():
  r = os.path.exists('user.txt')
  if r == False:
    print("初期設定を行います")
    print("目を閉じてください")
    setting()
    eye_int()
  elif r == True:
    count = len(open('user.txt').readlines())
    if count == 0:
      print("初期設定を行います")
      print("目を閉じてください")
      setting()
      eye_int()
    elif count == 1:
      eye_int()

図10 setting ()関数の定義コード

import cv2
import math
def setting():
  f = open('user.txt', 'w')
  count = 0
  eye_sum=0
  while True:
    ret,rgb = cap.read()
    eye = face_landmark_find(rgb)
    if ret == True:
      if eye != 10:
        count +=1
        eye_sum += eye
    if(count > 50):
      x=eye_sum/50+0.01
      break
  cap.release()
  cv2.destroyAllWindows()
  x = math.floor(x*100)/100
  f.write(str(x)+'\n')
  f.close()

図11 eye_int()関数の定義コード

def eye_int():
  f = open('user.txt','r+')
  lins = f.readlines()
  print('推奨する設定値は'+lins[0]+'です')
  tmp = input('設定値を入力してください:')
  f.write(tmp)

特集1 LibreOfficeでPythonマクロ(Vol.82記載)

投稿日:2023.01.25 | カテゴリー: コード

著者:荒川 雄介

オープンソースのオフィスソフト「LibreOffice」は、Pythonで記述されたマクロ(簡易スクリプト)を実行できます。しかしデフォルト状態では、Pythonマクロを作成しやすい環境が整備されていません。本特集では、開発環境を整備する手順を中心に、Pythonマクロ作成についての基礎知識を紹介します。使い慣れた言語を使って、LibreOfficeのさまざまな処理を効率化しましょう。

シェルスクリプトマガジン Vol.82は以下のリンク先でご購入できます。

図3 「Hello!」と書かれたダイアログを表示するPythonマクロのコード

from scriptforge import CreateScriptService
def hello():
  bas = CreateScriptService("Basic")
  bas.MsgBox("Hello!")
g_exportedScripts = (hello,)

図9 CSVファイルからCalcのシートにデータを読み込むPythonマクロのコード

from scriptforge import CreateScriptService
def load_csv():
  cal = CreateScriptService("Calc")
  cal.ImportFromCSVFile(r"C:\test.csv", "A1")
g_exportedScripts = (load_csv, )

図11 図9のコードを新規のCalcシートを開くように変更したもの

from scriptforge import CreateScriptService
def load_csv():
  ui = CreateScriptService("UI")
  cal = ui.CreateDocument("Calc")
  cal.ImportFromCSVFile(r"C:\test.csv", "A1")
g_exportedScripts = (load_csv, )

図12 文書ファイルがある場所からCSVファイルを読み込めるように図9のコードを変更したもの

from scriptforge import CreateScriptService
import uno
import os.path
def load_csv():
  doc  = XSCRIPTCONTEXT.getDocument()
  path = uno.fileUrlToSystemPath(doc.URL)
  cdir = os.path.dirname(path)
  cal = CreateScriptService("Calc")
  cal.ImportFromCSVFile(cdir + r"\test.csv", "A1")
g_exportedScripts = (load_csv, )

図13 データベースからデータを読み込んで集計/グラフ表示をするPythonマクロのコード

from scriptforge import CreateScriptService
def importdata():
  # データベースからデータを取得
  db=CreateScriptService('database',registrationname='Bibliography')
  sql='SELECT [Custom1] AS [Language],[Identifier] FROM [biblio] ORDER BY [Language] ASC'
  data=db.GetRows(sql,header=True)
  db.CloseDatabase()
  # 取得したデータをシートにコピー
  calc=CreateScriptService("Calc")
  datarange=calc.setArray('Sheet1.A1',data)
  # ピボットテーブルを作成して集計
  pivot=calc.CreatePivotTable('Pivot1',datarange,targetcell='D1',
  datafields='Identifier;Count',rowfields='Language',
  rowtotals=False,columntotals=False,filterbutton=False)
  # グラフを作成
  chart=calc.CreateChart('NumberByLanguage','Sheet1',pivot,rowheader=True,
                         columnheader=True)
  chart.ChartType, chart.Dim3D,chart.Legend='Pie',True,True
  chart.Resize(4000, 3000, 7000, 2500)
g_exportedScripts = (importdata, )

図18 図9のコードをイベント駆動できるように修正

from scriptforge import CreateScriptService
def load_csv(args=None):
  cal = CreateScriptService("Calc")
  cal.ImportFromCSVFile(r"C:\test.csv", "A1")
g_exportedScripts = (load_csv, )

図19 Calcのシート(Sheet1)の内容をすべて消去するPythonマクロのコード

from scriptforge import CreateScriptService
def clear(args=None):
  calc=CreateScriptService("Calc")
  calc.ClearAll('Sheet1.*')
g_exportedScripts = (clear, )

図20 外部ライブラリ(NumPy)を利用するythonマクロのサンプルコード

from scriptforge import CreateScriptService
import numpy as np
def test_numpy():
  A = np.array([1, 2, 3, 4, 5, 6]).reshape(2,3)
  B = A + 10
  cal = CreateScriptService("Calc")
  cal.setArray("A1", B.tolist())
g_exportedScripts = (test_numpy, )

シェルスクリプトマガジンvol.82 Web掲載記事まとめ

投稿日:2023.01.25 | カテゴリー: コード

004 レポート ポッキーでプログラミング
005 レポート WebAssembly対応Ruby 3.2.0
006 製品レビュー 制御機器「NFCタグ」
007 NEWS FLASH
008 特集1 LibreOfficeでPythonマクロ/荒川雄介 コード掲載
016 特集2 Dropboxを活用しよう/岡崎隆之、進藤麻礼子、井川恵理
028 緊急企画 Mastodonサーバーを構築しよう/麻生二郎
046 Raspberry Piを100%活用しよう/米田聡
050 行動経済学と心理学で円滑に業務を遂行/請園正敏
052 中小企業手作りIT化奮戦記/菅雄一
057 Hello Nogyo!
058 Pythonあれこれ/飯尾淳
066 法林浩之のFIGHTING TALKS/法林浩之
068 タイ語から分かる現地生活/つじみき
072 Emotet/桑原滝弥、イケヤシロウ
074 香川大学SLPからお届け!/谷﨑勇太 コード掲載
080 AWKでデジタル信号処理/斉藤博文 コード掲載
086 ユニケージ通信/田渕智也、高橋未来哉
090 Bash入門/大津真
098 Techパズル/gori.sh
099 コラム「ユニケージ流思考法」/シェル魔人

Vol.82

投稿日:2023.01.25 | カテゴリー: バックナンバー

 Microsoft Office上での処理を自動化する場合、「BASIC」(VBA)言語によるマクロを記述することがよくあります。オープンソースのオフィスソフト「LibreOffice」でも同様に、BASICによるマクロが記述できて動作します。ただし、Microsoft Office上のBASICとどこまで互換性があるのかは未知数です。
 LibreOfficeでは、BASIC以外に「BeanShell」(Java風のスクリプト言語)、「JavaScript」「Python」の言語でもマクロを記述できます。Pythonは人気のプログラミング言語であり、国内にも多くのプログラマがいます。LibreOfficeだけをビジネスの現場で使うならPythonでマクロを記述するのがよいでしょう。特集1では、このPythonによるマクロ作成の基本を解説しています。
 特集2では、老舗のオンラインストレージサービス「Dropbox」を紹介しています。オンラインストレージは、クラウド上でファイルを保管して管理するだけではありません。共同の編集作業や、ファイルの整理に十分活躍します。本特集を参考にしてDropboxでファイルを自在に扱ってください。
 緊急企画では、Twitterの代替となる「Mastodon」サーバーの構築方法を解説しています。米Twitter社を買収したElon Musk氏によって、収益改善やコスト削減などが進められています。しかし、それと同時にさまざまな不安を感じている人が増えています。Mastodonは、1社運営ではなく、さまざまな団体や企業、個人のサーバーが連携し合ってTwitterと同等のサービスが提供できるオープンソースのソフトウエアです。すぐにTwitterの代替となるわけではありませんが、Twitterの代替として最も注目されています。
 このほか、「行動経済学と心理学で円滑に業務を遂行」の新連載を開始しました。仕事を進めるときに、人間関係は重要です。言い方一つで、意欲的になったり、充実感が得られたりします。行動経済学と心理学による分析結果からチームで円滑に業務を遂行する方法を解説します。
 今回も読み応え十分のシェルスクリプトマガジン Vol.82。お見逃しなく!

※記事掲載のコードはこちら。記事の補足情報はこちら

※読者アンケートはこちら

Vol.82 補足情報

投稿日:2023.01.19 | カテゴリー: コード

Pythonあれこれ

 記事中で使用するデータファイルは以下のWebページから入手できます。

https://github.com/shellscript-magazine/python_this_and_that/releases/tag/ver2.0

情報は随時更新致します。

  • shell-mag ブログの 2023年1月 のアーカイブを表示しています。

  • -->