質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Xamarin

Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。

Q&A

解決済

4回答

7044閲覧

Xamarin.FormsでOpenCVを使って顔認証がしたい(Android)

taichaso

総合スコア22

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Xamarin

Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。

0グッド

0クリップ

投稿2018/03/26 04:25

前提・実現したいこと

Xamarin.FormsでOpenCVを使って顔認証をしたいと思っています。
Formsの必要がないといわれてしまうかもしれませんが、現時点ではAndroidのみの実装予定です。

Xamarin.FormsからDepencencyServiceを使ってXamarin.Androidに書いてあるC++の処理を呼び出すという流れで考えています。
カメラやギャラリーから画像を取得し、顔認識を行う関数の引数として取得した画像を送り、返り値として顔の位置が表示された画像(下の画像のような状態のもの)が返ってくるようなものにしたいと思っています。

![このような画像(b814c28bdf91ebe6aabd69ae43a7313c.jpeg)

C++の処理を.dllとしてビルドして、.dllをAndroidで参照するという流れまでは理解することができたのですが、そこで疑問が出てきたので質問させていただきます。

質問内容

こちらのようなC++のサンプルソースを関数として作成しAndroidでその処理を呼び出すことができるのか

C++のクラスライブラリをプロジェクトの中で作り、できた.dllファイルをそのまま参照しても問題ないのか

これらよりのことを行うことよりも簡単に実装することができるのか

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

これらよりのことを行うことよりも簡単に実装することができるのか

リアルタイムに、あるいは自力で、顔検出をしたいのではなければ、各社が出している WebAPI を使用した方が簡単かと思います。

投稿2018/03/26 15:20

amay077

総合スコア1075

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

C/C++のライブラリをC#で呼ぶ方法は

  • DllImport属性(System.Runtime.ExceptionServices名前空間)を使う
  • C++/CLIによるラッパークラスを経由して呼び出す

の2種類があります。

CppSharpを使えばヘッダーファイルとライブラリファイルを解析をしてC++/CLI用のコードとC#用のコードを自動生成してくれます。C/C++の解析にClangを用いて実装されています。

以下はVista時代のVisual C++の流儀(前編)に掲載されているcounterクラスを以下に示します。

cpp

1#ifndef COUNTER_H__ 2 #define COUNTER_H__ 3 4 class counter { 5 private: 6 int value_; 7 public: 8 counter(); 9 void increment(); 10 int value() const; 11 }; 12 13 #endif

cpp

1#include "counter.h" 2 3 counter::counter() : value_(0) { 4 } 5 6 void counter::increment() { 7 ++value_; 8 } 9 10 int counter::value() const { 11 return value_; 12 }

それではcounterクラスを自動でラッピングしてくれるCppSharpによるC++/CLIのヘッダーファイルとソースファイルを生成されたソースコードを以下に示します。

cpp

1// ---------------------------------------------------------------------------- 2// <auto-generated> 3// This is autogenerated code by CppSharp. 4// Do not edit this file or all your changes will be lost after re-generation. 5// </auto-generated> 6// ---------------------------------------------------------------------------- 7#pragma once 8 9#include "CppSharp.h" 10#include <../counter.h> 11 12namespace CounterLib 13{ 14 ref class Counter; 15} 16 17namespace CounterLib 18{ 19 public ref class Counter : ICppInstance 20 { 21 public: 22 23 property ::counter* NativePtr; 24 property System::IntPtr __Instance 25 { 26 virtual System::IntPtr get(); 27 virtual void set(System::IntPtr instance); 28 } 29 30 Counter(::counter* native); 31 static Counter^ __CreateInstance(::System::IntPtr native); 32 Counter(); 33 34 Counter(CounterLib::Counter^ _0); 35 36 ~Counter(); 37 38 !Counter(); 39 40 property int Value 41 { 42 int get(); 43 } 44 45 void Increment(); 46 47 protected: 48 bool __ownsNativeInstance; 49 }; 50}

cpp

1// ---------------------------------------------------------------------------- 2// <auto-generated> 3// This is autogenerated code by CppSharp. 4// Do not edit this file or all your changes will be lost after re-generation. 5// </auto-generated> 6// ---------------------------------------------------------------------------- 7#include "CounterWrapper.h" 8 9using namespace System; 10using namespace System::Runtime::InteropServices; 11 12CounterLib::Counter::Counter(::counter* native) 13 : __ownsNativeInstance(false) 14{ 15 NativePtr = native; 16} 17 18CounterLib::Counter^ CounterLib::Counter::__CreateInstance(::System::IntPtr native) 19{ 20 return gcnew ::CounterLib::Counter((::counter*) native.ToPointer()); 21} 22 23CounterLib::Counter::~Counter() 24{ 25 delete NativePtr; 26} 27 28CounterLib::Counter::!Counter() 29{ 30 delete NativePtr; 31} 32 33CounterLib::Counter::Counter() 34{ 35 __ownsNativeInstance = true; 36 NativePtr = new ::counter(); 37} 38 39void CounterLib::Counter::Increment() 40{ 41 ((::counter*)NativePtr)->increment(); 42} 43 44CounterLib::Counter::Counter(CounterLib::Counter^ _0) 45{ 46 __ownsNativeInstance = true; 47 if (ReferenceEquals(_0, nullptr)) 48 throw gcnew ::System::ArgumentNullException("_0", "Cannot be null because it is a C++ reference (&)."); 49 auto &__arg0 = *(::counter*)_0->NativePtr; 50 NativePtr = new ::counter(__arg0); 51} 52 53System::IntPtr CounterLib::Counter::__Instance::get() 54{ 55 return System::IntPtr(NativePtr); 56} 57 58void CounterLib::Counter::__Instance::set(System::IntPtr object) 59{ 60 NativePtr = (::counter*)object.ToPointer(); 61} 62 63int CounterLib::Counter::Value::get() 64{ 65 auto __ret = ((::counter*)NativePtr)->value(); 66 return __ret; 67}

あとは「共通言語ランタイム サポート (/clr)」「ダイナミック ライブラリ (.dll)」の設定への変更とスタティックライブラリへのパスを設定してビルドすればC#からでもVB/F#からでもこのcounterクラスを呼び出すことができます。

ILSpyというツールを使ってCounterを解析すると以下のようなC#のコードが生成されています。

cs

1using System; 2using System.Runtime.ExceptionServices; 3using System.Runtime.InteropServices; 4 5namespace CounterLib 6{ 7 public class Counter : ICppInstance, IDisposable 8 { 9 private unsafe counter* <backing_store>NativePtr; 10 11 protected bool __ownsNativeInstance; 12 13 public int Value 14 { 15 get 16 { 17 return <Module>.counter.value(this.<backing_store>NativePtr); 18 } 19 } 20 21 public unsafe virtual IntPtr __Instance 22 { 23 get 24 { 25 IntPtr result = new IntPtr((void*)this.<backing_store>NativePtr); 26 return result; 27 } 28 set 29 { 30 this.<backing_store>NativePtr = (counter*)value.ToPointer(); 31 } 32 } 33 34 public unsafe counter* NativePtr 35 { 36 get 37 { 38 return this.<backing_store>NativePtr; 39 } 40 set 41 { 42 this.<backing_store>NativePtr = value; 43 } 44 } 45 46 public unsafe Counter(Counter _0) 47 { 48 this.__ownsNativeInstance = true; 49 if (object.ReferenceEquals(_0, null)) 50 { 51 throw new ArgumentNullException("_0", "Cannot be null because it is a C++ reference (&)."); 52 } 53 counter* ptr = _0.<backing_store>NativePtr; 54 counter* ptr2 = <Module>.@new(4u); 55 counter* ptr3; 56 if (ptr2 != null) 57 { 58 cpblk(ptr2, ptr, 4); 59 ptr3 = ptr2; 60 } 61 else 62 { 63 ptr3 = null; 64 } 65 this.<backing_store>NativePtr = ptr3; 66 } 67 68 public unsafe Counter() 69 { 70 this.__ownsNativeInstance = true; 71 counter* ptr = <Module>.@new(4u); 72 counter* ptr2; 73 try 74 { 75 if (ptr != null) 76 { 77 ptr2 = <Module>.counter.{ctor}(ptr); 78 } 79 else 80 { 81 ptr2 = 0; 82 } 83 } 84 catch 85 { 86 <Module>.delete((void*)ptr, 4u); 87 throw; 88 } 89 this.<backing_store>NativePtr = ptr2; 90 } 91 92 public unsafe Counter(counter* native) 93 { 94 this.__ownsNativeInstance = false; 95 base..ctor(); 96 this.<backing_store>NativePtr = native; 97 } 98 99 public unsafe static Counter __CreateInstance(IntPtr native) 100 { 101 return new Counter((counter*)native.ToPointer()); 102 } 103 104 private unsafe void ~Counter() 105 { 106 <Module>.delete((void*)this.<backing_store>NativePtr, 4u); 107 } 108 109 private unsafe void !Counter() 110 { 111 <Module>.delete((void*)this.<backing_store>NativePtr, 4u); 112 } 113 114 public void Increment() 115 { 116 <Module>.counter.increment(this.<backing_store>NativePtr); 117 } 118 119 [HandleProcessCorruptedStateExceptions] 120 protected unsafe virtual void Dispose([MarshalAs(UnmanagedType.U1)] bool A_0) 121 { 122 if (A_0) 123 { 124 <Module>.delete((void*)this.<backing_store>NativePtr, 4u); 125 } 126 else 127 { 128 try 129 { 130 this.!Counter(); 131 } 132 finally 133 { 134 base.Finalize(); 135 } 136 } 137 } 138 139 public sealed override void Dispose() 140 { 141 this.Dispose(true); 142 GC.SuppressFinalize(this); 143 } 144 145 protected override void Finalize() 146 { 147 this.Dispose(false); 148 } 149 } 150}

投稿2018/03/27 00:00

編集2018/03/27 00:08
naohiro19_

総合スコア178

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

画像をサーバに投げて、サーバ側で処理して返すのが、ツラミは少なそう。
応答速度的には、ネイティブで処理したほうが早そうだけど。

投稿2018/03/26 08:25

kiichi54321

総合スコア1984

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

C#からC++のdllを呼び出すことは可能です。

https://qiita.com/ask/items/ee2ff5b8706effc0c3d8

C#版OpenCVはイマイチ使いづらいという話を聞いたことがあります。(ソースなし)
C++側でOpenCVをいろいろ操作して、結果だけC#側に返すのがやりやすいと思います。

投稿2018/03/26 04:47

kazto

総合スコア7196

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

taichaso

2018/03/27 00:14

回答ありがとうございます。 考えていた方法で間違えなさそうなのでC#からC++の.dllを呼び出すことについて学習してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問