2013年12月31日火曜日

Windows7で音声合成できない・・・・

先日Windowsで音声合成するサンプルを書きましたが、Windows7では動作させることができません。
Windows7標準の音声合成機能はなぜか日本語音声合成エンジンの提供が通常では行われていないので、プログラムから標準機能のみでの音声合成はできないことになります。

Microsoftの方針としてはSpeechPlatformをインストールして利用してほしいようです。
実際Office2010以降の読み上げ機能もSpeechPlatformをインストールするように説明があります。

音声認識に関してもサンプルプログラムは動きませんでした。

次回はちょっと予定を変更して、SpeechPlatformのインストールに関して書いてみたいと思います。

2013年12月27日金曜日

Windowsで音声認識(Choices+GrammarBuilder)

先日の音声合成に続いて、Windows標準の音声認識機能を使ってみます。

標準の音声認識機能は学習方式と辞書方式どちらにも対応しているようなのですが、今回は辞書方式で認識させます。

音声合成の場合と同じく特に用意するものはありません。

さっそくサンプルプログラムです。コンソールアプリケーションです。

using System;
using System.Speech.Recognition;

namespace SpeechRecognized_Sample
{
    class Program
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {

            //認識エンジン(既定のロケールを使用)
            using (SpeechRecognitionEngine sre = new SpeechRecognitionEngine())
            {

                //イベント登録
                sre.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(sre_SpeechRecognized);

                //語彙登録
                Choices words = new Choices(new string[] { "晴れ", "曇り", "雨", "雪" });

                //GrammarBuilderインスタンス
                GrammarBuilder gb = new GrammarBuilder("今日の天気は");

                //GrammarBuilderインスタンスに語彙を追加
                gb.Append(words);

                //Grammarインスタンスを作成
                Grammar g = new Grammar(gb);

                //Grammarインスタンスをロード
                sre.LoadGrammar(g);

                Console.Write("認識開始" + "\n");

                //入力ソース(既定のマイク)
                sre.SetInputToDefaultAudioDevice();

                //非同期で認識開始
                sre.RecognizeAsync(RecognizeMode.Multiple);

                while (true)
                {
                    Console.ReadLine();
                }
            }
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void sre_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            Console.WriteLine("認識しました:" + e.Result.Text + " 信頼度:" + e.Result.Confidence);
        }
    }
}


説明:
「プロジェクト」>「参照の追加」>「アセンブリ」>「フレームワーク」内の「System.Speech」のチェックを忘れないでください。
今回辞書への登録方法としてChoicesクラスとGrammarBuilderクラスを使っています。
Choicesクラスに認識させたい単語を文字列配列として与えます。
その後Choicesオブジェクトを引数としてGrammarBuilderクラスに与えます。
次にGrammarクラスにGrammarBuilderオブジェクトを与えます。
最後に認識エンジンにGrammarオブジェクトをロードして辞書に登録します。

サンプルではGrammarBuilderインスタンスを作成するときに文字列を与えています。
このようにすることで「今日の天気は」+「Choicesクラスに登録した単語」の組み合わせの文章を登録できます。

音声合成の場合より少し複雑ですが、手順がわかればそれほど難しくはないと思います。

次回はSRGSを使って認識させるサンプルの予定です。


2013年12月25日水曜日

Windowsで音声合成

先日大阪でDev(ice)LOVE デバイス祭りという勉強会に参加しました。
「KINECTを使った音声対話」という内容で話をさせていただいたのですが、その時のスライドに対応したサンプルプログラム+αを何回かに分けて書いていきたいと思います。

ちなみにスライドはこちらにアップロードしています。

まず最初に音声合成のサンプルプログラムです。
勉強会の時はSpeechPlatform11をインストールした状態での説明でしたが、Windows標準の状態でもできますので特に何も用意する必要はありません。(もちろん開発環境は必要です^^;)

サンプルプログラムの動作確認は Windows8 Pro+VS C# 2012 Express for Desktopですが、
Windows7やC#2010でも動くと思います。.NET Framework3.5以上なら大丈夫でしょう。もしかするとXPでも動くかもしれないです。

さっそくプログラムです。コンソールアプリとなります。

using System;
using System.Speech.Synthesis;

namespace Speak_Sample
{
    class Program
    {
        static void Main(string[] args)
        {
            //音声合成エンジン
            SpeechSynthesizer ss = new SpeechSynthesizer();
           
            //出力を既定のスピーカーに設定
            ss.SetOutputToDefaultAudioDevice();

            //音声出力
            ss.Speak("こんにちは,今日はようこそいらっしゃいました。");

            //キー入力待ち
            Console.ReadKey();
           
        }
    }
}

あらかじめ「プロジェクト」>「参照の追加」>「アセンブリ」>「フレームワーク」内の「System.Speech」にチェックを入れてください。

2行目の「System.Speech.Synthesis」でWindows標準の音声合成機能を利用できるようにしています。

しゃべらせるだけならこれだけです。ひらがな、カタカナ、漢字も使えます。英語も標準で使えます。
多国語対応ですが、別に言語パックなどをインストールしなければいけないでしょう。

2013年8月2日金曜日

LeapMotion サンプル その1 (WPF+VB)

KINECTよりすごい(かも)と言われているLeapMotionを手に入れました。
2013/7/22に一般発売でしたが、21日に注文して27日には到着しましたので比較手に入手はしやすいようです。

さて、LeapMotionで何ができるのかと簡単に説明するとセンサー上の手指の位置や移動の情報を高精度で取得できるガジェットです。

開発環境はC++,C#,JAVA,Javascript,Python等色々あります。OSはWindows7以降,MacOS X等(Linuxはまだβ版ドライバ)です。

SDKも一通り揃っているので、開発しやすいと思います。

ただ、SDK内のサンプルプログラムはWPF向けではないので、VB(開発環境には載っていないけれども.NetFramework3.5以降対応なので問題なし)+WPFのサンプルプログラムを作ってみました。

内容は指一本をセンサー上で動かすとCanvas上のポインター(Ellipse)が指先と同じように動きます。
LeapMotionはSDK上に仮想スクリーンを生成する機能を持っているので、それを利用しています。

早速コードをと行きたいところですが、まずは開発環境を整えましょう。

環境についてはこちらのブログを参照するのが早いと思います。

Natural Software
 http://www.naturalsoftware.jp/blog/8389

C#向けですが、VBも同じです。C++とかMacでの環境設定の説明もあるので他の記事も参考になると思います。

それではプログラムコードです。

まずはXAMLのソースです。画面構成はテキストボックスを4つと、Canvasを1つ配置しています。
Canvasのサイズは適当に変えても大丈夫です。

MainWindow.xaml
<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="900" Width="1228">
    <Grid>
        <Canvas Name="Canvas1" Height="800" Width="1200" Margin="10,50,82,19"/>
        <TextBox Name="textbox1" HorizontalAlignment="Left" Height="23" Margin="85,10,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="80"/>
        <TextBox x:Name="textbox2" HorizontalAlignment="Left" Height="23" Margin="245,10,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="80"/>
        <TextBox x:Name="textbox3" HorizontalAlignment="Left" Height="23" Margin="358,10,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="80"/>
        <TextBox x:Name="textbox4" HorizontalAlignment="Left" Height="23" Margin="470,10,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="80"/>
        <Label Content="Frame ID:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="70"/>
        <Label Content="Finger ID:" HorizontalAlignment="Left" Margin="170,10,0,0" VerticalAlignment="Top"/>
        <Label Content="X:" HorizontalAlignment="Left" Margin="330,10,0,0" VerticalAlignment="Top"/>
        <Label Content="Y:" HorizontalAlignment="Left" Margin="443,10,0,0" VerticalAlignment="Top"/>
    </Grid>
</Window>

次にプログラムコードです。
MainWindow.xaml.vb

Imports Leap
Class MainWindow
    Private leap As New Controller
    Private windowWidth As Integer = 1200       ''仮想スクリーンの幅
    Private windowHeight As Integer = 800       ''仮想スクリーンの高さ
    Public Sub New()
        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()
        ' InitializeComponent() 呼び出しの後で初期化を追加します。
        ''イベント登録
        AddHandler CompositionTarget.Rendering, AddressOf UpdateFrame
    End Sub
    Private Sub UpdateFrame(sender As Object, e As EventArgs)
        Dim frame As Leap.Frame = leap.Frame
        Dim finger As Finger = frame.Fingers.Frontmost                      ''一番センサーに近い指を選択
        Dim stabilizedPosition As Vector = finger.StabilizedTipPosition
        Dim iBox As InteractionBox = leap.Frame.InteractionBox
        Dim normalizedPosition As Vector = iBox.NormalizePoint(stabilizedPosition)
        Dim x As Double = normalizedPosition.x * windowWidth
        Dim y As Double = windowHeight - normalizedPosition.y * windowHeight
        ''テキストボックスに各情報をセット
        textbox1.Text = frame.Id
        textbox2.Text = finger.Id
        textbox3.Text = CInt(x)
        textbox4.Text = CInt(y)
        ''Canvasのクリア
        Canvas1.Children.Clear()
        ''指を認識していないときは何もしない
        If finger.Id = -1 Then
        Else
            Dim el As New Ellipse
            Canvas1.Children.Add(el)
            With el
                .Margin = New Thickness(CInt(x), CInt(y), 0, 0)
                .Fill = New SolidColorBrush(Colors.Green)
                .Width = 10
                .Height = 10
            End With
        End If
    End Sub
End Class



WPFを使う場合に問題になるのが、要素の書き換え(この場合はCanvas)とセンサーからのデータ取得を同一スレッドで行う必要があることになります。

今回はCompositionTarget.Renderingイベントに合わせて、センサーからデータを取得しています。
CompositionTarget.RenderingはWPFの描画プロセス中に発生するイベントです。

プログラム内の描画ルーチン(UpdateFrame)は最低限のことしかしていません。本来であれば指先をロストした時の処理なども必要になると思います。(なので指先がセンサーの認識範囲外に移動するとポインターが暴れます。)

次はこのプログラムにタッチエミュレーションを加えてみようと思います。


2013年6月27日木曜日

Node.jsからローカルのSQLServerに接続

最近はNode.jsとDB接続に関して色々調べています。
Node.jsと組み合わせるDBはNosql系のDBが多いですが、今回はSQLServerでやってみました。

MS純正のNode用ドライバは以前から提供されているのですが、日本語での情報がほとんどないため結構苦労しました。

今回はHyper-V上のWindows7にSQLServer2012ExpressとNode.jsをインストールしてみました。

環境:
・Windows7 Pro SP1 32bit
・SQLServer 2012 Express x86版
・Node.js v0.8.25 32bit

その他
・Express 3.3.0 + ejs

また node-sqlserverのコンパイルに必要なのが
・Visual C++ 2010 Express
・Python 2.7

となります。


導入手順

1.Node.jsのダウンロードとインストールをします。今回は0.8系の最新版を選択しました。
  (最新安定版の10.0系ではnode-sqlserverがコンパイルできませんでした。)

2.Visual C++ 2010 ExpressSQLServer2012Expressをダウンロードして、インストールします。
  SQLServerはネットワーク接続できるようにファイアウォール等の設定をしています。

3.Python2.7をダウンロードしてインストールします。

4.SQLServerに「test」データベースを作成し、「T_M商品」テーブルを作成します。
  内容は下の図を参照してください。データも適当に入れておきます。
  



5.C:\に「node」フォルダを作成し、この中にアプリケーションを配置するようにします。

6.Node.jsコマンドプロンプトを起動してからC:\nodeフォルダに移動します。

7.コマンドプロンプトでc:\node> npm install -g express と入力してExpressをインストールします。

8.c:\node> express -e test と入力してtestフォルダにアプリケーションの雛形を作成します。
  testフォルダには以下のように雛形が作成されます。
  

9.package.jsonファイルをエディタで以下のように編集します。

-------------------------------------------------------- 
{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.3.0",
    "ejs": "*",
    "node-sqlserver": "*" <------------赤字部分を追加
  }
}
--------------------------------------------------------
このときファイルの文字コードに気をつけましょう。UTF-8で保存しておかないと正常に動作しない可能性があります。以下すべてのファイルの文字コードがUTF-8になるようにしてください。

10.コマンドプロンプト上でtestフォルダに移動してから c:\node\test> npm install と入力する
   と先ほどのpackage.jsonの内容にしたがってインストールが行われます。このとき途中で
   黄色のワーニングメッセージが出るかもしれませんが、コンパイル環境が問題なければ
   そのまま問題なく終了します。

11.問題なくインストールができるとtestフォルダにはnode_modulesフォルダが追加されています。
   

12.node_modules>node-sqlserver>build>Releaseフォルダ内のsqlserver.nodeファイルを
   node_modules>node-sqlserver>libフォルダ内にコピーします。

13.testフォルダにあるapp.jsファイルを以下のように編集します。

途中から
----------------------------------

app.get('/', routes.index);
app.get('/users', user.list);
app.post('/',routes.index);  <-----赤字の部分を追加

----------------------------------
以下は変更なし


14.test>routesフォルダにあるindex.jsファイルを以下のように編集します。

-------------------------------------------------------------------------------
exports.index = function(req, res){
if (req.body.code) {
var sql=require('node-sqlserver');
var cn_str="Driver={SQL Server Native Client 11.0};Server=(local);Database=test;Uid=ユーザー名;Pwd=パスワード;";
sql.query(cn_str,"select * from T_M商品 where 商品コード='" + req.body.code + "'",function(err,rst) {
if (err) {
res.render('index', { title: 'ERROR' });
console.log(err);
}
res.render('index2',{ title: 'Result',
    rst: rst
});
});
}
else {
res.render('index', { title: '検索' });
}
};
-------------------------------------------------------------------------------


15.test>viewsフォルダにあるindex.ejsファイルを以下のように編集します。

-------------------------------------------------------------------------------
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1>検索</h1>
      
      <form method="POST" action="/">
        コード検索: <input type="text" name="code" size="50">
        <input type="submit" value="検索実行">
      </form>
  </body>
</html>
-------------------------------------------------------------------------------


16.test>viewsフォルダにindex2.ejsファイルを以下の内容で追加します。

-------------------------------------------------------------------------------
<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
 
    <h1>Data</h1>
 
<form method="POST" action="/">
        コード検索: <input type="text" name="code" size="50">
        <input type="submit" value="検索実行">
</form>

<P>

<table border="1">
 <tr>
<th>商品コード</th>
<th>商品名</th>
<th>標準価格</th>
 </tr>

 <% for(var i=0;i<rst.length;i++){ %>
<tr>
 <td> <%= rst[i]['商品コード'] %> </td>
 <td> <%= rst[i]['商品名'] %> </td>
 <td> <%= rst[i]['価格'] %> </td>
</tr>
 <% } %>

</table>
  </body>
</html>
-------------------------------------------------------------------------------


17.アプリケーションを動かしてみます。コマンドプロンプトでc:\node\testフォルダに移動して
   c:\node\test> node app.jsと入力します。
   問題がなければ「Express server listeng on port 3000」と表示されます。


18.ブラウザで「http://localhost:3000/」にアクセスすると以下のように表示されます。


19.試しにコードを入力して検索を実行すると以下のような結果になりました。



まだSelect文のテストしかしていませんが、このようにNode.js+SQLServerの組み合わせでアプリケーションが作成できました。

Node.jsはまだまだ勉強中なのでたいしたサンプルではないですが、少しでも参考になればと思います。


2013年6月26日水曜日

2013年2月14日木曜日

LocalDBをVBAから使ってみる

久しぶりの投稿です。

しばらくKinectさわっていません。
なぜかHoGの投稿に定期的にアクセスがあります。どうしてなのかな?

さて、今回はSQLServer2012から新たに追加になったLocalDBについてです。

SQL Server2012Expressもほとんど同じですが、スタンドアローン環境で使うならLocalDBの方が手軽に使えそうです。

ただ、色々なサイトで解説はあるんですが、VBAでの解説があまりないようです。

試しにExcel2013でADO+NativeClientで接続してみようとすると、最初はうまく接続できませんでした。


最初に書いたコードです。

-----------------------------------------------------------------------------------------------------------
Sub DB接続()

Dim cn As New ADODB.Connection

cn.ConnectionString = "provider=sqlncli11;server=(localdb)\v11.0;database=test;integrated security=true;DataTypeCompatibility=80;MARS Connection=True"

cn.Open

Dim rs As New ADODB.Recordset

rs.Open "select * from T_商品", cn, adOpenStatic, adLockReadOnly

If rs.BOF And rs.EOF Then

Else
Range("A1").Select
ActiveCell.CopyFromRecordset rs
End If

rs.Close
Set rs = Nothing

End Sub
-----------------------------------------------------------------------------------------------------------
(あらかじめ既定のインスタンスにtestデータベースを作成して、T_商品テーブルを追加しています。)

この場合コネクションを開いた時点でエラーが発生しました。

色々試した結果は

「integrated security=true」を「integrated security=SSPI」に変更すれば正常に動作しました。

通常TrueでもADO.NETなどは動くようなのですが・・・・

まぁ、これでEXCELやACCESSでもLocalDBが利用できそうです。

あとLocalDBはSQLOLEDBプロバイダは使えないみたいです。