普段はWeb関係のコードを書いていますが、今回いろいろな事情がありWindowsアプリを作成しました。
私のC#のスキルですが、
- 会社でUnity(C#)を使ったゲームを2年作った
- Windows/Macどちらも動く.NET Coreで動くバッチを作成した
という経歴なのでWindowsのアプリは実は初めて作りました。
というわけで、自分自身の備忘録を兼ねてWindowsのアプリを作る方法を1から解説していこうと思います。
完成品
とってもシンプルなQRコードリーダーです。
- QRコードを読み込んだら
- テキストファイルに書き込み
- 書き込んだファイルをメモ帳で開く
という処理を行います。
実装手順
参考資料・実装したコード
今回以下の記事を参考にしました(カメラ実装部分なんてほぼコピペ…)
【カメラ導入】OpencCvSharpでWebカメラの映像をキャプチャして保存する
【QRコード読み込み】ZXing.NETでQRコードやバーコードを解析するには?[C#/VB]
【実装したコード】https://github.com/belltreeSzk/qrcode-decoder/blob/master/QR-Reader-formapp/Form1.cs
環境構築・カメラの読み取り
開発環境は Visual Studio 2019 です。
今回は OpenCvSharp というライブラリを使用して、カメラを利用します。
カメラ導入の資料を参考にベースを作っていきましょう。
- Windowsフォームアプリケーション(.NET Framework)でのプロジェクトの作成
- PictureBoxの配置・イベントの設定
- NuGetでOpenCvSharpのインポート
- Form1.csの内容をコピペ
補足: 2.の配置やイベントの設定によってForm1.csに関数が追加されていくため、順番通りに進めていくことをオススメします。
カメラが認識されない場合(『camera was not found!』が出る場合)
Webカメラを接続しているのにカメラが認識されない場合、以下の原因が考えられます。
- そもそもOSがWebカメラを認識していない
- 他のアプリケーションで既にカメラを利用している
- 外部接続のWebカメラを使用している
Webカメラが認識されない場合は Windows 10のパソコンでWebカメラが動作しない、認識されない場合の設定・対処方法 などのページを参考にWindowsでカメラを認識させてください。
他のアプリケーションで既にカメラを利用している場合もWebカメラが認識しない場合があります。
私の場合は、Slackでビデオ通話やZoomをしながらプログラムを動かそうとしたところ認識できなかったため、もしも他のアプリケーションでWebカメラを利用しているにも関わらずカメラが認識されない場合はカメラが他のアプリケーションで使われていないか確認してみましょう。
また外部接続のWebカメラを使用している場合、以下の処理で正しくWebカメラを取得できません。
//カメラ画像取得用のVideoCapture作成
capture = new VideoCapture(0);
0番目のカメラは内蔵カメラという割り振りになっており、1番目以降は外部接続のWebカメラとなっています。
もしも利用したいカメラが外部接続だった場合、1以降のインデックスを指定する必要があります。
私は以下のように実装して、とりあえずどれかのWebカメラがヒットするように実装しました。
for (int i = 0, max = 10; i < max; i++) {
//カメラ画像取得用のVideoCapture作成
capture = new VideoCapture(i); // 0がインカメ, 1以降がウェブカメラ
if (capture.IsOpened())
{
break;
}
}
QRコードの読み取り
QRコードは ZXing.Net というライブラリを利用して変換します。
GitHubのREADMEにサンプルコードが紹介されていますが、BarcodeReaderというクラスのインスタンスにBitmap形式のQRコードの画像をDecodeで送信すると文字列に変換してくれます。
OpenCVSharpでカメラで取得した画像をBitmap形式の画像を生成してframeという変数に格納しているため、そのままQRコードを読み込んで解析を行います。
/// <summary>
/// QRコードの解析
/// </summary>
private String scanQRcode() {
String text = null;
try {
Result result = reader.Decode(frame.ToBitmap());
if (result != null && prevData != result.Text) {
text = result.Text;
prevData = text;
}
} catch (Exception exception) {
throw exception;
}
return text;
}
ZXingでNullReferenceExceptionが出る
実は2020年9月現在、最新バージョンのZXing.Netを使用しているとNullReferenceExceptionが出る不具合があります。
既にGitHubのIssueに投稿されているのですが、最新バージョンで起きるようです。
本来はプルリクを出して修正出来れば格好良かったのですが、まだそんなスキルはないのでバージョンを1つ下げて再インストールを行いましょう。エラーが発生しないようになります。
ZXingでエラー出てしまう場合参考にしてみてください!
細かい実装
あとは細かい実装を行います。
- QRコードの結果をテキストに出力する
- メモ帳を開く
/// <summary>
/// データの保存
/// </summary>
/// <param name="text"></param>
private void Save(String text) {
if (text == null) {
return;
}
String userProfilePath = Environment.GetEnvironmentVariable("UserProfile");
String logPath = @"\Desktop\log.txt";
// テキストに追加
File.AppendAllText(userProfilePath + logPath, text + Environment.NewLine);
// メモ帳を開く
System.Diagnostics.Process.Start("notepad.exe", userProfilePath + logPath);
}
Windowsの実装をする際に注意すべきなのはMacと違ってドライブが明確に分かれている点です。
String userProfilePath = Environment.GetEnvironmentVariable("UserProfile");
C:¥~~~ など直接書きたくなる気持ちは分かるのですが、ユーザーによって環境が変わり不具合の原因になるため極力コードからPathを作るようにしましょう。
配布できる状態にする
完全に上記ページの手順でexeファイルを作成します。
出来た生成物をzipにでもアーカイブして配布すればちゃんと1つのプログラムとして利用することが出来ます。
この記事を読んだ人に持ち帰ってほしい学び
知識があれば初めてでもテンポよく開発できる
今回、ほぼ初めてWindowsアプリを作成しましたが3時間弱でここまで作ることが出来ました。
NuGetの存在だったり、ライブラリの使い方だったり、モジュールのインポートなどこれまでの知識があればググるだけでほぼコピペで作れます。
「最初にどんな言語を勉強すればいいですか〜?」という質問がよくありますが、全然関係ない言語の知識が新しい言語の理解の助けになることはあるので、今回の経験を通して色々学んできた甲斐があったなぁと感じました。
特にパッケージマネージャー、モジュールのインポートあたりは理解だけ でもしておくと将来役に立つと思います。
使えるライブラリは使っていこう
ライブラリの便利さをまざまざと感じた開発でした。
映像処理のOpenCV、バーコードリーダーのZXing、本当に無料でここまで使っていいの?と思う便利さでした。
フルスクラッチで書くのは勉強としては良いですが、ライブラリを使うことで実装コストを下げるだけでなく、主要な機能のメンテナンスをライブラリ側に委託することが出来たりとメリットが色々あるため何かを作る際はライブラリはどんどん使っていきましょう(ライセンスに気をつけてください!)
ライブラリで不具合があったらGitHubのIssueを確認しよう
エラーが出たら、自分のコードを確認することをまず行ってほしいのですが、エラーの出ている場所が明らかに自分の書いた場所じゃないことがあります。
大体Googleで調べれば解決するのですが、それでも解決しない場合はGitHubのIssueを確認してみましょう。
Issueとはそのライブラリに起こっている不具合や要望の一覧です。
今回は新しいバージョンでエラーが発生していることが分かりましたが、逆に新しいバージョンで直っている不具合もIssueで確認できます。
Googleで検索しているだけでも9割くらいは問題解決しますが、GitHubのIssueも選択肢の1つとして覚えておくだけで解決出来る可能性が少しだけ上がります。
ぜひライブラリで不具合があったらGitHubのIssueを確認することは覚えておきましょう。
ここまで読んで頂きありがとうございました!
コメント