2016年2月22日 星期一

影像處理(二值化、斷開、閉合)

成果

程式碼
<Window x:Class="Opening_and_Closing.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Opening_and_Closing"
        mc:Ignorable="d"
        Title="MainWindow" Height="562" Width="1247">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Label Content="二值化" Grid.Row="0" Grid.Column="0" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center" />
        <Label Content="斷開" Grid.Row="0" Grid.Column="1" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center" />
        <Label Content="閉合" Grid.Row="0" Grid.Column="2" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center" />
        <Image x:Name="img_threshold" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
        <Image x:Name="img_open" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top"/>
        <Image x:Name="img_close" Grid.Row="1" Grid.Column="2" HorizontalAlignment="Left" VerticalAlignment="Top"/>
    </Grid>
</Window>



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
using System.Drawing;
using System.IO;

namespace Opening_and_Closing
{
    /// &ltsummary&gt
    /// MainWindow.xaml 的互動邏輯
    /// &lt/summary&gt
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            //圖片路徑
            string contentDir = Directory.GetCurrentDirectory();
            int dirLength = contentDir.Length;
            if (contentDir.ToLower().EndsWith(@"\bin\x64\debug"))
                contentDir = contentDir.Remove(dirLength - 14, 14);
            else if (contentDir.ToLower().EndsWith(@"\bin\release"))
                contentDir = contentDir.Remove(dirLength - 12, 12);
            string path = contentDir + @"\j.png";

            //載入灰階的原圖
            Image&ltGray, Byte&gt grayImage = new Image&ltGray, byte&gt(path);

            //二值化,閥值設定為『灰階的平均值』
            Gray grayAge = grayImage.GetAverage();
            Image&ltGray, Byte&gt thresholdImage = grayImage.ThresholdBinary(grayAge, new Gray(255));
            img_threshold.Source = Emgu.CV.WPF.BitmapSourceConvert.ToBitmapSource(thresholdImage);

            //斷開Open
            Mat kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new System.Drawing.Size(5, 5), new System.Drawing.Point(-1, -1));
            Image&ltGray, Byte&gt openImage = thresholdImage.MorphologyEx(MorphOp.Open, kernel, new System.Drawing.Point(-1, -1), 2, BorderType.Default, new MCvScalar(255, 0, 0, 255));
            //Image&ltGray, Byte&gt openImage = thresholdImage.Dilate(1).Erode(1);
            img_open.Source = Emgu.CV.WPF.BitmapSourceConvert.ToBitmapSource(openImage);

            //斷開Open
            Image&ltGray, Byte&gt closeImage = thresholdImage.MorphologyEx(MorphOp.Close, kernel, new System.Drawing.Point(-1, -1), 2, BorderType.Default, new MCvScalar(255, 0, 0, 255));
            img_close.Source = Emgu.CV.WPF.BitmapSourceConvert.ToBitmapSource(closeImage);
        }
    }
}

影像處理(二值化、侵蝕、擴張)

成果


程式碼

&ltWindow x:Class="Eroding_and_Dilating.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Eroding_and_Dilating"
        mc:Ignorable="d"
        Title="MainWindow" Height="562" Width="1247"&gt
    &ltGrid&gt
        &ltGrid.RowDefinitions&gt
            &ltRowDefinition Height="50" /&gt
            &ltRowDefinition Height="*" /&gt
        &lt/Grid.RowDefinitions&gt
        &ltGrid.ColumnDefinitions&gt
            &ltColumnDefinition Width="*" /&gt
            &ltColumnDefinition Width="*" /&gt
            &ltColumnDefinition Width="*" /&gt
        &lt/Grid.ColumnDefinitions&gt
        &ltLabel Content="二值化" Grid.Row="0" Grid.Column="0" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center" /&gt
        &ltLabel Content="侵蝕" Grid.Row="0" Grid.Column="1" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center" /&gt
        &ltLabel Content="擴張" Grid.Row="0" Grid.Column="2" FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center" /&gt
        &ltImage x:Name="img_threshold" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Top"/&gt
        &ltImage x:Name="img_erode" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top"/&gt
        &ltImage x:Name="img_dilate" Grid.Row="1" Grid.Column="2" HorizontalAlignment="Left" VerticalAlignment="Top"/&gt
    &lt/Grid&gt
&lt/Window&gt

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Emgu.CV;
using Emgu.CV.Structure;
using System.Drawing;
using System.IO;

namespace Eroding_and_Dilating
{
    /// &ltsummary&gt
    /// MainWindow.xaml 的互動邏輯
    /// &lt/summary&gt
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            //使用DirectoryInfo類別初始化,並傳入專案執行檔所在目錄
            DirectoryInfo dir = new DirectoryInfo(Directory.GetCurrentDirectory());
            //Parent:移動至上層目錄
            string path = dir.Parent.Parent.Parent.FullName + @"\j.png";

            //載入灰階的原圖
            Image&ltGray, Byte&gt grayImage = new Image&ltGray, byte&gt(path);

            //二值化,閥值設定為『灰階的平均值』
            Gray grayAge = grayImage.GetAverage();
            Image&ltGray, Byte&gt thresholdImage = grayImage.ThresholdBinary(grayAge, new Gray(255));
            img_threshold.Source = Emgu.CV.WPF.BitmapSourceConvert.ToBitmapSource(thresholdImage);

            //侵蝕Erode,迭代2次侵蝕
            Image&ltGray, Byte&gt erodeImage = thresholdImage.Erode(2);
            img_erode.Source = Emgu.CV.WPF.BitmapSourceConvert.ToBitmapSource(erodeImage);

            //擴張Dilate,迭代2次擴張
            Image&ltGray, Byte&gt dilateImage = thresholdImage.Dilate(2);
            img_dilate.Source = Emgu.CV.WPF.BitmapSourceConvert.ToBitmapSource(dilateImage);
        }
    }
}

[EmguCV] 開啟彩色影像

成果























程式碼
&ltWindow x:Class="Basic_Program.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Basic_Program"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525"&gt
    &ltGrid&gt
        &ltButton x:Name="button" Content="Open" HorizontalAlignment="Left" Margin="411,150,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/&gt
        &ltImage x:Name="image" HorizontalAlignment="Left" Height="268" Margin="22,24,0,0" VerticalAlignment="Top" Width="371"/&gt
    &lt/Grid&gt
&lt/Window&gt

using Emgu.CV;
using Emgu.CV.Structure;
using System;
using System.Windows;
using System.Windows.Forms;

namespace Basic_Program
{
    /// 
    /// MainWindow.xaml 的互動邏輯
    /// 
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog Openfile = new OpenFileDialog();
            if (Openfile.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                Image My_Image = new Image(Openfile.FileName);
                image.Source = Emgu.CV.WPF.BitmapSourceConvert.ToBitmapSource(My_Image);
            }
        }
    }
}

2015年7月23日 星期四

Intel RealSense Camera "Color" in C#/WPF


Intel RealSense最基本的功能就是『彩色影像』,
其實Intel的SDK都有相當多Sample可以參考,
不過小弟資質駑鈍看不懂,所以爬文後才做出此功能。
成果圖


































(一)、. Build Events

























if "$(Platform)" == "x86" ( copy /y "$(RSSDK_DIR)\bin\win32\libpxccpp2c.dll" "$(TargetDir)" ) else (copy /y "$(RSSDK_DIR)\bin\x64\libpxccpp2c.dll" "$(TargetDir)" )

(二)、加入參考 libpxcclr.cs.dll





















※注意是\\...\x64 ,而不是\\...\win32

(三)、人機介面

  • StackPanel
  • Image:imgColorStream
  • Label:lblMessag































Mainwindow.xml 
<Window x:Class="ColorRealSense.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ColorRealSense"
        mc:Ignorable="d"
        Title="ColorRealSense" Height="635" Width="715"
        WindowStartupLocation="CenterScreen"
        Closing="Window_Closing"
        Loaded="Window_Loaded"
        ResizeMode="CanMinimize">
    <Grid>
        <StackPanel>
            <Image x:Name="imgColorStream" />
            <Label x:Name="lblMessage" Content="Label" HorizontalAlignment="Center" FontSize="24" />
        </StackPanel>
        <Image x:Name="image" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="260" Source="D:\C#\ColorRealSense\ColorRealSense\logo\logo.png"/>
    </Grid>
</Window>
(四)、Create the Utility Class

  • Right-click ColorRealSensein Solution Explorer.
  • Select Add, New Item…
  • Select Class and name it ConvertBitmap.cs.
  • Click the Add button.

using System;
using System.Windows.Media.Imaging;

namespace ColorRealSense
{
    class ConvertBitmap
    {
        [System.Runtime.InteropServices.DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr handle);
        public static IntPtr intPointer;
        private static BitmapSource bitmapSource;

        public static BitmapSource BitmapToBitmapSource(System.Drawing.Bitmap bitmap)
        {
            intPointer = bitmap.GetHbitmap();

            bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(intPointer,
                IntPtr.Zero,
                System.Windows.Int32Rect.Empty,
                System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());

            DeleteObject(intPointer);
            return bitmapSource;
        }
    }
}

(五)、後版設計
Mainwindow.xml.cs 
using System;
using System.Windows;
using System.Windows.Media;
using System.Threading;
using System.Drawing;

namespace ColorRealSense
{
    /// <summary>
    /// MainWindow.xaml 的互動邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        private Thread processingThread;
        private PXCMSenseManager senseManager;
        private PXCMHandModule hand;
        private PXCMHandConfiguration handConfig;
        private PXCMHandData handData;
        private PXCMHandData.GestureData gestureData;
        private bool handWaving;
        private bool handTrigger;
        private int msgTimer;

        public MainWindow()
        {
            InitializeComponent();
            handWaving = false;
            handTrigger = false;
            msgTimer = 0;

            // Instantiate and initialize the SenseManager
            senseManager = PXCMSenseManager.CreateInstance();
            senseManager.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_COLOR, 640, 480, 30);
            senseManager.EnableHand();
            senseManager.Init();

            // Configure the Hand Module
            hand = senseManager.QueryHand();
            handConfig = hand.CreateActiveConfiguration();
            handConfig.EnableGesture("wave");
            handConfig.EnableAllAlerts();
            handConfig.ApplyChanges();

            // Start the worker thread
            processingThread = new Thread(new ThreadStart(ProcessingThread));
            processingThread.Start();
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            processingThread.Abort();
            if (handData != null) handData.Dispose();
            handConfig.Dispose();
            senseManager.Dispose();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            lblMessage.Content = "(RealSense)";
        }

        private void ProcessingThread()
        {
            // Start AcquireFrame/ReleaseFrame loop
            while (senseManager.AcquireFrame(true) >= pxcmStatus.PXCM_STATUS_NO_ERROR)
            {
                PXCMCapture.Sample sample = senseManager.QuerySample();
                Bitmap colorBitmap;
                PXCMImage.ImageData colorData;

                // Get color image data
                sample.color.AcquireAccess(PXCMImage.Access.ACCESS_READ, PXCMImage.PixelFormat.PIXEL_FORMAT_RGB24, out colorData);
                colorBitmap = colorData.ToBitmap(0, sample.color.info.width, sample.color.info.height);

                // Retrieve gesture data
                hand = senseManager.QueryHand();

                if (hand != null)
                {
                    // Retrieve the most recent processed data
                    handData = hand.CreateOutput();
                    handData.Update();
                    handWaving = handData.IsGestureFired("wave", out gestureData);
                }

                // Update the user interface
                UpdateUI(colorBitmap);

                // Release the frame
                if (handData != null) handData.Dispose();
                colorBitmap.Dispose();
                sample.color.ReleaseAccess(colorData);
                senseManager.ReleaseFrame();
            }
        }

        private void UpdateUI(Bitmap bitmap)
        {
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate ()
            {
                if (bitmap != null)
                {
                    // Mirror the color stream Image control
                    imgColorStream.RenderTransformOrigin = new System.Windows.Point(0.5, 0.5);
                    ScaleTransform mainTransform = new ScaleTransform();
                    mainTransform.ScaleX = -1;
                    mainTransform.ScaleY = 1;
                    imgColorStream.RenderTransform = mainTransform;

                    // Display the color stream
                    imgColorStream.Source = ConvertBitmap.BitmapToBitmapSource(bitmap);

                    // Update the screen message
                    if (handWaving)
                    {
                        lblMessage.Content = "Hello World!";
                        handTrigger = true;
                    }

                    // Reset the screen message after ~50 frames
                    if (handTrigger)
                    {
                        msgTimer++;

                        if (msgTimer >= 50)
                        {
                            lblMessage.Content = "(Wave Your Hand)";
                            msgTimer = 0;
                            handTrigger = false;
                        }
                    }
                }
            }));
        }
    }
}

2015年7月14日 星期二

Android RadioGroup

成果展示:










































Project






程式碼:
mainwindow.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainwindowActivity">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:text="@string/lblSelect"
            android:id="@+id/lblSelect" />

        <RadioGroup
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:id="@+id/radiogroup"
            android:gravity="center">

            <RadioButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/rdoTemperature"
                android:id="@+id/radioButton1"
                android:checked="false" />

            <RadioButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/rdoPosition"
                android:id="@+id/radioButton2"
                android:checked="false" />

            <RadioButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/rdoLinear"
                android:id="@+id/radioButton3"
                android:checked="false" />
        </RadioGroup>

    </LinearLayout>

</RelativeLayout>
MainwindowActivity
package com.test.mytransform;

import android.content.Intent;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.RadioButton;
import android.widget.RadioGroup;


public class MainwindowActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mainwindow);
        RadioGroup radiogroup = (RadioGroup) findViewById(R.id.radiogroup);
        RadioButton radioButton1 = (RadioButton) findViewById(R.id.radioButton1);
        RadioButton radioButton2 = (RadioButton) findViewById(R.id.radioButton2);
        RadioButton radioButton3 = (RadioButton) findViewById(R.id.radioButton3);
        radiogroup.setOnCheckedChangeListener(listener);
    }

    private RadioGroup.OnCheckedChangeListener listener = new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {
            switch (checkedId)
            {
                case (R.id.radioButton1):
                    Intent intent1 = new Intent();
                    intent1.setClass(MainwindowActivity.this, Window1Activity.class);
                    startActivity(intent1);
                    MainwindowActivity.this.finish();
                    break;
                case (R.id.radioButton2):
                    Intent intent2 = new Intent();
                    intent2.setClass(MainwindowActivity.this, Window2Activity.class);
                    startActivity(intent2);
                    MainwindowActivity.this.finish();
                    break;
                case (R.id.radioButton3):
                    Intent intent3 = new Intent();
                    intent3.setClass(MainwindowActivity.this, Window3Activity.class);
                    startActivity(intent3);
                    MainwindowActivity.this.finish();
                    break;
            }
        }
    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_mainwindow, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}