以前、IronPythonでimportができない例を書きました。

C#でIronPythonと連携する際にnumpyがimportできない | 詠み人知らずの備忘録



上記の対応を行うことで、DLLがロードできるため
numpyやwaveなどをimportできるようにはなったのですが、Scipyだけは下記のようにエラーが出てだめでした。

'module' object has no attribute '_getframe'

Scipy_error.png

どうやらコンソールからIronPythonを起動する際にScipyを使用するに、 -X:Frames と引数を渡していることに関係あるみたいです。

結果としては、Pythonのエンジンを起動する際に下記のようにオプションを設定して起動するように行えばいいようです。

var options = new Dictionary();
options["Frames"] = true;
options["FullFrames"] = true;
ScriptEngine engine = Python.CreateEngine(options);

※1行目と5行目がなぜかおかしくなっています。
 ただしくは、
 var options = new Dictionary<string, object>();
 です。



また、Python側でも以下のpathを追加していないとno moduleのエラーがでます。
特に、Scipyでは4行目の定義も必要のようです。
sys.path.append(r'C:\Program Files\IronPython 2.7')
sys.path.append(r'C:\Program Files\IronPython 2.7\DLLs')
sys.path.append(r'C:\Program Files\IronPython 2.7\Lib')
sys.path.append(r'C:\Program Files\IronPython 2.7\Lib\site-packages')



C#にはどうやら音声ファイルを簡単に読み込む手段がないようで、
じゃあPythonに任せればいいのでは?


。。。ということで今回は、C#とIronPythonで音声ファイルのデータを読み込みます。


Pythonの音声ファイルの取得はこちらを参考にしました。
漫ろ草 SozoroGusa: pythonでwaveファイル(2)



ソース

C#側
using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using IronPython.Hosting;           // for IronPython
using Microsoft.Scripting.Hosting;  // for IronPython

namespace LoadWave
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void 開くOToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //「ファイルの種類」を設定
            openFileDialog1.Filter = "音声ファイル(WAV)|*.wav;|すべてのファイル(*.*)|*.*";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                // Scipyを起動するためのオプション設定
                var options = new Dictionary();
                options["Frames"] = true;
                options["FullFrames"] = true;

                ScriptEngine engine = Python.CreateEngine(options);

                ScriptSource script = engine.CreateScriptSourceFromFile("sample.py");
                ScriptScope scope = engine.CreateScope();
                
                // 選択したwavファイルをPythonに渡す値として設定
                scope.SetVariable("filename", openFileDialog1.FileName);

                // IronPythonを実行
                script.Execute(scope);

                // 処理した音声データを取得
                var audio = scope.GetVariable("audio");
            }
        }
    }
}



C#のopenFileDialogで、選択した音声ファイルをIronPythonに渡してfilenameという変数で使用しています。
// 選択したwavファイルをPythonに渡す値として設定
scope.SetVariable("filename", openFileDialog1.FileName);



IronPythonで取得した音声データ(audio)をC#側に返しています。
// 処理した音声データを取得
var audio = scope.GetVariable("audio");



IronPython側
#-*- coding: utf-8 -*-
import sys
sys.path.append(r'C:\Program Files\IronPython 2.7')
sys.path.append(r'C:\Program Files\IronPython 2.7\DLLs')
sys.path.append(r'C:\Program Files\IronPython 2.7\Lib')
sys.path.append(r'C:\Program Files\IronPython 2.7\Lib\site-packages')

import clr
clr.AddReference('mtrand.dll')

import wave
import struct

wf = wave.open(filename, "rb")

#オーディオチャンネル数(モノラルなら1、ステレオなら2)
nchannels=wf.getnchannels()
#サンプルサイズ(バイト)
sampwidth=wf.getsampwidth()
#サンプリングレート
framerate=wf.getframerate()
#オーディオフレーム数
nframes=wf.getnframes()
#オーディオフレーム(リストオブジェクト)
frames=wf.readframes(nframes)
wf.close()

audio = struct.unpack("%dh" %nframes*nchannels, frames)



C#で配列を受け取る際にどのようにすればいいのか、特に記載はなかったのですが。
上記のようで問題ないようです。



ちなみに、正弦波の音声データを読み込んで、取得したデータを表示したものが下記のグラフです。

sin.png


巷で大人気の漫画カメラというソフトがあります。

漫画カメラ | スマートフォン カメラアプリ | スーパーソフトウエア



その漫画カメラの実装について、こちらにわかりやすい解説を見つけました。

【連載】コンピュータビジョンのセカイ - 今そこにあるミライ (39) iPhoneアプリ「漫画カメラ」に見るコンピュータビジョンの実応用例 | 開発・SE | マイナビニュース

【連載】コンピュータビジョンのセカイ - 今そこにあるミライ (40) iPhoneアプリ「漫画カメラ」で使われている画像処理手法その1 | 開発・SE | マイナビニュース

【連載】コンピュータビジョンのセカイ - 今そこにあるミライ (41) iPhoneアプリ「漫画カメラ」で使われている画像処理手法その2 | 開発・SE | マイナビニュース



こちらで具体的に、iOSで実装されている方がおります。

OpenCVで写真を漫画風に加工しよう 〜実装編〜 | Developers.IO



ソース

ということで、今回は漫画カメラ風の画像を作り出すのをやってみました。
ちなみに、PythonとOpenCVで実装しています。
手順は以下の通りです。
  1. 画像を読み込む
  2. Cannyのエッジ検出を行い、その画像をネガポジ変換を行う。
  3. 3値化処理を行う
  4. 3値化処理の灰色に割り当てられたところをスクリーントーンに置き換える
  5. 2,4の画像を合成する


ちなみに、2,3をいっぺんに行ったり、
5の合成の後に灰色部分を消すため再度2値化処理を行ったり色々とアレ・・・です。。。


スクリーントーンはこちらのサイトからいただいたものを使用しました。
WEB用無料素材 | デジタルトーンスジタオ




import cv2
import numpy

# 画像を読み込む
img = cv2.imread("Lenna.bmp",cv2.CV_LOAD_IMAGE_GRAYSCALE)
screen = cv2.imread("screen.bmp",cv2.CV_LOAD_IMAGE_GRAYSCALE)

# エッジ検出後にネガポジ反転
edge= cv2.Canny(img,80,120)
nega = cv2.bitwise_not(edge)

# sizeを取得
width = img.shape[0] 
height = img.shape[1]

# 3値化を行う(ただし灰色の場合はスクリーントーンに置き換える)
temp = numpy.zeros_like(img)
for i in xrange(width):
    for j in xrange(height):
        if img[i,j]<80:
            temp[i,j] = 0
        elif img[i,j]>=80 and img[i,j]<160:
            temp[i,j] = screen[i,j]
        else:
            temp[i,j] = 255

# 3値化とエッジの画像を合成
alpha = 0.5
result = cv2.addWeighted(nega,alpha,temp,1-alpha,0.0)
(thresh,result)=cv2.threshold(result,200,255,cv2.THRESH_BINARY)



結果

結果は以下になります。。。


【元画像】
Lenna



【エッジ画像(Canny)】
edge.png



【ネガポジ変換後】
nega.png



【3値化画像】
3val.png



【ネガポジ+3値化=漫画風】
result_20130320013925.png



反省点

画像の大きさに合わせてスクリーントンのサイズを変えたり、
スクリーントンのパターンを変更できるようにしたいですね。

あとは、画像合成のうまい方法忘れてしまいました。。。orz

C#からIronPythonを呼び出すために、調べていた際にはまったことをメモ。

簡単なスクリプトやメソッドなら呼び出せるのですがimport numpyやimport waveなどを使用すると
下記のようなエラーが・・・






メッセージ内容を見ると

IronPython.Runtime.Exceptions.ImportException はハンドルされませんでした。
Message=No module named numpy


とのこと、

DLLのロードができていないようなのですが、
他のサイトでは連携の際に上記現象の記載がない方もいらっしゃるようでこのへんは謎です。



ソース

エラーの原因は、IronPythonでロードができていないようです。
強調された箇所を追加することによって実行ができるようになりました。
#もっといい手法あるような気がしますが、調べても出てこないので。。。

ソースは以下のようになります。

Python
#-*- coding: utf-8 -*-
import sys
sys.path.append(r'C:\Program Files\IronPython 2.7')
sys.path.append(r'C:\Program Files\IronPython 2.7\DLLs')
sys.path.append(r'C:\Program Files\IronPython 2.7\Lib')
sys.path.append(r'C:\Program Files\IronPython 2.7\Lib\site-packages')

import clr
clr.AddReference('mtrand.dll')

import numpy as np

result = np.sin(input)



C#
次にC#です。
以下の2つのDLLを参照の追加を行い。
  • IronPython.dll
  • Microsoft.Scripting.dll


その後、usingの追加を行ってください。
  • using IronPython.Hosting;
  • using Microsoft.Scripting.Hosting;
// Pythonスクリプト実行エンジン
ScriptEngine engine = Python.CreateEngine();

// 実行するPythonのソースを指定
ScriptSource source = engine.CreateScriptSourceFromFile("../../sample.py");

// 実行エンジンに渡す値を設定する
ScriptScope scope = engine.CreateScope();

// Pythonに渡す値を設定(inputという変数に40を設定)
scope.SetVariable("input", 40);

// 実行
source.Execute(scope);

// Pythonの実行結果を取得
double result = scope.GetVariable("result");




IronPythonでの計算、C#側で計算結果の受け取りができることを確認しました。
もっと良い方法があるのかもしれませんが、この辺であきらめましたorz


若干ロードがあるせいか遅い気がしますが、IronPythonのnumpyなどのライブラリがC#で使えるのは大きなメリットかなと思います。

OpenCVSharpの公式サイトに記載されているので、ご存じかもしれませんが。
< デバッグ中にIplImageの中を確認する方法をメモしておきます。

DebuggerVisualizer - opencvsharp http://code.google.com/p/opencvsharp/wiki/DebuggerVisualizer

導入方法

OpenCVSharpの中に含まれているdllの中に

OpenCvSharp.DebuggerVisualizers.dll

があります。
それを、My DocumentのVisual StudioのVisualizersというフォルダにコピーします。

VistaでVisual Studio2010の例ですと。
C:\Users\XXX\Documents\Visual Studio 2010\Visualizers
になります。


使い方

デバッグ中にIplImageの変数にフォーカスを当てると、虫メガネのマークが表示されるので
それをクリックすると現在の状況の画像が表示されます。

FC2カウンター
プロフィール

詠み人知らず

Author:詠み人知らず
プログラム好きな名もなき凡人がお送りしています。(得意とは言っていない
最近の興味はPython、C#、Matlab(Octave)、画像処理、AR(拡張現実)、統計などなど・・・

気分で思いついたことを書くため話題に一貫性がないかもしれません。

カレンダー
08 | 2017/09 | 10
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
最新記事
タグクラウドとサーチ

カテゴリ
最新コメント
最新トラックバック
月別アーカイブ