平成 12 年度
学士学位論文ニューラルネットワークを用いた
筋活動電位のパターン認識システムの構築に関する研究
Construction of pattern recognition system of
erectoromyogram by neural networks

学籍番号 1010419
指導教員

中原

竹田史章

昌樹

教授

2001 年 2 月 5 日
情報システム工学科

概要
腕の動作により、携帯機器等における動作識別を可能とするために、本論文では被験者の随意運動に伴う生体信号である筋活動電位（EMG：electromyogram）の認識システムを検討する。特に、筋活動電位の登録、認識には学習能力を有しかつ、非線形パターン識別が可能な階層型ニューラルネットワークを用い、シミュレーションにてその有効性と可能性を示す。

abstract
In this paper, we propose a recognition system to enable recognition ofoperation in portable equipment by operating the arm of testee. Especially,learning and recognition of electromyogram by using neural networks, which havethe learning ability and nonlinear pattern identification, is possible.We show theeffectiveness and possibility of the electromyogram recognitionby simulation.
キーワード：ニューラルネットワーク、屈筋信号、伸筋信号、生体情報

− i −

目次
１．はじめに ................................................................
................................................................................................
..........................................................................
.......................................... 1
２．筋電パターン認識システム................................
................................................................
２．筋電パターン認識システム...............................................................................
............................................... 3筋活動電位.................................................................................................. 3
２．１ 筋活動電位
総合操作装置の構成.................................................................................... 3
２．２ 総合操作装置の構成
２．３ システム構成 ............................................................................................ 4
２．４ 入力部 ....................................................................................................... 5
電極................................................................................................. 5
２．４．１ 電極
２．４．２ 電極配置 ......................................................................................... 6
２．５ 信号処理部 ................................................................................................ 7
２．５．１ アンプの構成 .................................................................................. 7
２．５．２ アンプの設計仕様 ........................................................................... 8
ＤＦＴ、ＦＦＴ..............................................................................11
２．５．３ ＤＦＴ、ＦＦＴ
２．５．４ 筋電信号出力プログラム .............................................................. 12
２．６ データ変換部 .......................................................................................... 16
２．６．１ データ変換プログラム .................................................................. 16
データ抽出.................................................................................... 20
２．６．２ データ抽出
登録・認識部
２．７ 登録・認識部 .......................................................................................... 21
２．７．１ ニューラルネットワーク .............................................................. 21
２．７．２ 学習システム ................................................................................ 26
２．７．３ 環境設定ファイル ......................................................................... 26
データベース設定ファイル........................................................... 27
２．７．４ データベース設定ファイル
学習データ抽出............................................................................. 27
２．７．５ 学習データ抽出
スラブ値ファイル作成.................................................................... 28
２．７．６ スラブ値ファイル作成
スラブファイルの並び替え............................................................. 29
２．７．７ スラブファイルの並び替え
教師ファイル作成........................................................................... 29
２．７．８ 教師ファイル作成
２．７．９ 学習 ................................................................................................ 30
認識・評価
２．７．１０ 認識
・評価 .................................................................................. 30
３． 実験 ................................................................
................................................................................................
............................................................................
............................................ 33
３．１ 電極の最適位置 ....................................................................................... 33
３．２ データ採取 .............................................................................................. 34
ノイズ対策.................................................................................... 34
３．２．１ ノイズ対策
３．２．２ 実験方法 ....................................................................................... 34
３．２．３ 実験条件 ....................................................................................... 35
実験結果.................................................................................................. 35
３．３ 実験結果
４．まとめ ................................................................
................................................................................................
............................................................................
............................................ 50− ii −

５．謝辞 ................................................................
................................................................................................
...............................................................................
............................................... 51
６．参考文献 ................................................................
................................................................................................
........................................................................
........................................ 52
付録 ................................................................
................................................................................................
......................................................................................
...................................................... 53− iii −

１．はじめに
従来、被験者の動作を解析するためには、マウス、データグローブ、データスーツ、
モーションキャプチャなどのように位置や力の情報を計測するものがある。しかしながら、これらはユーザが直接触れる機器の形状、重量がユーザの身体的特性に合っていない場合、使いにくく、ユーザに不快感を与える。具体的には、マウスが大きすぎたり、腕時計が重過ぎたりするなどである。
近年、携帯電話を代表とする携帯情報端末機器は急速に普及し、Bluetooth（１）などの携帯機器の無線通信規格が整いつつあり、これを利用すれば、多くの機器で使用頻度の高い操作を一つの操作装置で集約して行うことも可能である。たとえば、公共交通を利用する際に、携帯電話をマナーモードにする、あるいは、音楽プレーヤの音量を調節するなどの操作を各機器を取り出すことなく、片手で一度に行うことが実現可能であると考えられる。
現在、このように、機器の操作だけを独立した機能として持ち、携帯機器のネットワークをコントロールする装置（総合操作装置と略記）は提供されていない。そのため、総合操作装置を操作する信号には被験者の随意運動に伴い発生する生体信号である筋活動電位を検討する。
生体信号には顔、光彩、指紋、筆圧、音声などがあり、前者の 3 つは身体的特徴、
後者の 2 つは行動的特徴と呼ばれる。これらの違いを述べると、行動的特徴はデータ採取に際して心理的抵抗が小さい。そして、身体的特徴は再現性が高く、同一人物か
ら何度でも同じデータを得ることが可能であるといった特徴がある。本研究で使用する筋活動電位は行動的特徴に含まれる。
筋活動電位により制御される総合操作装置は操作性を考え、腕時計型や指輪型であることが望ましいと考えられる。そのため、指や手首の筋活動電位を採取することが考えられるが、手首から得られる筋活動電位は微弱な電位であるために、本研究では、腕からの筋活動電位において最も良好な出力結果が得られた前腕二頭筋にて認識実験を行う。
通常、細胞内側の電位は細胞外側に対して、マイナスの電位である。これは主に K＋の細胞内外の濃度差によってもたらされる。このマイナスに偏った電位を静止膜電位という。活動電位とは脱分極による細胞の興奮、すなわち、細胞内側の電位が静止
膜電位(約−70mv)を超え、一時的(約 1ms)に正になる一連の反応をいう（2），(3)。筋活
動電位の発生に際してはまず、遠心性神経のインパルスが神経と筋の接合部である神経筋接合部に到達する。神経インパルスが神経末端より伝達物質アセチルコリンが遊離され、これが神経筋接合部の間隙を越え、筋の膜面に達し、筋線維に興奮を引き起こす。これを膜の脱分極といい、マイナス側にある静止膜電位の平衡状態を破り、プラス側に変化させることである。いくつかの神経パルスの到達により興奮状態が高ま− 1 −ると、筋細胞内部は急速に 30〜50mV に増加する。ここで、筋に電極を装着すれば、電位変化を観測することができる。これを筋活動電位と呼ぶ(4)。筋活動電位には筋収縮レベルに応じて発生する、動作、力の入れ具合、運動レベルに応じての情報や運動の柔らかさの情報を含むといった特徴を持つ。
現状の筋活動電位の認識するための機器は、機器が大きく、センサの位置ずれなどにより検出信号が変化し、誤認識がおこる可能性がある。また、筋活動電位は個人差があり、人によっては誤認識、誤動作がおこる可能性がある。そのために機器の誤動
作、誤認識は事故を引き起こすことも考えられる。本研究では、筋活動電位の特徴抽
出には従来手法である高速フーリエ変換（FFT：Fast Fourier Transform）とニュー
ラルネットワークを利用し（５）．（６）．（７）、誤認識、誤動作の少ない筋電位認識システムを提案する。
本研究では、手首の動作識別を検討する。実際に起こりうる様々な手首の動作の中から、手首を上下へ動かすという 2 種類の動作が識別可能であるかを検証する。被験者が右手の手首を上に上げる際に使用する筋である橈側（とうそく）手根屈筋、下に下げる際に使用する筋である尺側（しゃくそく）手根屈筋の筋活動電位を検出する。
電極から検出された筋活動電位は非常に微弱である。そのため、アンプにより筋活動電位を増幅する必要がある。さらに、電極からアンプまでの配線にはノイズが混入しており、筋活動電位よりも大きな電位をもっている場合が多い。そのため、筋活動電位を採取する際のノイズ対策についても検討する。そして、ノイズ除去を行った筋活
動電位を特徴抽出し、このデータをニューラルネットワークへの入力信号とする。使用するニューラルネットワークは階層型で、このニューラルネットワークは文字認識
や、画像認識に適している。ニューラルネットワークの出力関数にはシグモイド関数を使用し、非線形分離能力を持たせる。本研究では学習能力を有しかつ、非線形分離能力を有する 3 層の階層型ニューラルネットワークを使用し、認識システムの有用性について検討する（５）。

− 2 −２．筋電パターン認識システム
２．１ 筋活動電位
筋活動電位とは筋を使うことにより、細胞内液と細胞外液のバランスが崩れ、脱分極が起こり発生する。筋活動電位は筋収縮レベルに応じて発生する、動作、力の入れ具合、運動レベルに応じての情報や運動の柔らかさの情報を含むといった特徴を持つ。
つまり、個人差はあるものの、筋に力を入れるほど、大きな筋活動電位が発生する。
さらに、運動に応じての特徴を持つため、この特徴をつかむことができれば、動作の認識が可能である。つぎに筋活動電位により制御される総合操作装置について述べる。

２．２ 総合操作装置の構成
本章では前章で述べた総合操作装置の構成について述べる。携帯機器の操作インタ
ーフェースのみが独立した装置は現在販売されておらず、同等の機能をもつ代替品はあまりない。類似の技術として音声認識による操作装置などがあるが、騒音を問題とする公共の場では使用が限定される。本研

図 2.1

携帯機器総合操作装置の概略図

操作指令「E-mail」
E-mail」
「受信」

図 2.2

総合操作装置の構成− 3 −究で目標とする総合操作装置は片手で周囲に影響を与えず操作できるという点で、使用場所を制限されないというメリットを持つ。総合操作装置の機能としては携帯電話
でのメールの受信や、マナーモードへの設定/解除、音楽プレーヤでの鑑賞曲の変更
や音量の調節などが考えられる。現在、総合操作装置は操作性を考慮すると、図 2.1のように腕時計型や指輪型が望ましいと考えられる。そのため、指や手首における筋活動電位を測定することが望ましい。
図 2.2 に総合操作装置の構成図を示す。
センサである腕時計などから筋活動電位を検出する。腕時計を装着する手首から検出される筋活動電位は微弱な信号であるために、アンプ部で信号を増幅させ、信号による操作指令の認識を行う。そして、その認識結果を無線で携帯機器に送信し、機器が作動する仕組みである。
手首から検出される筋活動電位は小さく、良好な大きさの電位が得られないことがわかった。そこで、本研究では腕からの筋活動電位を採取するために、最も大きい筋活動電位が検出された前腕二頭筋にて実験を行う。

２．３ システム構成
本研究で提案する筋活動電位のパター
ン認識システムの構成を図 2.3 に示す。
本システムは入力部、信号処理部、データ変換部、認識・登録部から構成される。
入力部では腕に装着する電極より採取される筋電信号はアンプにより増幅される。そして、A/D 変換され、PC（PC：
Personal Computer）へ入力される。入力された筋電信号は PC 内の筋電信号出力プログラムにより時系列データ（Tdataと略記）を生成する。さらに、FFT により特徴抽出され、Tdata より FFT データ（Fdata と略記）を生成する。
図 2.3
− 4 −

システム構成出力される Tdata,Fdata は Fdata のみ PC 内に組み込まれているニューロ学習シ
ステム（学習システムと略記）に入力される。その際、ニューロ学習システムに入力するためのヘッダ情報が付加される。学習で得られたニューロウェイトを用いて、様々のデータの評価を行う。

２．４ 入力部
２．４．１ 電極
筋活動電位には表面電極（passive electrode）により計測される表面筋電と針電極（inserted electrode）により計測される深層筋電がある。針電極は直接筋中に刺入するために、計測される深層筋電は、近傍の活動電位のみを計測することができる。
このため、特定の筋からの特徴が得やすいという利点を持つが、それと同時に被験者に拒否感を与えるという欠点も併せ持つ（６）。それに対し、表面電極は測定に苦痛を伴わず、容易に着脱でき、電極の腐食等による細胞への影響がないために生体に対して安全である。しかしながら、計測される筋活動電位は複数の筋線維の活動電位（MUAP）が混入した信号であるため、生の記録波形から筋の活動様式や運動制御を分離することは容易ではない（８）。
本研究では携帯等の情報端末の操作装置、入力装置として実用化を考慮し電極には表面電極用いる。表面電極はさらに湿式（電解クリームを使用する）と乾式（電解ク
リームを使用しない）に分類される。扱いやすさの点からみると、乾式が望ましいが、筋電信号を採取するためには湿式の方が現段階では確実性が高いという点により、湿式を採用する。
湿式の表面電極では金属−電解液、つまり電極の金属−汗の平衡状態の不均衡により、不安定で数 10mv 程度の大きな電位をもつ分極電位が生じるが、これは温度変化、発汗、電解クリームの変化、電極と皮膚間の動き、電解液と金属の種類や性状などにより影響を受ける。この分極電位を抑えるために電極には銀−塩化銀電極（NT-211U，8φ，
日本光電（株）製）を用いる。電解クリームには脳波筋電用ペースト（エレフィックス
Z-401CE，日本光電（株）製）を使用する。
ラジオや TV 放送の電波、蛍光灯などから発生する電磁波ノイズなどの影響から配線を守るために、図 2.4 のように電極の配線を束ね、
図 2.4 小型生体用電極− 5 −配線にノイズが混入しないようにアルミホイルで覆う。さらに、束ねた配線をリング状にしている。リング状にしているのも電磁波ノイズの影響を軽減するためである。
配線をリング状にすると、リングの中を通過する電磁波を電流として検出し、増幅する可能性がある。この電磁波の影響を軽減するには 2 つの方法があり、1 つはリングの面積を最小にし、通過する電磁波の量を小さくする方法である。もう 1 つはリングを 2 つ作り、一方のリングに発生した電流と、もう一方に発生したリングの電流を逆向きに作用させ、相殺する方法である。本研究では、後者の方法を採用する。つまり、同じ大きさ、回数で巻いたリングを途中で逆向きにして束ねることにより、リングに通過した電磁波によって発生する電流は互いに打ち消し合い消えてしまう。
図 2.4 に実験で用いた電極を示す。2 個の測定電極 2 組と 1 個の不感電極（アース）の計 5 個を利用する双極誘導法を用いる。このため、図より 5 本の配線が見られるが、その内訳として、2 箇所の筋を測定するためにチャンネル 1，2 分の 4 個の測定電極と１つの不感電極を割り当てている。

２．４．２ 電極配置
手首を上げる動作、下げる動作の 2 種類を検出するために、電極には 2 チャンネル用意する。橈側手根屈筋にチャンネル 1 の電極を、尺側手根屈筋にはチャンネル 2 の電極を配置する。手首を上に上げた場合、橈側手根屈筋が主に使用され、手首を下に下げた場合、尺側手根屈筋が主に使用される。本研究の電極配置は図 2.9 のように筋線維に対し、垂直に配置する。図 2.10 のように筋線維方向に沿って、測定電極を配置する。そして、筋肉の存在しない肘に不感電極を配置すると、クロストークを防ぐことができる。これは、信号チャネルを多重化することにより、他のチャンネルに信号が伝わることを防げ、特定の筋からの情報を得られるために、良好な出力が期待できる。しかしながら、電極を前者のように配置しない理由は特定の筋からの情報により、特定の動きだけを認識するのではなく、複数の筋から様々な情報を得て、腕の様々な動きの認識できることを目的としているため、電極を図 2.9 のように配置する。電極は筋線維の走行方向に沿って 2cm 間隔で固定する。不感電極はチャンネル 1，2 の電極の中央に配置する。

図 2.5

橈側手根屈筋（右手）
− 6 −

図 2.6

尺側手根屈筋（右手）図 2.7

手首を上に上げた状態（右手）図 2.9

実験で採用した電極配置

図 2.8

手首を下に下げた状態（右手）

図 2.10

理想と思われる電極配置

２．５ 信号処理部
２．５．１ アンプの構成
本節では、まず、アンプの構成である、A/D 変換変換回路について述べる。A/D 変
換回路は図 2.11 のように構成される（２）。
はじめに、複数あるアナログ入力信号（筋電信号）の中から、変換する 1 つの信号を選択するためのマルチプレクサがある。これは、入力選択用の数ビットのディジタ
ル信号を与えてアナログスイッチを操作させ、アナログ入力を切り替える仕組みの− 7 −

図 2.11

A/D 変換回路の構成

IC である。
フィルタは不必要な信号を取り除くために使用する。フィルタには低い周波数の信号のみを通過させて高い周波数の信号を除去するローパスフィルタ、高い周波数の信号のみを通過させて低い周波数の信号を除去するハイパスフィルタ、ある範囲の周波数の信号のみを通過させるバンドパスフィルタ、ある特定の周波数の信号のみを除去するノッチフィルタなどがある。表面筋電の場合、2、3Hz〜2kHz 程度周波数成分のうち、ノイズが混入する可能性の低い 70Hz 以上の周波数成分をローパスフィルタとノッチフィルタで検出する。
増幅器は微弱なアナログ信号を A/D 変換器が扱いやすい大きさまで増幅する。サンプルホールドは正しく A/D 変換を行うために A/D 変換器が変換処理中にアナログ信号が変化しないよう、ある瞬間の値を保持させる。DI/IO ポートは A/D 変換器からの変換出力や、A/D 変換器の制御信号を PC とやりとりするための専用制御回路である。
タイマーはサンプリング周期を発生させるものである。タイマー出力がパソコンへ向いているのは変換開始制御を割り込み処理として行うためである。

２．５．２ アンプの設計仕様
筋電信号の主な周波数は、表面電極で測定した場合、数 Hｚ（2，3Hz）〜2kHzと報告されている。表 2.12 からわかるように、商用周波数ノイズ（70Hz）の影響を避けるため、筋電信号のうち 70Hz〜2kHz を抽出する。ノイズ混入を軽減するために差動増幅という手法を利用する。これは双極誘導である 2 個の測定電極 2 組と 1 個の不感電極の間に生じる電位差には筋活動電位は逆相（信号の位相が 180 度ずれる）、
周囲ノイズは同相（信号の位相が同じ）で入る。そこで、この測定電極と不感電極間の電位差の差をとると、出力には同相の周囲ノイズは打ち消されるため現れず、逆相− 8 −である筋活動電位のみが現れ、ノイズを除去することができる。そして、アンプの筐体はアルミ製である。これは電磁波ノイズの影響を軽減するためである。表 2.12 中の CMRR(common mode rejection ratio, 同相信号除去比）とはノイズ除去能力を示している。出力される筋電信号は、一般にいわれる EMG である。
表 2.12

アンプの設計仕様

低域遮断周波数
高域遮断周波数増幅率（ゲイン）EMG
出力最大電圧入力定格電圧CMRR

図 2.1370Hz（6次フィルタ）
2kHｚ（6次フィルタ）
約2000倍 （65ｄB）
4ch計測可±5V±2.5ｍV
60ｄB 以上

アンプの内部

A/D 変換カードには A/D 変換カード（MREX-5054B，RATOC Systems Inc.製）を用いた。図 2.14 に A/D 変換カードと接続用 BNC コネクタ付 BOX を示す。
図 2.15 に実験で用いるアンプを示す。左から電源スイッチ、電極に接続するためのチャンネル 1 のプラス、マイナス、アース、チャンネル２のマイナス、プラス、そして、採取する筋活動電位にノイズが多く混入する場合に使用するアース、Ａ/Ｄ変換
カードに接続するためのチャンネル 4，3，2，1 である。チャンネル 3，4 はデータ採取部位を増やす際の予備であり、本研究では使用しない。

− 9 −

図 2.14

A/D 変換カードと接続用 BNC コネクタ付 BOX

図 2.15

図 2.16

アンプの外観システムの完成状態- 10 -

２．５．３ ＤＦＴ、ＦＦＴ
本項ではまず、筋電信号出力プログラムに組み込まれた FFT について述べる。FFTとは離散フーリエ変換（DFT：Discrete Fourier Transfomer）の演算時間を大幅に短縮させたものである。DFT とはサンプリングされた有限個のディジタル信号に対するフーリエ変換のことである。フーリエ変換とはフーリエ係数を求める処理で、x(t)のフーリエ級数展開は∞

x(t ) = a 0 + ∑ (a n cos 2πnt / T + bn sin 2πnt / T )

(2.1)

n =1

と表せる。 a n , bn はフーリエ係数で、 a 0 は直流成分を表す。直流成分は入力データの平均値で、フーリエ係数は信号 x(t)に含まれる各成分の割合を示す。
この x(t)は式(2.2)のように複素数で表現するので、
x(n) = x r (n) + jxi (n)(2.2)

DFT による変換結果も複素数となり、X (k ) = ∑ ( x r (n) + jxi (n))(cos(2πnk / N ) − j sin( 2πnk / N )(2.3)= ∑ {( x r (n) cos(2πnk / N ) + xi (n) sin( 2πnk / N )) + j ( xi (n) cos(2πnk / N )− x r (n) sin(2πnk / N ))}(2.4)と表される。

図 2.17

フーリエ変換- 11 -

FFT の高速化の仕掛けは、演算の過程でビット並びが逆転する現象が起こるために正常な順に並べ替える処理であるビット逆転処理と FFT の基本演算におけるデー
タの流れであるバタフライ演算の 2 つの手法により複素数の乗算処理を共用できるようになるため、乗算回数が激減し、高速演算処理が可能となる。（９），（１０）表 2.18に DFT と FFT の演算回数の比較を示す。
表 2.18 DFT と FFT の演算回数

データ数ｎ個のフーリエ変換を行う場合、通常、ｎ２回の積和演算が必要とするが、FFT アルゴリズムを用いると nlog2n 回と大幅に減らすことができ、膨大な時間を要
す DFT の演算時間が短縮できる。

２．５．４ 筋電信号出力プログラム
ここで、筋電信号出力プログラムにより出力される Tdata に対し、FFT 処理を行ったものを Fdata とする。Fdata は振幅スペクトルといい、

Xn = a n + bn
2

(2.5)

2

と表す。
手首を上げると橈側手根屈筋が主に使用され、橈側手根屈筋であるチャンネル 1からの筋活動電位が増加する。ここで、手首を上げた時の波形を図 2.19，図 2.20 に示す。図 2.19，図 2.20 において大きな波形を示すのはチャンネル 1 である橈側手根屈筋の出力波形である。逆に小さな波形を示すのはチャンネル 2 である尺側手根屈筋の出力波形である。図 2.19 は被験者が手首を上げた時の実時間波形（Tdata）を図2.20 は被験者が手首を下げた時の振幅スペクトル（Fdata）を示す。
同様に、手首を下げると尺側手根屈筋が主に使用され、尺側手根屈筋であるチャン- 12 -

ネル 2 からの筋活動電位が増加する。図 2.21，図 2.22 において大きな波形を示すのはチャンネル 2 である尺側手根屈筋の出力波形である。逆に小さな波形を示すのはチャンネル 1 である橈側手根屈筋の出力波形である。

図 2.19

手首を上げた時の実時間波形（Tdata）

図 2.20

手首を上げた時の振幅スペクトル（Fdata）- 13 -

図 2.21

図 2.22

手首を下げた時の実時間波形（Tdata）

手首を下げた時の振幅スペクトル（Fdata）- 14 -

図 2.23

筋電信号サンプルプログラム実行画面

Fdata は(2.5)式よりマイナスの値をとらないが、図 2.21，図 2.22 のようにチャンネル 2 の Fdata がマイナスの値を示す理由はチャンネル 1，2 の波形が重なり、見づ
らいため、チャンネル 2 から出力されるの Fdata に−1 を掛け、グラフを反転させる。
図 2.23 は筋電信号出力プログラム実行画面を示す。上の画面には実時間波形を、下の画面には振幅スペクトルを出力する。このプログラムにより保存されるファイル
名は”nameA001u.txt”となり、name が被験者の名前、Ａは採取位置、001 は採取カ
ウント数、u は手首を上に上げた状態、d は手首を下げた状態でのデータを示す。
図 2.24 は筋電信号出力プログラムから出力されるデータの一部である。データはアスキー形式で、左列から順に時間間隔、チャンネル 1 から出力される Tdata、チャ
ンネル 2 の Tdata、周波数のサンプリング間隔、チャンネル 1 の Fdata、チャンネ
ル 2 の Fdata である。
サンプリング点が 2048 個のため、採取されるデータは 2048 行出力される。Fdata
は 2048 の半分である 1024 個のデータが必要であればよいので、1025 行目以降のチャンネル 1，2 の Fdata には 0 を代入する（１1）。

- 15 -

図 2.24筋電信号出力プログラムの出力データ（一部）

２．６ データ変換部
本節では前項により出力された Fdata を学習システムに入力するため、ヘッダ情報を Fdata に付加するデータ変換プログラムについて述べる。

２．６．１ データ変換プログラム
筋電信号出力プログラムに出力されるデータは表 2.24 で示すように時間間隔、チャンネル 1，2 の Tdata、周波数のサンプリング間隔、チャンネル 1，2 の Fdata が記述されている。
学習システムへの入力データは表 2.25 に示されるようにヘッダ情報、画像データ、
スラブ値データで構成される。
スラブ値データとは筋電信号出力プログラムにより出力されるチャンネル 1，2 のFdata を示す。
図 2.26 に示すように、学習システムで設定するニューラルネットワークの入力層
細胞数は 50 である。各 1024 ずつ存在するチャンネル 1，2 の Fdata からそれぞれ
25 個ずつ計 50 個のデータをニューラルネットワークへの入力データとする。このデータを SLAB1〜50 とする。SLAB1〜25 にはチャンネル 1 の Fdata から抽出する
25 個、SLAB26〜50 はチャンネル 2 の Fdata から抽出する 25 個を割り当てる。た- 16 -

とえば、図 2.24 の場合、チャンネル 1，2 の Fdata の上から 25 個を抜き出すと SLAB1
は 16.501464、 SLAB2 は 8.4778502、 SLAB26 は 1.3256835 となる。この SLAB1〜50 の抽出方法については 2.6.2 項で触れる。
さらに、図 2.24 に示すチャンネル 1，2 の Fdata はアスキー形式のため、学習シ
ステムへの入力形式であるバイナリ形式に変換する。
表 2.25

データ１枚分のフォーマット

ヘッダ情報
ダミーデータ
スラブ値データ(64byte)(4byte)(200byte)

データの解説をすると、ヘッダに 64byte、ダミーデータに 4byte（float 型）を確保する。ダミーデータとは学習システムの汎用性を保つために本来は画像データが入力される。しかしながら、本研究である筋電パターン認識システムには不必要である
ため、領域の確保のみを行う。Fdata はプログラム中、float 型（4byte）で宣言されているため、スラブ値データには (25 + 25) × 4 = 200 byte を確保している。

図 2.26

ニューラルネットワークへの入力データモデル- 17 -

表 2.27

ヘッダ情報のフォーマット

予約領域１(4byte)
データ１枚分の総サイズ(4byte)パターン番号(1byte)金種(1byte)方向(1byte)国情報(1byte)
通し番号(2byte)機種(1byte)号機(1byte)
種別(1byte)
センサ番号(1byte)
画像のXサイズ（画素数）(2byte)
画像のYサイズ（画素数）(2byte)センサ有効域チャネル番号（L） (2byte)
センサ有効域チャネル番号（H） (2byte)
予約領域２(2byte)センサ分解能（X方向）(1byte)センサ分解能（Y方向）(1byte)
予約領域３(6byte)紙幣の中心画素のX座標(2byte)紙幣の中心画素のY座標(2byte)
画像データのオフセット(4byte)
予約領域４(4byte)
スラブ値の種類数(1byte)
１種類目のスラブ値のマスクID (1byte)
１種類目のスラブ値の個数(1byte)
予約領域５(5byte)
スラブ値のオフセット(4byte)
予約領域６(4byte)表 2.27 は表 2.25 のデータ 1 枚分のヘッダ部分の構成を示すものであり、表 2.27
は紙幣の場合を示し、本研究では筋電パターン認識システム用に応用する。
・予約領域
学習システムを拡張するために用意している。
・データ 1 枚分の総サイズ
上記で示したヘッダ情報 64byte、画像データ 4byte、スラブ値データ
200byte の計 268byte である。
・画像フレームの X サイズ、Y サイズ
画像データの大きさ。
・画像データのオフセット- 18 -

ヘッダの先頭を 0 バイト目とする際、画像データの先頭からのバイト数。
・1 パターン目のスラブ値の数
ニューラルネットへの入力層数。
・スラブ値データのオフセット
ヘッダの先頭を 0 バイト目とする際、スラブ値データの先頭からのバイ
ト数。
ここで、採取したデータの集合をデータファイルとし、データファイルの構成を図2.28 に示す。
データファイル名の”emg01.db”で同じ動作のファイルを 1 つに管理する。
図 2.29、図 2.30 に、このプログラムの入力画面と出力結果を示す。

図 2.28

データファイルの構成- 19 -

図 2.29

入力画面例

図 2.30

出力画面例

図 2.30 の左列がチャンネル 1 の Fdata、右列がチャンネル 2 の Fdata である。

２．６．２ データ抽出
採取される Fdata は 2 チャンネルで 1024× 2=2048 個である。ニューラルネット
ワークの入力層数が 50 のため、2048 のデータから、いかにして 50 個の情報を得るかについて検討する。
ここで、2 種類の処理方法を提案する。チャンネル 1，2 が存在するために、チャンネル 1 つに対して、SLAB1〜25、SLAB26〜50 の各 25 ずつの入力を行う。まず、
1 つ目は商用周波数ノイズ(1〜60Hz)を避けるために、それぞれチャンネル 1，2 の60~1019 個目の Fdata を抽出する。そして、各チャンネルの総和を 24 等分し、それぞれの区間の和をとる。それぞれの区間の和を各チャンネルの総和で割った数値
24× 2=48 個を SLAB1〜24，SLAB26〜49 とする。SLAB25，SLAB50 には各チャ
ンネルの総和を適当な値である 30000 で割る。これは学習システムに対し、入力の- 20 -

ダイナミックレンジを合わせるためである。この手法を手法 1 と呼ぶこととする。
2 つ目は前者で行った Fdata60〜1019 個目のデータの範囲を半分に狭め、60〜515
個目対し、同様の処理を行う。これを手法 2 と呼ぶこととする。
上記の 2 手法以外に各チャンネルの Fdata1〜25 の各点であるデータを SLAB1〜
25 と設定する場合も良好な結果が得られることがわかった。しかしながら、この手法を採用しない理由は 60Hz 以下はノイズが混入しやすく、さらに、周波数のデータ
は 10Hz や 20Hｚの範囲での振幅の変化が大きく、そのために Fdata の 1 周波数（１つの数字）をそのまま使う場合、データごとの誤差に弱い検出になるからである。

２．７ 登録・認識部
登録・認識部
２．７．１ ニューラルネットワーク
ニューラルネットワークとは人間の脳の情報処理を工学的にモデル化したネット
ワークのことである。
本節では、学習システムに用いている階層型ニューラルネットワークについて解説する。
ニューラルネットワークの計算メカニズムには、大きく分類するとして 2 つあり、一方は階層的型ネットワーク（層状結合ネットワーク）で、もう一方は相互結合のある非階層的なネットワークである（１２）。

図 2.31

階層型ネットワーク- 21 -

本研究で用いた計算アルゴリズムは中間層が 1 つからなる 3 層の階層型ネットワークである。図 2.31 の丸印で表されたのがニューロンで、ネットワークのノードにあたる処理要素で、多入力、一出力の素子である。
各ニューロンは、入力層、中間層、出力層のそれぞれ独立した層に配置する。各層のニューロンはそれより 1 つ前の層のニューロンから入力を受ける。各層間では、すべてのニューロンが結びついている。

＜情報の伝達＞
ニューラルネットワークにおいて、入力層に与えられた入力パターンが、いかにして伝達され、出力層から出力されるかについて説明する。

図 2.32

情報の伝達

図 2.32 で、s1，s2，s3 はそれぞれ入力層の第 1，2，3 ユニット、a1，a2 はそれ
ぞれ中間層の第１,２ユニット、r1，r2，r3 はそれぞれ出力層の第 1，2，3 ユニットである。また、S1，S2，S3 は入力層への入力値（スラブ値）、R1，R2，R3 は出力層の出力値を表す。
入力層の第 I ユニットから中間層の第 j ユニットへの結合の重み（ウェイト）をWij とする。ここで、ウェイトとはその結合が結ぶユニット間の相互作用の強さを表す。
中間層と出力層の間の情報伝達方法も全く同じであるため、入力層と中間層を例にとり説明する。

- 22 -

<ユニットの入力値>
ユニットの入力値>
入力層の第 I ユニットの出力値を Si とすると（入力層のユニットは入力値と出力値が同じ）、中間層の第 j ユニットの入力の総和 Ij はつぎのようにして求められる。

I = W S +W S +W S
I = W S +W S +W S
1

11

1

21

2

31

3

2

12

1

22

2

32

3

(2.6)

となり一般的に、I =∑ W S
j

ij

(2.7)

i

i

と表すことができる。

<ユニットの出力値>
ユニットの出力値>
中間層の第 j ユニットの入力の総和を Ij とすると、中間層の第 j ユニットの出力値
Oj はつぎのようにして求めることができる。

O = f (I )jj(f は入出力関数)(2.8)

このようにして、入力層の各ユニットの出力値と、入力層の中間層の各ユニット間のウェイトから中間層の各ユニットの出力値を得ることができる。
同様にして、中間層の各ユニットの出力値と、中間層と出力層の各ユニット間のウェイトから出力層の各ユニットの出力値を得ることができる。

- 23 -

＜中間層・出力層の入出力関数＞＜中間層・出力層の入出力関数＞
中間層・出力層の各ユニットの入出力関数としてはシグモイド関数
f ( x) =1
 − x +θ 
1 + exp

 T 

(2.9)

を使用する。(2.9)式において、x は各ユニットへの入力値で、f(x)はそのユニットの出力値です。T はネットワークの温度と呼ばれる正の数で、T が大きくなるほどグラ
フはなだらかになり、θはユニット単位のしきい値を表す。
ここでシグモイド関数のグラフを示す。（θ=0）
T は後述する総合誤差に比例して、1.3 から 0.7 まで変化させる。この操作は学習プログラムが自動的に行う。

図 2.33

シグモイド関数＜学習アルゴリズム＞
先に述べた情報の伝達の項で、入力層に与えられた入力パターンが中間層を経て変換され、出力層から出力パターンが得られることを示したが、入力パターンに対して期待する出力パターンを得るためには、各ユニット間のウェイトを適切な値にする必要がある。本項ではこのウェイトを適切な値に設定するための学習アルゴリズムにつ- 24 -

いて述べる。
学習方法としては、誤差逆伝搬（ＢＰ：Error Back Propagation）アルゴリズムを使用する。具体的には、いくつかの入力パターンの例（学習データ）を与え、その時の出力パターンと期待する出力パターン（教師値）との誤差が減少するようにウェイ
トを修正する。
ある入力パターンを与えた時の出力層の第 j ユニットの出力を Oj、このときの出力層の第 j ユニットの期待値（教師値）を Tj とすると、第 j ユニットの誤差 Ej はつぎのようにして求める。

E = 2 (T − O )1jj(2.10)

2j

したがって、1 つの学習パターン P における出力層の誤差 Ep はつぎのようにして求める。

E = 2 ∑ (T − O )1pj(2.11)2jj

ここで、全学習パターンの誤差の総和を E とし、これを総合誤差と呼ぶこととする。
E = ∑Ep =
p

(

)

1
−Oj 2
∑∑
T
j
2 p j

(2.12)

上記の総合誤差 E が最小になるように各ユニット間のウェイトを修正する。
修正の方法としては最急降下法を用いる。具体的には、各学習パターンごとに、各ユニットの誤差 Ej が最小となる方向へ微小な変更を加えていく。
t 回目の学習における k-1 層の第 I ユニットから k 層の第 j ユニットへのウェイト
Wij の修正量Δwij(k-1,k)(t)は(2.13)式のようにして求める。

∆Wijk−1,k (t) = −εδkjOkj−1 +α∆Wijk−1,k (t −1) + β∆Wijk−1,k (t −2)(2.13)

上式において”ε”は学習定数、”α”は慣性定数、”β”は振動定数である。この式を改良型ＢＰ法と呼ぶこととする。
また、”δj(k)”は k 層の第 j ユニットの一般化誤差で、k 層が出力層の場合と中間層の場合によって算出方法が異なる。以下に一般化誤差の算出方法を示す。
k 層が出力層の場合、(Ij(k)は k 層の第 j ユニットの入力総和)- 25 -

δ kj = (Tj − Okj ) f ' (I kj )(2.14)

k 層が中間層の場合、（ただし、m は出力層のユニット番号）δ kj=  ∑ W jmk , k −1δ mk +1  f ' (I kj ) m
(2.15)＜学習パラメータ＞
前項で示した(2.13)式の“ε”の項は大きな値を設定するとウェイトの修正量が大きくなり、学習は早くなるが、限度をこえると逆に学習が収束しなくなる。総合誤差が上下するときは学習定数を小さくし、誤差の減少速度が小さいときは学習定数を大きくする必要がある。この操作は学習プログラムが自動的に行うため、ユーザーは学習開始時の学習定数の初期値を後述する環境設定ファイルで設定する必要がある。
“α”の項は総合誤差の振動を減らし、学習の収束を加速させる働きをする。“β”の項は総合誤差を上下に振動させ、極小値から脱出させる働きをする。

２．７．２ 学習システム
この学習システムは後述に示すプログラムを集合体であるバッチファイルである。
各プログラムの動作の説明を行い、学習システム全体の流れを説明する。

２．７．３ 環境設定ファイル
ネットワークの構成はこの環境設定ファイルで設定する。設定項目は入力層の細胞数、中間層の数、中間層の細胞数、出力層の細胞数、データファイルのパターン数、
1 パターンのデータの個数、(2.13)式における学習定数、慣性定数、振動定数等を環境設定ファイル（テキスト形式）で決定する。

- 26 -

図 2.34

環境設定ファイル

２．７．４ データベース設定ファイル
データファイルのパス名をパターン番号順に 1 行に 1 ファイルずつデータベース
設定ファイル（テキスト形式）に記述する。

図 2.35

データベース設定ファイル

２．７．５ 学習データ抽出
ここでは環境設定ファイルで指定した 1 パターンの学習枚数分だけデータベース
設定ファイルに登録されたデータファイルの先頭から取り出し、学習データファイル（LDATA1，2）を作成する。

- 27 -

図 2.36

学習データ抽出画面

２．７．６ スラブ値ファイル作成
学習データファイルのスラブ値を取り出して、スラブファイルを作成する。スラブ
ファイル（SLAB1~50）の作成中の画面を図 2.37 に示す。

図 2.37

スラブファイル作成画面- 28 -

２．７．７ スラブファイルの並び替え
学習収束を早めるために、各パターンのスラブファイル（SLAB1〜50）を並び替
え、学習ファイル(LEARN.S)を作成する。学習ファイルと各スラブファイルの関係
は図 2.38 に示す。図中のｎは 1 パターンの学習枚数である。

図 2.38

学習ファイルと各スラブファイルの関係

２．７．８ 教師ファイル作成
環境設定ファイルで指定されたパターン数に従って教師ファイルを作成する。正解
ならば 1、不正解ならば 0 を教師する行列を作成する。
1 0


0
1



(2.16)

作成された行列はパターン数をｎとし、n× n 行列である。本研究の場合、手首が上の状態と下の状態の 2 パターンであるため、２× ２行列が作成される。

- 29 -

２．７．９ 学習
ニューロ学習を実行し、ウェイトファイルを作成する。学習プログラムは環境設定
ファイルの最終誤差判定値または学習回数のどちらかの条件を満たした時に終了する。図 2.39 中の左下は相互誤差を表し、右半分はそれぞれのパターンの出力ユニッ
ト値を表す。そのため、本研究では腕の上下の 2 パターンを学習するので、2 つの出力が表示される。

図 2.39学習画面

２．７．１０ 認識・評価
認識・評価
ウェイトファイルを用いてデータファイルを評価し、評価結果としてログファイルを出力する。
図 2.40 の評価実行時画面中の右半分は１行目がパターン１の反応値、２行目がパ
ターン２の反応値を表す。パターン 1 は手首を上に上げた時のデータ、パターン 2
は手首を下に下げた時のデータを示す。したがって、図 2.40 の評価中のデータはパ
ターン２に反応していることから、手首を下げたデータであると判明する。

- 30 -

図 2.40

評価実行時画面

図 2.41

ログファイル- 31 -

ログファイル中の小数値を出力する 2 列は左列から順にパターン 1 の反応値、パターン 2 の反応値を表す。尚、これらの値の最大値は 1 である。これより、評価データは手首を上にあげたデータであると判定できる。

- 32 -

３． 実験
ここでは著者が行ったシミュレーション実験について述べる。図のように被験者は右腕の脇をしめ、手を軽く握り、腕を 90 度に曲げた状態で手首を上下させ、筋電信号を採取する。

３．１ 電極の最適位置
電極の最適ポイントは被験者 12 人の筋活動電位を測定し、筋電信号出力プログラ
ムより出力された各人の Tdata と Fdata から、最適ポイントを推定する。それによると、個人差はみられるものの、数人から腕を垂直に曲げた状態で上腕二頭筋から8cm のポイントが最も良好な筋活動電位が採取できた。その最適ポイントを C と呼ぶこととする。
さらに、最適ポイントの周囲 1.5ｃｍについても同様にデータ採取を行う。図 3.2のように手側を A、体側を B と記述する。

図 3.1

データ採取位置- 33 -

３．２ データ採取
実験データは 5 人から採取する。

３．２．１ ノイズ対策
まず、データ採取の際して、推測されるノイズを挙げる。
(1) 電極の接触抵抗(2) 配線での電磁誘導
これらを解決するために著者が行った対策は、(1) 電解クリームを十分につけ、医療用テープで電極を強く押さえつける。
(2) 電極を束ね、アルミホイルでシールドする。この他に行ったノイズ対策としては、(3) 机に電磁ノイズが混入している場合が考えられるため、電極の配線をリング状に束ねたものを空中に浮かせ、地面に触れないようにする。
(4) 電極を束ねたリング状の配線はラジオのアンテナに相当するため、様々な方向へ配線を向ける。
(5) リング状の配線に手で直接触れる。

３．２．２ 実験方法
本項では提案手法による筋電信号の学習と未学習データによるシミュレーション
実験を学習システムにて実施する。その実験方法について述べる
データ採取位置（A，B，C）の 3 箇所において、2.6.2 項で述べた手法 1，2 の実験を行う。さらに、学習データを全て同一人物のデータとし、他人のデータを評価したもの、全て異なる人物を学習データとし、残りの本人のデータを評価したものについての計 12 種類の実験を行う。
被験者 5 人（全員男子大学生、健常者）に対し、同じ動作を 1 人、1 箇所につき 5個ずつ採取する。したがって、評価個数（データファイル 1）は 5× 5=25 個となる。

- 34 -

３．２．３ 実験条件
実験条件を表 3.2 に示す。
表 3.2

実験条件

チャンネル数
データ数
入力層細胞数中間層数
中間層細胞数出力層細胞数
学習定数
慣性定数
振動定数
学習パターン数
１パターンの提示個数
評価個数
最終誤差判定値
最大学習回数学習アルゴリズム

2
2048
50
1
50
2
0.05
0.95
-0.1
2
3
25
0.000120000
改良型BP法(2.12)式

３．３ 実験結果＜手法１＜手法１で学習データ 5 枚が全て同一人物である場合＞
まず、データ採取位置を変化させ、手首を上下させた結果について述べる。また、グラフ中のチャンネル 1，2 をチャンネル 1，2 と表記している。

- 35 -

１）

データ採取位置 A に電極を配置する

手首を上に上げた状態のデータファイルの評価結果を(3.1)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）

(3.1)

1

学習回数：426 回

0.8

表 3.3

チャンネル毎の反応値

チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

10.986653
0.112370

ch1の反応値(SLAB1～25)
ch2の反応値(SLAB26～50)

0.6
0.4
0.2
0
1

表 3.4

4

7

10 13 16 19 22 25

手首を上に上げた時の評価結果

表 3.4 は SLAB 1〜25 がチャンネル１に反応したグラフと、SLAB 26〜50 がチャンネル 2 に反応したグラフを 1 つにしたものである。縦軸が反応値、横軸がスラブ番号を表す。●印は SLAB 1〜25 におけるチャンネル 1 の反応値、■印は SLAB 26〜50 におけるチャンネル 2 の反応値を表す。
表 3.4 はデータ採取位置 A に電極を配置し、手首を上に上げた状態の出力結果を示す。評価データは手首を上に上げた状態である。そのため、チャンネル 1 が高い反応を示し、チャンネル２については低い反応を示しているので、良好な結果であることがわかる。表 3.3 のグラフにおいて、それぞれのチャンネルの反応値は最大が 1 である。しかしながら、ニューラルネットワークは完全に正解であるという答えを出力することはないと考えられる。ここでの反応値 1 とは 0.9999991 以上を示す。

- 36 -つぎに、手首を下に下げた状態のデータファイルの評価結果を(3.2)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）

(3.2)

1

表 3.5 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

0.025762
010.973796

0.8
0.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7

10 13 16 19 22 25

表 3.6 手首を下に下げた時の評価結果
評価データは手首を下に下げた状態である。そのため、チャンネル 1 は低い反応を、
チャンネル 2 は高い反応を示していることから、良好な結果であることがわかる。
２）

データ採取位置 B に電極を配置する

まず、手首を上に上げた状態のデータファイルの評価結果を(3.3)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）

学習回数：375 回

1

表 3.7 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

(3.3)

1
0.987885
0.022073
0

0.8
0.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1 4 7 10 13 16 19 22 25
表 3.8 手首を上げた時の評価結果- 37 -つぎに、手首を下に下げた状態のデータファイルの評価結果を(3.4)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）

(3.4)

1
0.8

表 3.9 チャンネル毎の反応値0.6チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

0.40.034312
01
0.965577

ch1の反応値
ch2の反応値

0.2
0
1

4

7 10 13 16 19 22 25

表 3.10 手首を下げた時の評価結果
３）

データ採取位置 C に電極を配置する

まず、手首を上に上げた状態のデータファイルの評価結果を(3.5)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）

(3.5)

1

学習回数：574 回

0.8

表 3.11 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

10.977942
0.02174100.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7

10 13 16 19 22 25

表 3.12 手首を上げた時の評価結果- 38 -つぎに、手首を下に下げた状態のデータファイルの評価結果を(3.6)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）

(3.6)

1
0 .8

表 3.13 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

0.027013
01
0.973669

0 .6

ch1の 反 応 値
ch2の 反 応 値

0 .4
0 .2
0
1

4

7

10 13 16 19 22 25

表 3.14 手首を下げた時の評価結果
この実験結果から、データ採取位置の違いにより認識率の変化がみられないことが
わかる。

＜手法２
＜手法２で学習データ 5 枚が全て同一人物である場合＞
データ採取位置を変化させ、手首を上下させた結果について述べる。
４）

データ採取位置 A に電極を配置する

まず、手首を上に上げた状態のデータファイルの評価結果を(3.7)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）

(3.7)

1

学習回数：440 回
0.8

表 3.15 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

10.975493
0.02599200.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7

10 13 16 19 22 25

表 3.16 手首を上げた時の評価結果- 39 -つぎに、手首を下に下げた状態のデータファイルの評価結果を(3.8)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）

(3.8)

1
0.8

表 3.17 チャンネル毎の反応値 0.6
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

ch1の反応値
ch2の反応値

0.024113
0 0.4
10.975515 0.2
0
1

4

7

10

13 16 19 2225

表 3.18 手首を下げた時の評価結果
５）

データ採取位置 B に電極を配置する

まず、手首を上に上げた状態のデータファイルの評価結果を(3.9)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）

(3.9)

1

学習回数：351 回

0.8

表 3.19 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

10.976819
0.02397700.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7 10 13 16 19 22 25

表 3.20 手首を上げた時の評価結果- 40 -つぎに、手首を下に下げた状態のデータファイルの評価結果を(3.10)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）(3.10)

1

表 3.21 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

0.80.027833
010.971153

0.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7 10 13 16 19 22 25

表 3.22 手首を下げた時の評価結果
６）

データ採取位置 C に電極を配置する

まず、手首を上に上げた状態のデータファイルの評価結果を(3.11)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）(3.11)

1

学習回数：445 回
0.8

表 3.23 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

10.975313
0.02437100.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7 10 13 16 19 22 25

表 3.24 手首を上げた時の評価結果- 41 -つぎに、手首を下に下げた状態のデータファイルの評価結果を(3.12)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）

表 3.25 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

0.025157
01
0.975077(3.12)

1
0 .8
0 .6

ch1の 反 応 値
ch2の 反 応 値

0 .4
0 .2
0
1

4

7

10 13 16 19 22 25

表 3.26 手首を下げた時の評価結果
この結果より、Fdata の抽出の範囲、データ採取位置の違いによって認識率に変化がみられないことがわかる。そして、１人の学習データで他人の動作識別が可能である
ことがわかる。さらに、その認識率は良好であることがわかる。

＜手法１で学習データ 5 枚が全て異なる人物である場合＞
まず、データ採取位置を変化させ、手首を上下させた結果について述べる。
７）

データ採取位置 A に電極を配置する

手首を上に上げた状態のデータファイルの評価結果を(3.13)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）（3.13）

1

0.8

学習回数：417 回
表 3.27 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

10.971661
0.02762900.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

- 42 -

4 7 10 13 16 19 22 25

つぎに、手首を下に下げた状態のデータファイルの評価結果を(3.14)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）(3.14)

1

表 3.29 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

0.013192
01
0.975268

0.8
0.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7 10 13 16 19 22 25

表 3.30 手首を下げた時の評価結果
８）

データ採取位置 B に電極を配置する

手首を上に上げた状態のデータファイルの評価結果を(3.15)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）(3.15)

1

学習回数：337 回
0.8

表 3.31 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

0.999995
0.970992
0.028652
0.000007

0.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7 10 13 16 19 22 25

表 3.32 手首を上げた時の評価結果- 43 -つぎに、手首を下に下げた状態のデータファイルの評価結果を(3.16)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）(3.16)

1

表 3.33 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

0.80.024771
0.6
0
1 0.4
0.977011
0.2

ch1の反応値
ch2の反応値01

47 10 13 16 19 22 25

表 3.34 手首を下げた時の評価結果
９）

データ採取位置 C に電極を配置する

手首を上に上げた状態のデータファイルの評価結果を(3.17)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）(3.17)

1

学習回数：408 回

0.8

表 3.35 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

10.972868
0.02641500.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7 10 13 16 19 22 25

表 3.36 手首を上げた時の評価結果- 44 -つぎに、手首を下に下げた状態のデータファイルの評価結果を(3.18)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）(3.18)

1

表 3.37 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

0.022835010.9781410.8
0.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7

10 13 16 19 22 25

表 3.38 手首を下げた時の評価結果
この結果により、5 人の学習データでの動作識別が可能であることがわかる。さらに、その認識率は良好であることがわかる。

＜手法 2 で学習データ 5 枚が全て異なる人物である場合＞
まず、データ採取位置を変化させ、手首を上下させた結果について述べる。
１０） データ採取位置 A に電極を配置する
手首を上に上げた状態のデータファイルの評価結果を(3.19)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）(3.19)

1

0.8

学習回数：445 回

0.6

表 3.39 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

10.974102
0.0272130

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7

10 13 16 19 22 25

表 3.40 手首を上げた時の評価結果- 45 -つぎに、手首を下に下げた状態のデータファイルの評価結果を(3.20)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）(3.20)

10.8

表 3.41 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

0.60.029890 0.4
10.969489 0.2

ch1の反応値
ch2の反応値01

47 10 13 16 19 22 25

表 3.42 手首を下げた時の評価結果
１１） データ採取位置 B に電極を配置する
手首を上に上げた状態のデータファイルの評価結果を(3.21)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）(3.21)

1

学習回数：399 回
0.8

表 3.43 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

10.9701290.029960

0.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7 10 13 16 19 22 25

表 3.44 手首を上げた時の評価結果- 46 -つぎに、手首を下に下げた状態のデータファイルの評価結果を(3.22)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）(3.22)

10.8

表 3.45 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

0.02943010.971033

0.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7 10 13 16 19 22 25

表 3.46 手首を下げた時の評価結果
１２） データ採取位置 C に電極を配置する
手首を上に上げた状態のデータファイルの評価結果を(3.23)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）(3.23)

1

学習回数：512 回

0.8

表 3.47 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

10.972251
0.02846100.6

ch1の反応値
ch2の反応値

0.4
0.2
0
1

4

7 10 13 16 19 22 25

表 3.48 手首を上げた時の評価結果- 47 -つぎに、手首を下に下げた状態のデータファイルの評価結果を(3.24)式に示す。
認識率 =正しく反応した個数（25枚）
× 100 = 100%
評価個数（25枚）
1(3.24)

0.8
表 3.49 チャンネル毎の反応値
チャンネル1の最高反応値
チャンネル1の最低反応値
チャンネル2の最高反応値
チャンネル2の最低反応値

0.60.031172010.968592

ch1の反応値
ch2の反応値

0.4
0.2
0

1 4 7 10 13 16 19 22 25
表 3.50 手首を下げた時の評価結果
Fdata の抽出の範囲を狭めたが、認識結果には変化がみられなかった。
実験結果をまとめ、表 3.51、表 3.52 に示す。
表 3.51
採取位置
A
B
C

動作
上
下
上
下
上
下

表 3.52
採取位置
A
B
C

手法 1 の実験結果
学習データ人数
1人
5人
100%
100%
100%
100%
100%
100%
100%
100%
100%
100%
100%
100%

手法 2 の実験結果

動作
上
下
上
下
上
下

学習データ人数
1人
5人
100%
100%
100%
100%
100%
100%
100%
100%
100%
100%
100%
100%

- 48 -

表 3.4〜表 3.52 より採取位置の違いや Fdata の抽出範囲の違いにより、認識率の変化や反応値の大きな変化はみられなかった。また、学習データに 1 人のデータ、5人のデータを使った場合においても、認識率の変化や反応値の大きな変化はみられな
かった。そして、それぞれの動作に対し、その全てに正しい反応が得られ、その全ての反応値は高く、動作識別率も全て 100％であった。
全ての認識率が 100％であるため、どのような場合において認識率が低下するかを観測することができなかった。そのため、反応値で差異を明確にできるようデータ抽
出方法を考察することが今後の課題である。
この結果により、自分の動作をニューラルネットワークにより学習し、他人の動作を評価できることが示された。

- 49 -

４．まとめ
本研究は、腕の動作識別において被験者の随意運動に伴う生体信号である筋活動電位を検討した。そして、筋活動電位の登録、評価には階層型ニューラルネットワーク
を用い、認識システムとしての検証を行った。
実験結果により、手首の動作識別には提案した筋電パターン認識システムが有効であることを確認した。これにより手首での他の動作や手首以外の部位についても同様に動作識別が可能であることが期待できる。性別、年齢の違いによる識別率の調査、電極を乾式にし、波形が大きく観測することができなかった電極の手首へ移行についての検討を今後の課題とする。

- 50 -

５．謝辞
最後に本研究に御協力頂いた竹田史章教授、システム LSI(株)の山本様、グローリー工業(株)西蔭様に厚く御礼申し上げる。

- 51 -

６．参考文献
1) http://www2.freeweb.ne.jp/~tar4/tech/bluetooth.htm2) http://bme.ahs.kitasato-u.ac.jp:8080/docs/qrs/phy/index.html
3) http://www.kris.sfc.keio.ac.jp/grants/mori/99/doctor/report/3/mori_found6.htm
4) 三田勝己， 筋電図計測 ，BME, Vol.5, No.1, pp.33-40, 1991
5) 内田雅文，井出英人，横山修一， 筋電によるロボットアーム制御２ ，電気学会
誌，Vol.114-C, No.1, pp.269-270，1994
6) 栗林勝利，谷口隆雄，清水聖治，小江則禎， 前腕の筋活動電位のコマンド識別に関する研究 ，日本機会学会誌，pp.25-34, 1995
7) 福田修，辻敏夫，金子真， ニューラルネットを利用した筋電制御型ポインティン
グデバイス ，バイオメカニズム学術講演会，pp.281-284, 19988) 佐鹿博信， 動作分析と表面筋電図 ，総合リハ，Vol.18-5, pp.347-355, 1990
9) 坂巻佳壽美， 見てわかるディジタル信号処理 ，工業調査会，1998
10) http://mars.elcom.nitech.ac.jp/java-cai/signal/fft3.html
11) 竹田史章，大松繁，井上卓，尾波宰三， フーリエ変換を前処理とするニューラルネットワークによる紙幣識別 ，システム制御情報学会
論文，Vol.5, No.7, pp.265-273, 1992
12) 麻生英樹， ニューラルネットワーク情報処理 ，産業図書，1994
13) http://biking.taiiku.tsukuba.ac.jp/thesis/doguu/GR/GR.html
14) http://www.hip.atr.co.jp/patent/details/2557789.html
15) http://www01.u-page.so-net.ne.jp/db3/aseo/emg.htm16) 竹田史章，西蔭紀洋， 紙幣用ニューロテンプレートマッチング識別手法の開発 ，
電気学会誌，Vol.121-C, No.1, pp.196-205，2001
17) 竹田史章、大松繁、井上卓、尾波宰三、小西健一， ニューラルネットワークを用いた高速搬送紙幣の識別 ，電気学会論文 Vol.112-C, No.4, pp.249-258, 199218) http://jiten.nikkeibp.co.jp/cgibin/showic/~/showdata.cgi?tmpl=icd00_sh.tmpl&url=/icdic2000/0699_ni.html
19) 竹田史章，西蔭紀洋，内田久也，中原昌樹， ニューロテンプレートによるパターンマッチング識別手法の開発とその紙幣への適用 ，システム制御情報学会論文
Vol.112-C, No.4, pp.415-416, 2000
20) F.Takeda, M.Nakahara, Y.Ichiryu, H.Uchida, “Autonomic Neuro-Recognition
Board for Paper Currency”, SPAT2000 Workshop Proceeding, pp.85-90, 2000
21) B.Kermanshahi ニューラルネットワークの設計と応用 ，昭晃堂，199922) 長尾真， パターン情報処理 ，コロナ社，1983- 52 -

付録- 53 -

txt̲myolog1.vbp
・フォーム
Myo1.frm
・標準モジュール
FFTKModule2.bas
Vbadlib.bas
Myo1.frm'変数の定義Option Explicit'AD 変換用変数
Private Type ADCPARAM
MyCardType As Integer
2:REX5054B）
MyIOBase As Integer
MyIrqNo As Integer
SampTime As Integer
TimeUnitNo As Integer
AdcChannel As Integer
NCount As Long
数
MaxSampDataNum As Long
Pdata() As Integer
End Type
Private Adc As ADCPARAM
Private OleHandle As Long
Private AdCount As Long
Private DllMem As Long
り出したﾃﾞｰﾀを格納するｱﾄﾞﾚｽ
Private Sequence(4) As Integer'グラフ表示用定数および変数
Private Const YDIV_NUM = 10

' ｶｰﾄﾞ型式（1:REX5054U，' ｻﾝﾌﾟﾘﾝｸﾞ間隔' 時間単位' 変換ﾁｬﾝﾈﾙ数' 1 ﾁｬﾝﾈﾙ当たりの変換ﾃﾞｰﾀ個' 全 A/D 変換ﾃﾞｰﾀ個数' 変換ﾃﾞｰﾀ格納先ﾒﾓﾘｰ先頭ｱﾄﾞﾚｽ' MBOX.OCX ﾊﾝﾄﾞﾙ' Ad 変換ﾃﾞｰﾀ個数' ﾄﾞﾗｲﾊﾞが FIFO から取Private Const XDIV_NUM = 10
Private Xdiv As Double
Private Ydiv As Double
Private XWidth As Single
論理座標最大値
Private Yheight As Single
論理座標最大値
Private px As Single
Private py As Single
Private ChColor(6) As Long
Private CurrentWind As Integer' x 座標の目盛(sec/div)' y 座標の目盛(V/div)' 仮想ｳｨﾝﾄﾞｳにおけるｸﾞﾗﾌ' 仮想ｳｨﾝﾄﾞｳにおけるｸﾞﾗﾌ' 各ﾁｬﾝﾈﾙ描画色のｶﾗｰ番号'データ保管用グローバル変数
Private Ttime(8192) As Double, Ffreq(4096) As Double
Private Tdata(1 To 2, 8192) As Double, Fdata(1 To 2, 4096) As
DoublePrivate Pdata(1 To 2, 4096) As Double
Private Ave(4096) As Double
Private fftScale As Integer
Private Sub Form_Load()
Dim SlotNo As Integer
Dim i As Integer' 開始ﾎﾞﾀﾝを無効にする
IDB_START.Enabled = False
cmdLoad.Enabled = False
cmdSave.Enabled = False
cmdReDraw.Enabled = False
cmdFFT.Enabled = False' ｽﾛｯﾄ 0 またはｽﾛｯﾄ 1 に挿入されている自分のｶｰﾄﾞのﾘｿｰｽ情報を取得する
For SlotNo = 0 To 3 Step 1- 54 -

If
AdGetCardResource(hwnd,
SlotNo,Adc.MyCardType,
Adc.MyIOBase, Adc.MyIrqNo) = 0 Then
Exit ForEnd IfNext SlotNo
Debug.Print "Card Check", hwnd, SlotNo, Adc.MyCardType,
Adc.MyIOBase, Adc.MyIrqNo' ｶｰﾄﾞが挿入されていない場合のｴﾗｰ処理
If SlotNo >= 4 ThenIDC_STATUS.Caption = "REX-5054U/B AD ｶｰﾄﾞ検出ｴﾗｰ"
Exit SubEnd IfSelect Case Adc.MyCardType
Case REX5054U
IDC_STATUS.Caption = "REX-5054U 正常検出 I/O ﾍﾞｰｽ:0x" +Hex(Adc.MyIOBase) + " IRQ 番号:" + Str(Adc.MyIrqNo)'IDS_YRANGE.Caption = "0-2.5V"
Case REX5054B
IDC_STATUS.Caption = "REX-5054B 正常検出 I/O ﾍﾞｰｽ:0x" +Hex(Adc.MyIOBase) + " IRQ 番号:" + Str(Adc.MyIrqNo)'IDS_YRANGE = "±5V"
End Select'SamplingTime の初期値を 50usec(20kS)に設定
IDE_SAMPTIME.Text = 50
'SamplingTime の単位選択ｺﾝﾎﾞﾘｽﾄ作成
IDCB_TIMEUNIT.AddItem "sec"
IDCB_TIMEUNIT.AddItem "msec"
IDCB_TIMEUNIT.AddItem "usec"' ｺﾝﾎﾞﾘｽﾄの初期設定(usec)
IDCB_TIMEUNIT.ListIndex = 2' AD 変換ﾁｬﾝﾈﾙ数の初期値を 2 に設定

IDE_CHAN.Text = "2"' AD 変換個数の初期値を 2048 に設定' (計測時間約 100m 秒)
IDE_SAMPCOUNT.Text = "2048"
CurrentWind = 0'ﾋﾟｸﾁｬﾎﾞｯｸｽの初期値の取得、設定
PicGraph(0).ForeColor = QBColor(1)PicGraph(1).ForeColor = QBColor(1)' 前景色を設定' 前景色を設定' 各チャンネルグラフ描画色設定
ChColor(0) = 15
' 明るい白ChColor(1) = 12
' 明るい赤ChColor(2) = 14
' 明るい黄ChColor(3) = 9' 明るい青ChColor(4) = 10
' 明るい緑ChColor(5) = 11
' 明るいシアン
ChColor(6) = 13
' 明るいマゼンタ
IDC_STATUS.Caption = "サンプリング間隔などを決定してくだ
さい"
Debug.Print "Form Module loaded"
End Sub
Private Sub cmdDet_Click()
Dim IXdiv As Integer, IYdiv As String
Dim IFrange As Integer, IFdiv As Double
Dim RetCode As Long
cmdDet.Enabled = False
IDE_SAMPTIME.Enabled = False
IDCB_TIMEUNIT.Enabled = False
IDE_CHAN.Enabled = False
IDE_SAMPCOUNT.Enabled = False- 55 -

' AD 変換時間
Adc.SampTime = Val(IDE_SAMPTIME.Text)' ｻﾝﾌﾟﾘﾝｸﾞ時間
Adc.TimeUnitNo = Val(IDCB_TIMEUNIT.ListIndex)' AD 変換ﾁｬﾝﾈﾙ数
Adc.AdcChannel = Val(IDE_CHAN.Text)' AD 変換個数
Adc.NCount = Val(IDE_SAMPCOUNT.Text)'ｸﾞﾗﾌの目盛(Xdiv,Ydiv)を設定
Xdiv = (Adc.NCount * Adc.SampTime / XDIV_NUM / 1.024) *10# ^ (-3# * Adc.TimeUnitNo)
Select Case Adc.MyCardType
Case REX5054B' ±5Volt
Ydiv = 10# / YDIV_NUM
Case REX5054U' 0-2.5Volt
Ydiv = 2.5 / YDIV_NUM
End Select' ｽｹｰﾙの単位表示
If Xdiv < 10# ^ -3# Then
IXdiv = (Xdiv * 10# ^ 6#)
IDS_XDIV.Caption = Str(IXdiv) + "μ秒/div"
ElseIf Xdiv < 10# ^ 0# Then
IXdiv = (Xdiv * 10# ^ 3#)
IDS_XDIV.Caption = Str(IXdiv) + "m 秒/div"
Else
IXdiv = Xdiv
IDS_XDIV.Caption = Str(IXdiv) + "秒/div"
End If
IYdiv = " " + Format(Ydiv, "0.00") + "V/div"
IDS_YDIV.Caption = IYdiv
IFrange = 1# / (2# * Adc.SampTime * 10# ^ (-3# *Adc.TimeUnitNo))
If IFrange > 1000# Then
IFrange = IFrange / 1000
IDS_FRANGE.Caption = " 0〜" + Str(IFrange) + "kHz"ElseIf IFrange > 1# ThenIDS_FRANGE.Caption = " 0〜" + Str(IFrange) + "Hz"End IfIFdiv = (1# / (Adc.NCount * Adc.SampTime * 10# ^ (-3# *Adc.TimeUnitNo)))IDS_FDIV.Caption = "" + Format(IFdiv, "0.000") + "Hz"TFinp'=========================================
RetCode=AdSetParam(hwnd,
Adc.MyCardType,INTHISPEED_MODE, Adc.MyIOBase, Adc.MyIrqNo)
Debug.Print"SetParam",
hwnd,
Adc.MyCardType,INTHISPEED_MODE, Adc.MyIOBase, Adc.MyIrqNo, RetCode
If RetCode <> 0 ThenIDC_STATUS.Caption = "AD ｶｰ ﾄ ﾞ ﾊﾟﾗ ﾒ ｰﾀ 設定ｴﾗ ｰ [CODE:" +Str(RetCode) + "]"Exit SubEnd If'=========================================
Sequence(1) = 0: Sequence(2) = 1: Sequence(3) = 2: Sequence(4)=3' 変換ﾁｬﾝﾈﾙ数設定
RetCode = AdSetChannel(Adc.AdcChannel, Sequence(1))
Debug.Print "ADSetChannel", Adc.AdcChannel, Sequence(1),RetCodeIf RetCode <> Adc.AdcChannel ThenIDC_STATUS.Caption = "AD 変 換 ﾁ ｬ ﾝ ﾈ ﾙ 設 定 誤 り [CODE:" +- 56 -

Str(RetCode) + "]"Exit SubEnd IfvbCritical, "エラー"
Exit SubEnd If'================================================' 通常のﾓｰﾄﾞで開始終了
AdSetTrigger TRIGGER_DISABLE, PULSE_RISING'Debug.Print "OleHandle", OleHandle'================================================'================================================' ｻﾝﾌﾟﾘﾝｸﾞ間隔設定
RetCode = AdSetFreq(hwnd, Adc.SampTime, Adc.TimeUnitNo)
Debug.Print"ADSetFreq",
hwnd,
Adc.SampTime,
Adc.TimeUnitNo, RetCode
If RetCode <> 0 ThenIDC_STATUS.Caption = " ｻ ﾝ ﾌ ﾟ ﾘ ﾝ ｸ ﾞ 間 隔 設 定 誤 り [CODE:" +Str(RetCode) + "]"Exit SubEnd If'=========================================' VB ｱﾌﾟﾘｹｰｼｮﾝ側でﾃﾞｰﾀを保管するための配列を確保
Adc.MaxSampDataNum = Adc.AdcChannel * Adc.NCount
ReDim Adc.Pdata(Adc.MaxSampDataNum) As Integer' AD ﾃﾞｰﾀ格納ﾒﾓﾘｰをｱﾛｹｰﾄ(1 ﾁｬﾝﾈﾙ当たりの変換個数を指定する)
DllMem = AdAllocDataMem(hwnd, Adc.NCount)
If DllMem = 0 ThenIDC_STATUS.Caption = "変換ﾃﾞｰﾀ格納用ﾒﾓﾘﾌﾞﾛｯｸｱﾛｹｰｼｮﾝｴﾗｰ"
Exit SubEnd If'================================================'OLE のウィンドウハンドル取得
OleHandle = MBOX1.GetMboxWnd()
If (OleHandle = 0) Then
MsgBox "OLE のハンドルが取得できません。", vbOKOnly +IDB_START.Enabled = True
cmdLoad.Enabled = True
cmdSave.Enabled = False
cmdReDraw.Enabled = False
cmdFFT.Enabled = False
IDC_STATUS.Caption = ""End Sub
Private Sub IDB_START_Click()'ﾎﾟｰﾘﾝｸﾞﾓｰﾄﾞ A/D 変換実行
AdStartPolModeThread OleHandle
End Sub
Private Sub IDQUIT_Click()'AD ﾃﾞｰﾀ格納ﾒﾓﾘｰ開放
AdFreeDataMem
Unload Me
End Sub
Private Sub MBOX1_OnMsgPost(ByVal wParam As Integer,
ByVal lParam As Long)
Dim AdcStat As Integer' AD 変換ｽﾃｰﾀｽ
Dim ChNo As Integer' CH 番号変数
Dim DataNo As Long
Dim i As Long' lParam -> AD 変換ﾃﾞｰﾀｶｳﾝﾄ数- 57 -

AdCount = lParam' wParam -> AD 変換開始終了ｺｰﾄﾞ
AdcStat = wParam

Case AD_MODE_OVRUN:
IDC_STATUS.Caption = "FIFO ｵｰﾊﾞｰﾗﾝ停止"
End SelectEnd Sub

Debug.Print "StartEndCode", AdcStat
Select Case AdcStat
Case AD_MODE_RUN
IDC_STATUS.Caption = "変換開始..."Case AD_MODE_TRGRUN
IDC_STATUS.Caption = "ﾄﾘｶﾞｰ変換開始"
Case AD_MODE_STOP
IDC_STATUS.Caption = "指定個数終了"' ﾄﾞﾗｲﾊﾞがｾｯﾄした変換ﾃﾞｰﾀを自分のﾒﾓﾘへ転送保管します' 1 個の変換ﾃﾞｰﾀは 2 ﾊﾞｲﾄですので転送先のｱﾄﾞﾚｽに注意して下さい
VbMemCopy Adc.Pdata(0), DllMem, AdCount * 2' 各 CH のﾃﾞｰﾀを電圧値に変換する
For ChNo = 1 To Adc.AdcChannel
For i = 0 To Adc.NCount - 1
DataNo = i * Adc.AdcChannel + ChNo - 1'Tdata(ChNo, I) = (CLng(Adc.pData(DataNo) And &H1FFF) * 8)
/ CLng(32768) * CLng(10) - CLng(5)Tdata(ChNo, i) = CLng(Adc.Pdata(DataNo) And &H1FFF) /409.6 - 5#
Next iNext ChNo
PlotTData' グラフ描画

cmdFFT.Enabled = True
Case AD_MODE_PRESTOP:
IDC_STATUS.Caption = "ﾄﾘｶﾞｰ終了"

Private Sub cmdFFT_Click()Dim i As Integer
For i = 1 To Adc.AdcChannel
F_FFT Tdata(), Fdata(), Pdata(), i, CInt(Adc.NCount), 0
Next i
PlotFData
cmdSave.Enabled = True
cmdReDraw.Enabled = True
End Sub
Private Sub cmdSave_Click()Dim i As Integer, J As Integer
Dim Fnum As Integer
Dim Filename As String * 256
Dim Pos As String * 1
Dim TestNum As String * 3
Dim MType As String * 1
Dim A As String * 10, B As String * 10, D As String * 10, E As
String * 10, F As String * 10, G As String * 10, H As String * 10
If (ManName.Text = "" Or PosInitial.Text = "") ThenIDC_STATUS.Caption = "ファイルが生成できません"
Exit SubEnd IfIf (TestNo.Text = "" Or MoveType.Text = "") ThenIDC_STATUS.Caption = "ファイルが生成できません"
Exit SubEnd If- 58 -

Pos = PosInitial.Text
TestNum = TestNo.Text
MType = MoveType.Text
Filename = ManName.Text + Pos + TestNum + MType + ".txt"
Filename = FilePath.Text + "¥" + Filename
Debug.Print "save file = " + Filename' ﾌｧｲﾙを開く
Fnum = FreeFile()Open Filename For Binary As Fnum
'for ループ 2048 回
For i = 0 To Adc.NCount - 1't_No の記述
A = Str(Ttime(i))
Put #Fnum, , A
Put #Fnum, , ""'for ループ 2 回 tch1,tch2 の記述
For J = 1 To Adc.AdcChannel
B = Str(Tdata(J, i))
Put #Fnum, , B
Put #Fnum, , ""Next J

E = Str(Fdata(J, i + 1))
Put #Fnum, , E
Put #Fnum, , ""Next J'fch2 の記述
F = Str(Fdata(Adc.AdcChannel, i + 1))
Put #Fnum, , F
Put #Fnum, , ""Put #Fnum, , vbCrLf'i が 1025 以上の時の処理(f_No,fch1,fch2 を全て"0"にする)
Else'for ループ 2 回 f_No,fch1 に"0"を記述
For J = 0 To Adc.AdcChannel - 1
G = Str(0)Put #Fnum, , G
Put #Fnum, , ""Next J'+1 回 fch2 (計 2+1 回)"0"を記述
H = Str(0)Put #Fnum, , H
Put #Fnum, , vbCrLf
End IfNext i'i が 1024 回以下なら fdata も記述
If i < Adc.NCount / 2 Then
'f_No の記述
D = Str(Ffreq(i))
Put #Fnum, , D
Put #Fnum, , ""'for ループ 1 回 fch1 の記述
For J = 1 To Adc.AdcChannel - 1

Close #Fnum
IDC_STATUS.Caption = "saved " + Filename
End Sub
Private Sub cmdload_Click()Dim i As Integer, J As Integer
Dim Fnum As Integer, dammy As String
Dim Filename As String * 256- 59 -

Dim Pos As String * 1
Dim TestNum As String * 3
Dim MType As String * 1
If (ManName.Text = "" Or PosInitial.Text = "") ThenIDC_STATUS.Caption = "ファイルが生成できません"
Exit SubEnd IfIf (TestNo.Text = "" Or MoveType.Text = "") ThenIDC_STATUS.Caption = "ファイルが生成できません"
Exit SubEnd If
Pos = PosInitial.Text
TestNum = TestNo.Text
MType = MoveType.Text
Filename = ManName.Text + Pos + TestNum + MType + ".txt"
Filename = FilePath.Text + "¥" + Filename
Debug.Print "load file = " + Filename' ﾌｧｲﾙを開く
Fnum = FreeFile()Open Filename For Input As Fnum
For i = 0 To Adc.NCount - 1
Input #Fnum, dammy
Ttime(i) = CDbl(dammy)
For J = 1 To Adc.AdcChannel
Input #Fnum, dammy
Tdata(J, i) = CDbl(dammy)
Next J
If i < Adc.NCount / 2 Then
Input #Fnum, dammy
Ffreq(i) = CDbl(dammy)
For J = 1 To Adc.AdcChannel
Input #Fnum, dammy
Fdata(J, i + 1) = CDbl(dammy)

Next JElse
For J = 0 To Adc.AdcChannel
Input #Fnum, dammy
Next J
End IfNext i
Close #Fnum
cmdReDraw_Click
IDC_STATUS.Caption = "loaded " + Filename
cmdSave.Enabled = True
cmdReDraw.Enabled = True
cmdFFT.Enabled = True
End Sub
Public Sub PlotTData()'時間データのグラフ描画
Dim i As Long, ChNo As Integer
Dim Y As Double
CurrentWind = 0
DrawTScale'スケールの描画

PicGraph(CurrentWind).DrawStyle = 0
Debug.Print "adc.adcchannel = "; Adc.AdcChannel
For ChNo = 1 To Adc.AdcChannel
For i = 0 To Adc.NCount - 1 Step 1
Y = Tdata(ChNo, i) * py / Ydiv
If i = 0 Then
PicGraph(CurrentWind).PSet (i, Y), QBColor(ChColor(ChNo))
Else
PicGraph(CurrentWind).Line -(i, Y), QBColor(ChColor(ChNo))
End If- 60 -

Next iNext ChNo

Dim i As Long, ChNo As Integer
Dim Y As Double, Fdiv As Double
Dim max(1) As Double, min(1) As Double
Dim Ysig(2) As Double

End Sub
Public Sub DrawTScale()
Dim i As Single
Dim SS As Integer'時間データのスケール描画

SS = 40 'グラフの余白
Yheight = 1000
XWidth = Adc.NCount
PicGraph(CurrentWind).Cls
PicGraph(CurrentWind).Scale (0 - SS, Yheight / 2 + SS)-(XWidth+ SS, -Yheight / 2 - SS)
py = Yheight / YDIV_NUM
px = (Adc.NCount / 1.024) / XDIV_NUM
PicGraph(CurrentWind).DrawStyle = vbDot' ｘ軸方向の点線
For i = -YDIV_NUM / 2 To YDIV_NUM / 2 Step 1
PicGraph(CurrentWind).Line (0, i * py)-(XWidth, i * py),
QBColor(8)Next' ｙ軸方向の点線
For i = 0 To XDIV_NUM
PicGraph(CurrentWind).Line (i * px, Yheight / 2)-(i * px, Yheight / 2), QBColor(8)Next
PicGraph(CurrentWind).Line (XWidth, Yheight / 2)-(XWidth, Yheight / 2), QBColor(8)End Sub
Public Sub PlotFData()'FFT データのグラフ描画

Ysig(1) = 1#
Ysig(2) = -1#
CurrentWind = 1
DrawFScale
fftScale = 1'スケールの描画

PicGraph(CurrentWind).DrawStyle = 0
For ChNo = 1 To 2
'F_MaxMin Fdata(), ChNo, CInt(Adc.NCount), max(), min()'Fdiv = max(0)Fdiv = 1000
'Debug.Print "ch"; ChNo; " FFT Max : "; max(0)For i = 1 To Adc.NCount Step 1
Y = Fdata(ChNo, i) * Yheight / Fdiv
PicGraph(CurrentWind).Line ((i - 1) * 2 * fftScale, 0)-((i - 1) * 2 *fftScale, Y * Ysig(ChNo)), QBColor(ChColor(ChNo))
Next iNext ChNo
End Sub
Public Sub DrawFScale()
Dim i As Single
Dim SS As Integer'FFT データのスケール描画

SS = 40 'グラフの余白
Yheight = 1000
XWidth = Adc.NCount
PicGraph(CurrentWind).Cls
PicGraph(CurrentWind).Scale (0 - SS, Yheight + SS)-(XWidth +- 61 -

SS, -Yheight - SS)
py = Yheight / YDIV_NUM * 2
px = Adc.NCount / XDIV_NUM
PicGraph(CurrentWind).DrawStyle = vbDot' ｘ軸方向の点線
For i = -YDIV_NUM / 2 To YDIV_NUM / 2 Step 1
PicGraph(CurrentWind).Line (0, i * py)-(XWidth, i * py),
QBColor(8)Next' ｙ軸方向の点線
For i = 0 To XDIV_NUM
PicGraph(CurrentWind).Line (i * px, -Yheight)-(i * px, Yheight),
QBColor(8)Next
End Sub
Public Sub PlotPData()'位相データのグラフ描画
Dim i As Long, ChNo As Integer
Dim Y As Double, Pdiv As Double
Dim max(1) As Double, min(1) As Double
Dim Yoffset(2) As Double, Ysig(2) As Double
Dim CurrentDNum As Integer
Yoffset(1) = 0#
Yoffset(2) = 0#
Ysig(1) = 0
Ysig(2) = 1'ChNo = CurrentFFT
CurrentWind = 1
DrawPScale

PicGraph(CurrentWind).DrawStyle = 0
Pdiv = 2000# / (8# * Atn(1#))
For ChNo = 1 To 2
'Debug.Print "ch"; ChNo; " FFT Max : "; max(0)For i = 0 To Adc.NCount Step 1
Y = Pdata(ChNo, i) * Pdiv
PicGraph(CurrentWind).Line ((i * 2 + Ysig(ChNo)) * fftScale,Yoffset(ChNo))-((i * 2 + Ysig(ChNo)) * fftScale, Y +Yoffset(ChNo)), QBColor(ChColor(ChNo))
Next iNext ChNo'IDS_WLABEL(CurrentWind).Caption = " FFTdata / Phase" +Format(CurrentDNum, "00") + " / ALL"End Sub
Public Sub DrawPScale()
Dim i As Single
Dim SS As Integer'位相データのスケール描画

SS = 40 'グラフの余白
Yheight = 1000
XWidth = Adc.NCount
PicGraph(CurrentWind).Cls
PicGraph(CurrentWind).Scale (0 - SS, Yheight + SS)-(XWidth +SS, -Yheight - SS)
py = Yheight / YDIV_NUM * 2
px = Adc.NCount / XDIV_NUM
PicGraph(CurrentWind).DrawStyle = vbDot'スケールの描画' ｘ軸方向の点線
For i = -YDIV_NUM / 2 To YDIV_NUM / 2 Step 1
PicGraph(CurrentWind).Line (0, i * py)-(XWidth, i * py),
QBColor(8)- 62 -

Next

dt3 = 2 * pi * 100 / Adc.NCount' ｙ軸方向の点線
For i = 0 To XDIV_NUM
PicGraph(CurrentWind).Line (i * px, -Yheight)-(i * px, Yheight),
QBColor(8)Next

For i = 0 To Adc.NCount
Tdata(1, i) = Sin(dt1 * (i - 1)) + 0.3 * Sin(dt2 * (i - 1) + pi / 4) + 0.7* Sin(dt3 * (i - 1))
Tdata(2, i) = 0
Next iEnd Sub

PlotTData

Private Sub TFinp()
Dim i As Integer, J As Integer
Dim TInterval As Double, FInterval As Double
TInterval = Adc.SampTime * 10# ^ (-3# * Adc.TimeUnitNo)
FInterval = (1# / (Adc.NCount * TInterval))

End Sub

For i = 1 To Adc.NCount
Ttime(i) = i * TInterval
Next i
For i = 1 To Adc.NCount / 2
Ffreq(i) = i * FInterval
Next iEnd Sub
Private Sub cmdReDraw_Click()
PlotTData
PlotFData
End Sub
Private Sub Wave1_Click()Dim i As Integer, dt1 As Double, dt2 As Double, dt3 As Double
Dim pi As Double
pi = 4 * Atn(1)dt1 = 2 * pi * 4 / Adc.NCount
dt2 = 2 * pi * 56 / Adc.NCountFFTKModule2.bas
Public Sub F̲FFT(Tdata() As Double, Fdata() As Double, Pdata()
As Double, ̲CurrentNo As Integer, N As Integer, wind As Integer)'wind = 0 window なし'wind = 1 Hamming window'wind = 2 Hanning window'
Dim x(1, 8192) As Double 'x()は、FFT 変換用変数
F̲Window Tdata(), x(), CurrentNo, N, wind
fftCalc x(), CurrentNo, N, 1#
fftAbs Fdata(), Pdata(), x(), CurrentNo, N / 2
End Sub
Private Sub fftCalc(x() As Double, CurrentNo As Integer, N As
- 63 -

Integer, id As Double)' N
データ数、2 のべき乗であること 128,256,512,1024,...
' id= 1.0 FFT の計算' id=‑1.0 逆 FFT(RFT)の計算' 入力データ：x(0,N) 実数値データ:x(1,N) 虚数値データ x(2,N)' 出力 x(1,N)と x(2,N)に結果が入る (x(0,N)の内容は保持される)
Dim i As Integer, i0 As Integer, i1 As Integer, J As Integer
Dim ns As Integer, k As Integer, arg As Integer
Dim s As Double, c As Double, sc As Double, X1 As Double, y1
As Double
ns = N / 2: sc = 2 * 4 * Atn(1#) / N
For i = 0 To N: x(1, i) = 0: Next i
Do While ns >= 1
arg = 0For J = 1 To N Step 2 * ns
k = N / 4
c = Cos(sc * arg): s = Sin(id * sc * arg)
For i0 = J To J + ns ‑ 1
i1 = i0 + ns
X1 = x(0, i1) * c ‑ x(1, i1) * s: y1 = x(1, i1) * c + x(0, i1)* sx(0, i1) = x(0, i0) ‑ X1: x(1, i1) = x(1, i0) ‑ y1x(0, i0) = x(0, i0) + X1: x(1, i0) = x(1, i0) + y1
Next i0
Do While k <= arg
arg = arg ‑ k: k = k / 2
If k = 0 Then Exit Do
Looparg = arg + k
Next J
ns = ns / 2
Loop

If id < 0 Then
For i = 1 To N
x(0, i) = x(0, i) / N: x(1, i) = x(1, i) / N
Next iEnd If
J = 1
For i = 1 To N ‑ 1
If i <= J Then
X1 = x(0, i): x(0, i) = x(0, J): x(0, J) = X1
y1 = x(1, i): x(1, i) = x(1, J): x(1, J) = y1
End Ifk = N / 2
Do While k < J
J = J ‑ k: k = k / 2
Loop
J = J + k
Next iEnd Sub
Private Sub F̲Window(Tdata() As Double, x() As Double,
CurrentNo As Integer, ̲
N As Integer, win As Integer)
Dim i As Integer
Select Case win
Case 1
fftHamming Tdata(), x(), CurrentNo, N
Case 2
fftHanning Tdata(), x(), CurrentNo, N
Case ElseFor i = 1 To N
x(0, i) = Tdata(CurrentNo, i)x(1, i) = 0
Next i- 64 -

End SelectEnd Sub
Private Sub fftHanning(Tdata() As Double, x() As Double,
CurrentNo As Integer, N As Integer)
Dim i As Integer, sc As Double
sc = 2 * 4 * Atn(1#) / N
For i = 1 To N
x(0, i) = 0.5 * Tdata(CurrentNo, i) * (1# ‑ Cos(sc * (i ‑ 1)))x(1, i) = 0
Next iEnd Sub
Private Sub fftHamming(Tdata() As Double, x() As Double,
CurrentNo As Integer, N As Integer)
Dim i As Integer, sc As Double
sc = 2 * 4 * Atn(1#) / N
For i = 1 To N
x(0, i) = Tdata(CurrentNo, i) * (0.54 ‑ 0.46 * Cos(sc * (i ‑1)))x(1, i) = 0
Next iEnd Sub
Private Sub fftAbs(Fdata() As Double, Pdata() As Double, x()
As Double, CurrentNo As Integer, N As Integer)' z()=sqrt(x()^2+y()^2)
Dim i As Integer
For i = 1 To N
Fdata(CurrentNo, i) = Sqr(x(0, i) ^ 2 + x(1, i) ^ 2)
'Pdata(CurrentNo, i) = Atn(x(1, i) / x(0, i))
Next iEnd Sub

Public Sub F̲MaxMin(x() As Double, CurrentNo As Integer, N As
Integer, max() As Double, min() As Double)
Dim i As Integer
max(0) = x(CurrentNo, 1): min(0) = x(CurrentNo, 1)
max(1) = 0: min(1) = 0'Debug.Print "CurrentNo = "; Str(CurrentNo)
For i = 2 To N
If x(CurrentNo, i) > max(0) Thenmax(0) = x(CurrentNo, i)max(1) = i
End IfIf x(CurrentNo, i) < min(0) Thenmin(0) = x(CurrentNo, i)min(1) = i
End IfNext iEnd Sub

Vbadlib.bas
CurrentNo As Integer, N As Integer, wind As Integer)'wind = 0 window なし'wind = 1 Hamming window'wind = 2 Hanning window'
Dim x(1, 8192) As Double 'x()は、FFT 変換用変数- 65 -

F_Window Tdata(), x(), CurrentNo, N, wind
fftCalc x(), CurrentNo, N, 1#
fftAbs Fdata(), Pdata(), x(), CurrentNo, N / 2
End Sub
Private Sub fftCalc(x() As Double, CurrentNo As Integer, N As
Integer, id As Double)'N
データ数、2 のべき乗であること 128,256,512,1024,...
' id= 1.0 FFT の計算' id=-1.0 逆 FFT(RFT)の計算' 入力データ：x(0,N) 実数値データ:x(1,N) 虚数値データ x(2,N)' 出力 x(1,N)と x(2,N)に結果が入る (x(0,N)の内容は保持される)
Dim i As Integer, i0 As Integer, i1 As Integer, J As Integer
Dim ns As Integer, k As Integer, arg As Integer
Dim s As Double, c As Double, sc As Double, X1 As Double, y1 As
Doublens = N / 2: sc = 2 * 4 * Atn(1#) / N
For i = 0 To N: x(1, i) = 0: Next i
Do While ns >= 1
arg = 0For J = 1 To N Step 2 * ns
k=N/4
c = Cos(sc * arg): s = Sin(id * sc * arg)
For i0 = J To J + ns - 1
i1 = i0 + ns
X1 = x(0, i1) * c - x(1, i1) * s: y1 = x(1, i1) * c + x(0, i1) * sx(0, i1) = x(0, i0) - X1: x(1, i1) = x(1, i0) - y1x(0, i0) = x(0, i0) + X1: x(1, i0) = x(1, i0) + y1
Next i0
Do While k <= arg
arg = arg - k: k = k / 2
If k = 0 Then Exit Do
Looparg = arg + k

Next J
ns = ns / 2
Loop
If id < 0 Then
For i = 1 To N
x(0, i) = x(0, i) / N: x(1, i) = x(1, i) / N
Next iEnd If
J=1
For i = 1 To N - 1
If i <= J Then
X1 = x(0, i): x(0, i) = x(0, J): x(0, J) = X1
y1 = x(1, i): x(1, i) = x(1, J): x(1, J) = y1
End If
k=N/2
Do While k < J
J = J - k: k = k / 2
Loop
J=J+k
Next iEnd Sub
Private Sub F_Window(Tdata() As Double, x() As Double,
CurrentNo As Integer, _N As Integer, win As Integer)
Dim i As Integer
Select Case win
Case 1
fftHamming Tdata(), x(), CurrentNo, N
Case 2
fftHanning Tdata(), x(), CurrentNo, N
Case ElseFor i = 1 To N
x(0, i) = Tdata(CurrentNo, i)x(1, i) = 0
Next i- 66 -

End Selectmax(0) = x(CurrentNo, 1): min(0) = x(CurrentNo, 1)
max(1) = 0: min(1) = 0

End Sub
Private Sub fftHanning(Tdata() As Double, x() As Double,
CurrentNo As Integer, N As Integer)
Dim i As Integer, sc As Double
sc = 2 * 4 * Atn(1#) / N
For i = 1 To N
x(0, i) = 0.5 * Tdata(CurrentNo, i) * (1# - Cos(sc * (i - 1)))x(1, i) = 0
Next iEnd Sub
Private Sub fftHamming(Tdata() As Double, x() As Double,
CurrentNo As Integer, N As Integer)
Dim i As Integer, sc As Double
sc = 2 * 4 * Atn(1#) / N
For i = 1 To N
x(0, i) = Tdata(CurrentNo, i) * (0.54 - 0.46 * Cos(sc * (i - 1)))x(1, i) = 0
Next iEnd Sub
Private Sub fftAbs(Fdata() As Double, Pdata() As Double, x() As
Double, CurrentNo As Integer, N As Integer)' z()=sqrt(x()^2+y()^2)
Dim i As Integer
For i = 1 To N
Fdata(CurrentNo, i) = Sqr(x(0, i) ^ 2 + x(1, i) ^ 2)
'Pdata(CurrentNo, i) = Atn(x(1, i) / x(0, i))
Next iEnd Sub
Public Sub F_MaxMin(x() As Double, CurrentNo As Integer, N
As Integer, max() As Double, min() As Double)
Dim i As Integer'Debug.Print "CurrentNo = "; Str(CurrentNo)
For i = 2 To N
If x(CurrentNo, i) > max(0) Thenmax(0) = x(CurrentNo, i)max(1) = i
End IfIf x(CurrentNo, i) < min(0) Thenmin(0) = x(CurrentNo, i)min(1) = i
End IfNext iEnd Sub

手法１のプログラム (f_sum.c)#include<stdio.h>#include<stdlib.h>#include<conio.h>
unsigned longid1;
unsigned longid2;
unsigned char
id3;
unsigned char
id4;
unsigned char
id5;
unsigned char
id6;
unsigned int
id7;
unsigned char
id8;
unsigned char
id9;
- 67 -// 予約領域１// このデータ１枚分のサイズ// パターン番号
// 金種
// 方向
// 国情報// 通し番号
// 機種
// 号機

unsigned char
unsigned char
unsigned int
unsigned int
unsigned int
unsigned int
unsigned int
unsigned char
unsigned char
unsigned char
unsigned int
unsigned int
unsigned longunsigned longunsigned char
unsigned char
unsigned char
unsigned char
unsigned longunsigned long

id10;
id11;
id12;
id13;
id14;
id15;
id16;
id17;
id18;
id19;
id20;
id21;
id22;
id23;
id24;
id25;
id26;
id27;
id28;
id29;

// 種別（０：元画像 １：補正後）// センサ番号// 画像フレームのＸサイズ// 画像フレームのＹサイズ// センサ有効域チャネル番号（Ｌ）// センサ有効域チャネル番号（Ｈ）// 予約領域２// センサ分解能Ｘ// センサ分解能Ｙ// 予約領域３// 中心画素のＸ座標// 中心画素のＹ座標// 画像データのオフセット// 予約領域４// 格納されているスラブ種類数// １種類目のスラブ値のマスクｉｄ// １種類目のスラブ値の数// 予約領域５// スラブ値データのオフセット// 予約領域６(id1〜id29=ヘッダ)

float

id30;

// 画像データ４byte

int
float
float
FILE
char

i,j,n,k,l,m;
fch1[1024],fch2[1024],tch1[2048],tch2[2048];
t_No[2048],f_No[1024];*output_pt,*input_pt;
infile[20],outfile[20];

//

float

float
float
float
float
float

f1_sum_div=0.0,f2_sum_div=0.0;
f1_sum[60]={0.0},f2_sum[60]={0.0};
f1_in[60],f2_in[60];f1_input[30],f2_input[30];f1div,f2div;

f1_slab[1024],f2_slab[1024];

void main( void ){id1=0;// 予約領域１
id2=664; // このデータ１枚分のサイズ
id3=1;// パターン番号
id4=1;// 金種
id5=1;// 方向
id6=1;// 国情報id7=1;// 通し番号
id8=1;// 機種
id9=1;// 号機
id10=0;// 種別（０：元画像 １：補正後）
id11=0;// センサ番号
id12=20; // 画像フレームのＸサイズ
id13=20; // 画像フレームのＹサイズ
id14=4;// センサ有効域チャネル番号（Ｌ）
id15=201;// センサ有効域チャネル番号（Ｈ）
id16=0;// 予約領域２
id17=10; // センサ分解能Ｘ
id18=40; // センサ分解能Ｙ
id19=0;// 予約領域３
id20=0;// 中心画素のＸ座標
id21=0;// 中心画素のＹ座標
id22=64; // 画像データのオフセット
id23=0;// 予約領域４
id24=1;// 格納されているスラブ種類数
id25=1;// １種類目のスラブ値のマスクｉｄ
id26=50; // １種類目のスラブ値の数
id27=0;// 予約領域５
id28=464;// スラブ値データのオフセット
id29=0;// 予約領域６
id30=1;- 68 -// 画像データ

// ファイルオープン (出力）printf("出力ファイル名を入力＝");scanf("%s",&outfile);for(k=0;k<=24;k++){f1_sum_div=f1_sum_div+f1_sum[k];f2_sum_div=f2_sum_div+f2_sum[k];output_pt=fopen(outfile,"wb");

f1_in[k]= f1_sum[k] / f1_sum_div;
f2_in[k]= f2_sum[k] / f2_sum_div;}// REPEAT
printf("ファイル数の入力=");scanf("%d",&n);for(i=0; i<n;i++){// ファイルオープン (入力）
printf("入力ファイル名を入力＝");scanf("%s",&infile);
input_pt=fopen(infile,"ra");// ASCII ファイルのﾃﾞｰﾀをリード(No.,tch1(2048),tch2(2048),No.,
fch1(1024),fch2(1024))
for(j=60;j<=1019;j++){fscanf(input_pt,"%f%f%f%f%f%f",&t_No[j],&tch1[j],&tch2[j],&f_No[j],&fch1[j],&fch2[j]);}for(k=0;k<=24;k++){f1_sum[k]=0.0 ;f2_sum[k]=0.0;
for(l=1;l<=40;l++){f1_sum[k] += fch1[59+l+(40*k)];f2_sum[k] += fch2[59+l+(40*k)];}}for(k=0;k<=24;k++){f1_input[k]=f1_in[k+1];
f2_input[k]=f2_in[k+1];}
f1div=f1_sum_div / 30000;
f2div=f2_sum_div / 30000;
printf("¥n¥n¥n f1_input[1]= %f",f1_input[1]);printf("");
printf(" f2_input[1]= %f¥n",f2_input[1]);printf(" f1_input[2]= %f",f1_input[2]);printf("");
printf(" f2_input[2]= %f¥n",f2_input[2]);printf(" f1_sum[1]= %f",f1_sum[1]);printf(" f2_sum[1]= %f¥n",f2_sum[1]);printf(" f1div= %f",f1div);
printf("");
printf(" f2div= %f¥n",f2div);// ID の準備(64)//予約領域１
fwrite(&id1,
4,
1,//このデータ（１枚分の総サイズ）
fwrite(&id2,
4,
1,//パターン番号- 69 -

output_pt);//4byteoutput_pt);//4bytefwrite(&id3,
1,
1,
//金種
fwrite(&id4,
1,
1,-- 10 byte//方向
fwrite(&id5,
1,
1,
//国情報
fwrite(&id6,
1,
1,//通し番号
fwrite(&id7,
2,
1,
//機種
fwrite(&id8,
1,
1,
//号機
fwrite(&id9,
1,
1,
//種別
fwrite(&id10,1,1,//センサ番号
fwrite(&id11,
1,1,//画像のＸサイズ（画素数）
fwrite(&id12,
2,
1,
-- 20
//画像のＹサイズ（画素数）
fwrite(&id13,2,1,//センサ有効域チャネル番号（Ｌ）
fwrite(&id14,2,1,//センサ有効域チャネル番号（Ｈ）
fwrite(&id15,
2,
1,//予約領域２
fwrite(&id16,2,1,//センサ分解能（Ｘ方向）
fwrite(&id17,1,1,//センサ分解能（Ｙ方向）
fwrite(&id18,
1,
1,
-- 30
//予約領域３
fwrite(&id19,
1,
6,

output_pt);//1byteoutput_pt);//1byte --//紙幣の中心画素のＸ座標
fwrite(&id20,
2,1,//紙幣の中心画素のＹ座標
fwrite(&id21,
2,
1,
-- 40
//画像データのオフセット
fwrite(&id22,
4,
1,//予約領域４
fwrite(&id23,
4,1,//スラブ値の種類数
fwrite(&id24,
1,1,//１種類目のスラブ値のマスクＩＤ
fwrite(&id25,
1,
1,
-- 50
//１種類目のスラブ値の個数
fwrite(&id26,
1,
1,//予約領域５
fwrite(&id27,
1,5,//スラブ値のオフセット
fwrite(&id28,
4,
1,
-- 60
//予約領域６
fwrite(&id29,
4,
1,-- 64 (ヘッダの終了)

output_pt);//2byteoutput_pt);//2byte --output_pt);//4byteoutput_pt);//4byteoutput_pt);//1byteoutput_pt);//1byte --output_pt);//1byteoutput_pt);//5byteoutput_pt);//4byte --output_pt);//4byte --output_pt);//1byteoutput_pt);//1byteoutput_pt);//2byteoutput_pt);//1byteoutput_pt);//1byteoutput_pt);//1byteoutput_pt);//1byteoutput_pt);//2byte --output_pt);//2byteoutput_pt);//2byteoutput_pt);//2byteoutput_pt);//2byteoutput_pt);//1byteoutput_pt);//1byte --// ID + 画像データ + f1_slab(25) + f2_slab(25) をファイル出力//――――――
―――――
//
スラブ値

output_pt);//6bytefwrite(&f1_input, 4,//画像データ
fwrite(&id30,
ータの終了)

4,

100,output_pt);//4byte- 68 (画像デ//(この後にデータとなるスラブ値が書かれる)- 70 -

24,

output_pt);

fwrite(&f1div,
4,
fwrite(&f2_input, 4,
fwrite(&f2div,
4,

1,
24,
1,

output_pt);
output_pt);
output_pt);// ファイルクローズ(入力)fclose(input_pt);}// go to REPEAT// ファイルクローズ(出力)fclose(output_pt);}

unsigned int
unsigned int
unsigned int
unsigned int
unsigned char
unsigned char
unsigned char
unsigned int
unsigned int
unsigned longunsigned longunsigned char
unsigned char
unsigned char
unsigned char
unsigned longunsigned long

id13;
id14;
id15;
id16;
id17;
id18;
id19;
id20;
id21;
id22;
id23;
id24;
id25;
id26;
id27;
id28;
id29;

// 画像フレームのＹサイズ// センサ有効域チャネル番号（Ｌ）// センサ有効域チャネル番号（Ｈ）// 予約領域２// センサ分解能Ｘ// センサ分解能Ｙ// 予約領域３// 中心画素のＸ座標// 中心画素のＹ座標// 画像データのオフセット// 予約領域４// 格納されているスラブ種類数// １種類目のスラブ値のマスクｉｄ// １種類目のスラブ値の数// 予約領域５// スラブ値データのオフセット// 予約領域６(id1〜id29=ヘッダ)

手法２のプログラム (f_sum1.c)

float

id30;

#include<stdio.h>#include<stdlib.h>#include<conio.h>
unsigned longid1;
unsigned longid2;
unsigned char
id3;
unsigned char
id4;
unsigned char
id5;
unsigned char
id6;
unsigned int
id7;
unsigned char
id8;
unsigned char
id9;
unsigned char
id10;
unsigned char
id11;
unsigned int
id12;

int
float
float
FILE
char

i,j,n,k,l,m;
fch1[1024],fch2[1024],tch1[2048],tch2[2048];
t_No[2048],f_No[1024];*output_pt,*input_pt;
infile[20],outfile[20];

//

float

float
float
float
float
float

f1_sum_div=0.0,f2_sum_div=0.0;
f1_sum[60]={0.0},f2_sum[60]={0.0};
f1_in[60],f2_in[60];f1_input[30],f2_input[30];f1div,f2div;// 予約領域１// このデータ１枚分のサイズ// パターン番号
// 金種
// 方向
// 国情報// 通し番号// 機種// 号機// 種別（０：元画像 １：補正後）// センサ番号// 画像フレームのＸサイズ

void main( void ){- 71 -// 画像データ４byte

f1_slab[1024],f2_slab[1024];

id1=0;// 予約領域１
id2=664; // このデータ１枚分のサイズ
id3=1;// パターン番号
id4=1;// 金種
id5=1;// 方向
id6=1;// 国情報id7=1;// 通し番号
id8=1;// 機種
id9=1;// 号機
id10=0;// 種別（０：元画像 １：補正後）
id11=0;// センサ番号
id12=20; // 画像フレームのＸサイズ
id13=20; // 画像フレームのＹサイズ
id14=4;// センサ有効域チャネル番号（Ｌ）
id15=201;// センサ有効域チャネル番号（Ｈ）
id16=0;// 予約領域２
id17=10; // センサ分解能Ｘ
id18=40; // センサ分解能Ｙ
id19=0;// 予約領域３
id20=0;// 中心画素のＸ座標
id21=0;// 中心画素のＹ座標
id22=64; // 画像データのオフセット
id23=0;// 予約領域４
id24=1;// 格納されているスラブ種類数
id25=1;// １種類目のスラブ値のマスクｉｄ
id26=50; // １種類目のスラブ値の数
id27=0;// 予約領域５
id28=464;// スラブ値データのオフセット
id29=0;// 予約領域６
id30=1;// 画像データ// ファイルオープン (出力）printf("出力ファイル名を入力＝");scanf("%s",&outfile);

output_pt=fopen(outfile,"wb");// REPEAT
printf("ファイル数の入力=");scanf("%d",&n);for(i=0; i<n;i++){// ファイルオープン (入力）
printf("入力ファイル名を入力＝");scanf("%s",&infile);
input_pt=fopen(infile,"ra");// ASCII ファイルのﾃﾞｰﾀをリード(No.,tch1(2048),tch2(2048),No.,
fch1(1024),fch2(1024))
for(j=60;j<=515;j++){fscanf(input_pt,"%f%f%f%f%f%f",&t_No[j],&tch1[j],&tch2[j],&f_No[j],&fch1[j],&fch2[j]);}for(k=0;k<=24;k++){f1_sum[k]=0.0 ;f2_sum[k]=0.0;
for(l=1;l<=28;l++){f1_sum[k] += fch1[59+l+(28*k)];f2_sum[k] += fch2[59+l+(28*k)];}}for(k=0;k<=24;k++){f1_sum_div=f1_sum_div+f1_sum[k];f2_sum_div=f2_sum_div+f2_sum[k];- 72 -

f1_in[k]= f1_sum[k] / f1_sum_div;
f2_in[k]= f2_sum[k] / f2_sum_div;}
for(k=0;k<=24;k++){f1_input[k]=f1_in[k+1];
f2_input[k]=f2_in[k+1];}
f1div=f1_sum_div / 30000;
f2div=f2_sum_div / 30000;
printf("¥n¥n¥n f1_input[1]= %f",f1_input[1]);printf("");
printf(" f2_input[1]= %f¥n",f2_input[1]);printf(" f1_input[2]= %f",f1_input[2]);printf("");
printf(" f2_input[2]= %f¥n",f2_input[2]);printf(" f1_sum[1]= %f",f1_sum[1]);printf(" f2_sum[1]= %f¥n",f2_sum[1]);printf(" f1div= %f",f1div);
printf("");
printf(" f2div= %f¥n",f2div);// ID の準備(64)//予約領域１
fwrite(&id1,
4,
1,//このデータ（１枚分の総サイズ）
fwrite(&id2,
4,
1,//パターン番号
fwrite(&id3,
1,
1,
//金種
fwrite(&id4,
1,
1,

output_pt);//4byteoutput_pt);//4byteoutput_pt);//1byteoutput_pt);//1byte ---- 10 byte//方向
fwrite(&id5,
1,
1,
//国情報
fwrite(&id6,
1,
1,//通し番号
fwrite(&id7,
2,
1,
//機種
fwrite(&id8,
1,
1,
//号機
fwrite(&id9,
1,
1,
//種別
fwrite(&id10,1,1,//センサ番号
fwrite(&id11,
1,1,//画像のＸサイズ（画素数）
fwrite(&id12,
2,
1,
-- 20
//画像のＹサイズ（画素数）
fwrite(&id13,2,1,//センサ有効域チャネル番号（Ｌ）
fwrite(&id14,2,1,//センサ有効域チャネル番号（Ｈ）
fwrite(&id15,
2,
1,//予約領域２
fwrite(&id16,2,1,//センサ分解能（Ｘ方向）
fwrite(&id17,1,1,//センサ分解能（Ｙ方向）
fwrite(&id18,
1,
1,
-- 30
//予約領域３
fwrite(&id19,
1,6,//紙幣の中心画素のＸ座標
fwrite(&id20,
2,1,//紙幣の中心画素のＹ座標- 73 -

output_pt);//1byteoutput_pt);//1byteoutput_pt);//2byteoutput_pt);//1byteoutput_pt);//1byteoutput_pt);//1byteoutput_pt);//1byteoutput_pt);//2byte --output_pt);//2byteoutput_pt);//2byteoutput_pt);//2byteoutput_pt);//2byteoutput_pt);//1byteoutput_pt);//1byte --output_pt);//6byteoutput_pt);//2bytefwrite(&id21,
2,
1,
-- 40
//画像データのオフセット
fwrite(&id22,
4,
1,//予約領域４
fwrite(&id23,
4,1,//スラブ値の種類数
fwrite(&id24,
1,1,//１種類目のスラブ値のマスクＩＤ
fwrite(&id25,
1,
1,
-- 50
//１種類目のスラブ値の個数
fwrite(&id26,
1,
1,//予約領域５
fwrite(&id27,
1,5,//スラブ値のオフセット
fwrite(&id28,
4,
1,
-- 60
//予約領域６
fwrite(&id29,
4,
1,-- 64 (ヘッダの終了)//画像データ
fwrite(&id30,
ータの終了)

4,

output_pt);//2byte --output_pt);//4byteoutput_pt);//4byteoutput_pt);//1byteoutput_pt);//1byte --output_pt);//1byteoutput_pt);//5byteoutput_pt);//4byte --output_pt);//4byte --100,output_pt);// ファイルクローズ(入力)fclose(input_pt);}// go to REPEAT// ファイルクローズ(出力)fclose(output_pt);}//4byte- 68 (画像デ//(この後にデータとなるスラブ値が書かれる)// ID + 画像データ + f1_slab(25) + f2_slab(25) をファイル出力//――――――
―――――
//
スラブ値
fwrite(&f1_input, 4,
fwrite(&f1div,
4,
fwrite(&f2_input, 4,
fwrite(&f2div,
4,

24,
1,
24,
1,

output_pt);
output_pt);
output_pt);
output_pt);- 74 -