SlideShare a Scribd company logo
ARコンテンツ作成勉強会
C#ではじめようOpenCV
#AR_Fukuoka
今回の内容 (for Slide Share)
OpenCVを使ったカラートラッキングをやります
ただし・・・
画像処理プログラミングの基礎も勉強するため
ストレートに目的コンテンツには到達しません
あらかじめご了承ください
本日作成するコンテンツ
https://youtu.be/vnLiZFIe09I
Visual Studioを起動
プロジェクトを作成 (1/2)
①File
②New
③Project
プロジェクトを作成 (2/2)
①VisualC#
②Windows
③Windows Form Application
④OK
動作確認
Start
OpenCvSharpの導入 (1/4)
①Tools
②NuGet Package Manager
③Manage Nuget Package...
OpenCvSharpの導入 (2/4)
①Brows ②nuget.org
OpenCvSharpの導入 (3/4)
①OpenCVsharp3
②OpenCvSharp3 AnyCPU
③パッケージのチェックをON
④3.2.0.20170324
⑤Install
OpenCvSharpの導入 (4/4)
NuGetを閉じる
画像表示領域を作成 (1/5)
①ToolBoxタブ
②PictureBox
画像表示領域を作成 (2/5)
フォーム内をクリック
画像表示領域を作成 (3/5)
①PictureBoxをクリック
②Sizeを400,300
(なんでもOK)
画像表示領域を作成 (4/5)
BackgroundImageLayoutを
Zoomに変更
Zoomにするとアスペクト比を保持したままPictureBoxのサイズに合わせて画像を拡大・縮小
画像表示領域を作成 (5/5)
Formを選択してサイズを
PictureBoxに合わせる
Formのサイズはあとで変えるから適当でOK
Timerを用いた更新周期の設定
Timerを使うと任意に設定した間隔で処理(画像の取得・表示)を実行させられる
①ToolBoxタブ
②Timer
Timerを用いた更新周期の設定
①Form上をクリック
②Timerが追加される
➂Intervalを30[ms]
に変更(なんでもOK)
一定時間毎に呼び出される関数を作成
①Timerをダブルクリック
一定時間毎に呼び出される関数を作成
timer1_Tick関数が追加される
一定時間沖にtimer1_Tick関数の内部に書いた処理が実行される(予定)
Formが表示されたらTimerをスタートさせる
①Form1[Design]
②Form1をクリック
Formが表示されたらTimerをスタートさせる
①⚡をクリック
②Shownをダブルクリック
Formが表示されたらTimerをスタートさせる
namespace CVTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
}
private void Form1_Shown(object sender, EventArgs e)
{
timer1.Start(); //タイマーの動作を開始
}
}
}
①Form1_Shownが追加される
②自分で追加
Webカメラの画像を取得
using OpenCvSharp; //OpenCvSharpの機能をインポート
using OpenCvSharp.Extensions;
namespace CVTest
{
public partial class Form1 : Form
{
VideoCapture video = new VideoCapture(0); //Videoキャプチャ
Mat bgr; //カラー画像を扱うクラス
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
}
/*****以下省略*****/
Webカメラの画像を取得
VideoCapture video = new VideoCapture(0);;
Mat bgr;
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
bgr = video.RetrieveMat(); //カメラから画像を取得しbgrに記録
pictureBox1.BackgroundImage = bgr.ToBitmap();
bgr.Release(); //画像を記録したメモリを開放
}
private void Form1_Shown(object sender, EventArgs e)
{
timer1.Start();
}
画像を左右反転させよう
private void timer1_Tick(object sender, EventArgs e)
{
bgr = video.RetrieveMat();
bgr=bgr.Flip(FlipMode.Y);
pictureBox1.BackgroundImage = bgr.ToBitmap();
bgr.Release();
}
x
y
Flip
画像処理の過程を表示させよう
横方向に広げる
(大体2倍くらい)
画像処理の過程を表示させよう
PictureBoxをコピペ
pictureBox1 pictureBox2
画像処理用の画像を作成
VideoCapture video;
Mat bgr;
Mat src; //画像処理に用いる画像を保持
public Form1(){ /*省略*/ }
private void timer1_Tick(object sender, EventArgs e)
{
bgr = video.RetrieveMat();
bgr=bgr.Flip(FlipMode.Y);
ImageProcessing();
pictureBox1.BackgroundImage = bgr.ToBitmap();
pictureBox2.BackgroundImage = src.ToBitmap();
bgr.Release();
src.Release();
}
//以下の関数に画像処理のコードを書いていく
private void ImageProcessing()
{
src = bgr.Clone();
}
動作確認
OpenCVに慣れよう:グレースケール変換
Mat bgr;
Mat src; //画像処理に用いる画像を保持
public Form1(){ /*省略*/ }
private void timer1_Tick(object sender, EventArgs e)
{
bgr = video.RetrieveMat();
bgr=bgr.Flip(FlipMode.Y);
ImageProcessing();
pictureBox1.BackgroundImage = bgr.ToBitmap();
pictureBox2.BackgroundImage = src.ToBitmap();
bgr.Release();
src.Release();
}
private void ImageProcessing()
{
src = bgr.Clone();
src = bgr.CvtColor(ColorConversionCodes.BGR2GRAY);
}
CvtColorで画像変換
動作確認
グレースケール画像を二値化してみよう
0 255
0 255
0~255の輝度値を、ある値(しきい値)以上か未満かで分離することを二値化と呼ぶ。
画像処理すべき領域か否かをはっきり分けることができるため非常に重要なテクニック。
二値化の下準備
dstを表示
Mat src; //画像処理に用いる画像を保持
Mat dst; //二値化結果を保持
private void timer1_Tick(object sender, EventArgs e)
{
bgr = video.RetrieveMat();
bgr=bgr.Flip(FlipMode.Y);
ImageProcessing();
pictureBox1.BackgroundImage = bgr.ToBitmap();
pictureBox2.BackgroundImage = dst.ToBitmap();
bgr.Release();
src.Release();
dst.Release();
}
private void ImageProcessing()
{
src = bgr.CvtColor(ColorConversionCodes.BGR2GRAY);
dst = new Mat(bgr.Height, bgr.Width, MatType.CV_8U);
}
符号なし8bit(0~255)
二値化(ImageProcessing関数内)
src = bgr.CvtColor(ColorConversionCodes.BGR2GRAY);
dst = new Mat(bgr.Height, bgr.Width, MatType.CV_8U);
MatOfByte b_src = new MatOfByte(src);
MatOfByte b_dst = new MatOfByte(dst);
var index_src = b_src.GetIndexer();
var index_dst = b_dst.GetIndexer();
for(int y = 0; y < src.Height; y++)
{
for(int x = 0; x < src.Width; x++)
{
if (index_src[y, x] >= 100)
{
index_dst[y, x] = 255;
}
else
{
index_dst[y, x] = 0;
}
}
}
追加
動作確認
GUIでしきい値(Threshold)を変化させよう
Trackbar
GUIでしきい値(Threshold)を変化させよう
Trackbarを配置
GUIでしきい値(Threshold)を変化させよう
① Trackbarをクリックして
Propertiesを選択
③Maximumを255
TrackBarで入力できる値を0~255に設定
② をクリック
GUIでしきい値(Threshold)を変化させよう
①⚡をクリック
②Scrollをダブルクリック
TrackBarをスクロールしたときの挙動を記述する関数を生成
GUIでしきい値(Threshold)を変化させよう
Mat src;
Mat dst;
int th1;
/*省略*/
private void ImageProcessing ()
{
/*省略*/
for(int y = 0; y < src.Height; y++){
for(int x = 0; x < src.Width; x++){
if (index_src[y, x] >= th1){
index_dst[y, x] = 255;
}
else{
index_dst[y, x] = 0;
}
}
}
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
th1 = trackBar1.Value;
}
しきい値をth1に変更
trackBar1_Scroll関数が追加される
複数のしきい値を設定しよう
Trackbarをコピペ
複数のしきい値を設定しよう
① 2つめのTrackbarを
クリックしてPropertiesを選択
③Valueを255
2つめのTrackBarのデフォルト値を255に変更
② をクリック
複数のしきい値を設定しよう
①⚡をクリック
②Scrollをダブルクリック
TrackBarをスクロールしたときの挙動を記述する関数を生成
複数のしきい値を設定しよう
int th1;
int th2 = 255;
/*省略*/
private void ImageProcessing (){
/*省略*/
for(int y = 0; y < src.Height; y++){
for(int x = 0; x < src.Width; x++){
if (index_src[y, x] >= th1 && index_src[y, x] <= th2){
index_dst[y, x] = 255;
}
else{
index_dst[y, x] = 0;
}
}
}
}
/*省略*/
private void trackBar2_Scroll(object sender, EventArgs e){
th2 = trackBar2.Value;
}
2つめのしきい値を設定
trackBar2_Scroll関数が追加される
動作確認
色の抽出をしよう
【問題点】
 GrayScaleの場合は1変数なので抽出が容易
 色をR(赤)G(緑)B(青)での組み合わせで表現
した場合、特定の色の抽出はちょっと面倒。
 RGBでは色の境目を直線的に引くことも困難
【解決策】
 色空間としてHSVを使用する
 H(Hue)は色相で0~360°で表現される
※OpenCVの場合0~180
 S(Saturation)は彩度、0~100%で表現。
値が大きいほうがその色らしさが強い。
※OpenCVの場合0~255
 V(Value)は明度、 0~100%で表現。
値が大きいほど明るい
※OpenCVの場合0~255
GrayScale
RGB
HSV
色検出用の関数を作成
private void timer1_Tick(object sender, EventArgs e)
{
bgr = video.RetrieveMat();
bgr=bgr.Flip(FlipMode.Y);
ImageProcessing2();
pictureBox1.BackgroundImage = bgr.ToBitmap();
pictureBox2.BackgroundImage = dst.ToBitmap();
bgr.Release();
src.Release();
dst.Release();
}
private void ImageProcessing()
{
/*二値化処理*/
}
private void ImageProcessing2()
{
/*二値化処理*/
}
GrayScaleの二値化を行うImageProcessing関数をサンプルとして取っておく場合
②ImageProcessing2に変更
①コピペした後、関数名を
ImageProcessing2に変更
HSV変換と指定範囲の二値化
private void ImageProcessing2()
{
src = bgr.CvtColor(ColorConversionCodes.BGR2HSV);
dst = new Mat(bgr.Height, bgr.Width, MatType.CV_8U);
MatOfByte3 b_src = new MatOfByte3(src);
MatOfByte b_dst = new MatOfByte(dst);
var index_src = b_src.GetIndexer();
var index_dst = b_dst.GetIndexer();
for (int y = 0; y < src.Height; y++)
{
for (int x = 0; x < src.Width; x++)
{
if (index_src[y, x][0] >= th1 && index_src[y, x][0] <= th2)
{
index_dst[y, x] = 255;
}
else
{
index_dst[y, x] = 0;
}
/*以下省略*/
①変換方法を変更
②MatOfByte3に変更
③ index_src[y, x][0]
抽出したい色のHueの確認
private void ImageProcessing2()
{
src = bgr.CvtColor(ColorConversionCodes.BGR2HSV);
dst = new Mat(bgr.Height, bgr.Width, MatType.CV_8U);
MatOfByte3 b_src = new MatOfByte3(src);
MatOfByte b_dst = new MatOfByte(dst);
/*省略(二値化処理など)*/
this.Text = th1 * 2 + “~” + th2 * 2; //Hueの範囲を表示
}
抽出したい色に
関するHueの範囲を
メモしておこう
彩度S(Saturation)の設定もしよう
1つめのTrackbarをコピペ
彩度S(Saturation)の設定もしよう
②⚡をクリック
③Scrollをダブルクリック
TrackBarをスクロールしたときの挙動を記述する関数を生成
① 3つめのTrackbarを
右クリックしてPropertiesを選択
複数のしきい値を設定しよう
int th2 = 255;
int th3;
/*省略*/
private void ImageProcessing2 (){
/*省略*/
for(int y = 0; y < src.Height; y++){
for(int x = 0; x < src.Width; x++){
if (index_src[y, x][0] >= th1 && index_src[y, x][0] <= th2
&& index_src[y, x][1] >= th3){
index_dst[y, x] = 255;
}
else{
index_dst[y, x] = 0;
}
}
}
}
/*省略*/
private void trackBar3_Scroll(object sender, EventArgs e){
th3 = trackBar3.Value;
}
3つめのしきい値を設定
trackBar3_Scroll関数が追加される
抽出したい色のSaturationの確認
private void ImageProcessing2()
{
src = bgr.CvtColor(ColorConversionCodes.BGR2HSV);
dst = new Mat(bgr.Height, bgr.Width, MatType.CV_8U);
MatOfByte3 b_src = new MatOfByte3(src);
MatOfByte b_dst = new MatOfByte(dst);
/*省略(二値化処理など)*/
this.Text = th1 * 2 + "~" + th2 * 2 + ": " + th3;
}
抽出したい色に
関するSの値を
メモしておこう
動作確認
ノイズが残ることもある
Erodeを用いたノイズ除去
private void ImageProcessing2()
{
src = bgr.CvtColor(ColorConversionCodes.BGR2HSV);
dst = new Mat(bgr.Height, bgr.Width, MatType.CV_8U);
/*省略(二値化処理など)*/
dst = dst.Erode(null,null,2);
this.Text = th1 * 2 + "~" + th2 * 2+": "+th3;
}
白画素の縮小を2回行う
http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/index.html
成功例 やり過ぎ例
白画素の中から面積最大のもの(Blob)を探す
private void ImageProcessing2()
{
/*省略(HSV変換から二値化まで)*/
dst = dst.Erode(null, null, 2);
ConnectedComponents cc = Cv2.ConnectedComponentsEx(dst);
if (cc.Blobs.Count > 0) //0で落ちる場合は1に変更
{
ConnectedComponents.Blob blob = cc.GetLargestBlob();
if (blob.Area > 2000)
{
bgr.Circle(blob.Centroid, 30, Scalar.Cyan, 4);
}
}
this.Text = th1 * 2 + "~" + th2 * 2+": "+th3;
}
追
加
動作確認
円がついてくるはず
線を描く
List<OpenCvSharp.Point2d> list = new List<OpenCvSharp.Point2d>();
private void ImageProcessing2(){
/*省略(HSV変換から二値化、ノイズ除去まで)*/
ConnectedComponents cc = Cv2.ConnectedComponentsEx(dst);
if (cc.Blobs.Count > 0){
ConnectedComponents.Blob blob = cc.GetLargestBlob();
if (blob.Area > 2000){
list.Add(blob.Centroid);
for (int i = 1; i < list.Count; i++)
{
bgr.Line(list[i - 1], list[i], Scalar.Red, 3);
}
if (list.Count > 20)
{
list.RemoveAt(0);
}
}
}
this.Text = th1 * 2 + "~" + th2 * 2+": "+th3;
}
追
加
完成

More Related Content

DOCX
MEMOIRE DE STAGE
PDF
réaliser une plateforme d’automatisation et de génération des rapports de test
PDF
Fascicule de tp atelier développement web
PDF
HoloLensハンズオン:ハンドトラッキング&音声入力編
PPTX
[PFE] Master en ingénierie du logiciel
PDF
Rapport- Conception et réalisation d'une plateforme social learning
PDF
Deep Dive async/await in Unity with UniTask(EN)
PDF
Conception et développement d'une marketplace basée sur l'architecture micros...
MEMOIRE DE STAGE
réaliser une plateforme d’automatisation et de génération des rapports de test
Fascicule de tp atelier développement web
HoloLensハンズオン:ハンドトラッキング&音声入力編
[PFE] Master en ingénierie du logiciel
Rapport- Conception et réalisation d'une plateforme social learning
Deep Dive async/await in Unity with UniTask(EN)
Conception et développement d'une marketplace basée sur l'architecture micros...

What's hot (20)

PDF
Memory Management of C# with Unity Native Collections
PDF
Deep Learning : Application à la reconnaissance d’objets de classes multiples...
PDF
Conception et Réalisation Application Web Laravel PFE BTS
PDF
1601896849 rapport fluttercopie
PDF
Rapport projet: relisation d'une app desktop
DOCX
Rapport de PFE
PDF
Rapport de stage du fin d'étude
PDF
Introduction a Flutter
PDF
rapport de projet de fin d'étude_PFE
PDF
UniRx - Reactive Extensions for Unity(EN)
PDF
Outpatient Department System (OPD)
PDF
H3 2011 하이브리드 앱 아키텍쳐 및 개발방법
 
PPTX
Game Architecture with Scriptable Objects
PPTX
Conception et réalisation d’une application web (1).pptx
PDF
【Unity道場】AssetGraph入門 〜ノードを駆使しててUnityの面倒な手作業を自動化する方法〜
PDF
Mémoire - L'automatisation des tests fonctionnels - Emeline Simon
PDF
Application web php5 html5 css3 bootstrap
PDF
Rapport pfe talan_2018_donia_hammami
PPTX
非同期処理の基礎
Memory Management of C# with Unity Native Collections
Deep Learning : Application à la reconnaissance d’objets de classes multiples...
Conception et Réalisation Application Web Laravel PFE BTS
1601896849 rapport fluttercopie
Rapport projet: relisation d'une app desktop
Rapport de PFE
Rapport de stage du fin d'étude
Introduction a Flutter
rapport de projet de fin d'étude_PFE
UniRx - Reactive Extensions for Unity(EN)
Outpatient Department System (OPD)
H3 2011 하이브리드 앱 아키텍쳐 및 개발방법
 
Game Architecture with Scriptable Objects
Conception et réalisation d’une application web (1).pptx
【Unity道場】AssetGraph入門 〜ノードを駆使しててUnityの面倒な手作業を自動化する方法〜
Mémoire - L'automatisation des tests fonctionnels - Emeline Simon
Application web php5 html5 css3 bootstrap
Rapport pfe talan_2018_donia_hammami
非同期処理の基礎
Ad

Similar to ARコンテンツ作成勉強会:C#ではじめようOpenCV(カラートラッキング編) (20)

PDF
Halide による画像処理プログラミング入門
PDF
㉑CSSでアニメーション!その2
PDF
マイクロサービス時代の生存戦略 with HashiCorp
PDF
WSL2+docker+JupyterとVS Codeリモート環境の構築
PDF
Android上での3D(OpenGL)描画の基礎とNDKによる実践的高速化手法
PDF
Groovyで楽にSQLを実行してみよう
PDF
20100930 sig startups
PDF
3DCG(3Dコンピュータグラフィック)をWebGLで始めよう
PDF
10分で分かるr言語入門ver2.9 14 0920
PDF
JavaScript + CSS3を活用して スマートフォンサイト/アプリに 動きを付けてみよう
PPTX
T90 きっと怖くないmvvm & mvpvm
PPTX
3D で遊ぼう ~C#er も TypeScript で楽々 WebGL~
PDF
社内勉強会資料(Varnish Module)
PDF
FlutterをRenderObjectまで理解する
PDF
10分で分かるr言語入門ver2.10 14 1101
PDF
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
PDF
TypeScript と Visual Studio Code
PDF
Tokyor23 doradora09
PDF
Media Art II 2013 第5回:openFrameworks Addonを使用する
KEY
GroovyなAndroidテスト #atest_hack
Halide による画像処理プログラミング入門
㉑CSSでアニメーション!その2
マイクロサービス時代の生存戦略 with HashiCorp
WSL2+docker+JupyterとVS Codeリモート環境の構築
Android上での3D(OpenGL)描画の基礎とNDKによる実践的高速化手法
Groovyで楽にSQLを実行してみよう
20100930 sig startups
3DCG(3Dコンピュータグラフィック)をWebGLで始めよう
10分で分かるr言語入門ver2.9 14 0920
JavaScript + CSS3を活用して スマートフォンサイト/アプリに 動きを付けてみよう
T90 きっと怖くないmvvm & mvpvm
3D で遊ぼう ~C#er も TypeScript で楽々 WebGL~
社内勉強会資料(Varnish Module)
FlutterをRenderObjectまで理解する
10分で分かるr言語入門ver2.10 14 1101
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
TypeScript と Visual Studio Code
Tokyor23 doradora09
Media Art II 2013 第5回:openFrameworks Addonを使用する
GroovyなAndroidテスト #atest_hack
Ad

More from Takashi Yoshinaga (20)

PPTX
HoloLens2とMeta QuestではじめるWebXR
PPTX
【準備編】OculusQuest/HoloLens2対応WebXR開発
PPTX
ARコンテンツ作成勉強会( #AR_Fukuoka )紹介
PPTX
AI x WebAR: MediaPipeのハンドトラッキングを使ってみよう
PPTX
iPad LiDARで エンジニアカフェを3Dスキャン
PPTX
AI x OpenCV x WebAR: Selfie Segmentationを使ってみよう
PPTX
Web技術ではじめようAR/VRアプリ開発
PPTX
MRTKをNreal Lightに対応させてみた
PPTX
Nreal Lightハンズオン
PPTX
【準備編!】HoloLens 2/Oculus Quest対応WebXRハンズオン
PPTX
A-Frameで始めるWebXRとハンドトラッキング (HoloLens2/Oculus Quest対応)
PPTX
Holo-SDKハンズオン:はじめようヘッドトラッキングを用いた3D表現
PPTX
FUKUOKA Engineers Day 2021 発表資料:AR Fukuoka & HoloBox紹介
PPTX
Voxon Photonics VX1 で遊んでみた
PPTX
AR-Frame x AR.js入門
PPTX
AI x WebXR: フェイストラッキングを用いた擬似3D表現を解説!
PPTX
コロナ禍中のコミュニティ活動
PPTX
Project HoloBox
PPTX
AR Fukuoka紹介2020
PPTX
iPad LiDARで作ってみた in AR Fukuoka 忘年会2020
HoloLens2とMeta QuestではじめるWebXR
【準備編】OculusQuest/HoloLens2対応WebXR開発
ARコンテンツ作成勉強会( #AR_Fukuoka )紹介
AI x WebAR: MediaPipeのハンドトラッキングを使ってみよう
iPad LiDARで エンジニアカフェを3Dスキャン
AI x OpenCV x WebAR: Selfie Segmentationを使ってみよう
Web技術ではじめようAR/VRアプリ開発
MRTKをNreal Lightに対応させてみた
Nreal Lightハンズオン
【準備編!】HoloLens 2/Oculus Quest対応WebXRハンズオン
A-Frameで始めるWebXRとハンドトラッキング (HoloLens2/Oculus Quest対応)
Holo-SDKハンズオン:はじめようヘッドトラッキングを用いた3D表現
FUKUOKA Engineers Day 2021 発表資料:AR Fukuoka & HoloBox紹介
Voxon Photonics VX1 で遊んでみた
AR-Frame x AR.js入門
AI x WebXR: フェイストラッキングを用いた擬似3D表現を解説!
コロナ禍中のコミュニティ活動
Project HoloBox
AR Fukuoka紹介2020
iPad LiDARで作ってみた in AR Fukuoka 忘年会2020

ARコンテンツ作成勉強会:C#ではじめようOpenCV(カラートラッキング編)