Monday, April 13, 2015

การประมวลผลภาพจาก Kinect ตัวอย่างการปรับค่าสีด้วย slider

ลองมาสร้าง slider เพื่อใช้ปรับค่าสีกันครับ

ตัวอย่างก่อนปรับ

ตัวอย่างหลังปรับเพิ่มค่าสีน้ำเงิน

ก่อนอื่นก็ไปสร้างหน้าอินเตอร์เฟสก่อนครับ โดยไปปรับแก้ไฟล์ XAML ให้ได้ประมาณนี้
<Window x:Class="KinectCam.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
    <StackPanel Orientation="Horizontal">
        <Image Name="kinectVideo" Width="440"/>
        <Slider Name="BlueSlider" Background="Blue" Maximum="255" Minimum="-255" Orientation="Vertical" ValueChanged="BlueSlider_ValueChanged"/>
        <Slider Name="GreenSlider" Background="Green" Maximum="255" Minimum="-255" Orientation="Vertical" ValueChanged="GreenSlider_ValueChanged"/>
        <Slider Name="RedSlider" Background="Red" Maximum="255" Minimum="-255" Orientation="Vertical" ValueChanged="RedSlider_ValueChanged"/>
    </StackPanel>
</Window>

สังเกตว่าเรากำหนดให้ช่วงของ slider คือ -255 ถึง 255

หลักการค่อนข้างตรงไปตรงมาครับ เมื่อขยับ slider ก็ให้หาว่าค่าของ slider เป็นเท่าไหร่ สมมติเรียกว่าค่า offset

จากนั้นค่าของสีใหม่ = สีเดิม + offset
ถ้าค่านี้เกิน 255 ก็ให้เป็น 255 หรือถ้าต่ำกว่า 0 ก็ให้เป็น 0 ซึ่งเราเรียกวิธีการนี้ว่า Clamping หรือ Clipping ครับ

โค้ดทั้งหมดก็เพิ่มมานิดหน่อยจากของเดิมดังนี้ครับ
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 Microsoft.Kinect;

namespace KinectCam
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        KinectSensor myKinect;
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //Check if there is any connecting Kinect
            if (KinectSensor.KinectSensors.Count == 0)
            {
                MessageBox.Show("No Kinect detected!", "Error");
                //end this app
                Application.Current.Shutdown();
            }

            //Try to initialize Kinect
            try
            {
                //Get the first Kinect connected to this computer
                myKinect = KinectSensor.KinectSensors[0];
                //Enable the color video stream
                myKinect.ColorStream.Enable();
                //Start the sensor
                myKinect.Start();
            }
            catch
            {
                MessageBox.Show("Initialize Kinect failed!", "Error");
                //end this app
                Application.Current.Shutdown();
            }

            //Video event handler
            myKinect.ColorFrameReady += new EventHandler<ColorImageFrameReadyEventArgs>(myKinect_ColorFrameReady);           
        }

        //color value
        private int blueOffset = 0;
        private int greenOffset = 0;
        private int redOffset = 0;

        //color data array
        byte[] colorData = null;
        WriteableBitmap imageBitmap = null;
        void myKinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
        {
            using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
            {
                //if get new video frame
                if (colorFrame == null)
                    return;
                //create an array of pixel data
                if(colorData==null)
                    colorData = new byte[colorFrame.PixelDataLength];
                //extract pixel data from the frame to the array
                colorFrame.CopyPixelDataTo(colorData);

                //------------------------------------------------------
                //modify the pixel data
                //0=Blue,1=Green,2=Red,3=Alpha
                int newValue = 0;
                for (int i = 0; i < colorData.Length; i = i + 4)
                {
                    //blue
                    newValue = colorData[i] + blueOffset;
                    //clamping
                    if (newValue > 255)
                        newValue = 255;
                    if (newValue < 0)
                        newValue = 0;
                    colorData[i] = (byte)(newValue);

                    //green
                    newValue = colorData[i + 1] + greenOffset;
                    if (newValue > 255)
                        newValue = 255;
                    if (newValue < 0)
                        newValue = 0;
                    colorData[i + 1] = (byte)(newValue);

                    //red
                    newValue = colorData[i + 2] + redOffset;
                    if (newValue > 255)
                        newValue = 255;
                    if (newValue < 0)
                        newValue = 0;
                    colorData[i + 2] = (byte)(newValue);
                }
                //------------------------------------------------------

                //For the first video frame, no bitmap, create a writable bitmap of video size
                if (imageBitmap == null)
                {
                    imageBitmap = new WriteableBitmap(
                        colorFrame.Width,
                        colorFrame.Height,
                        96,     //dpiX
                        96,     //dpiY
                        PixelFormats.Bgr32,
                        null    //palette:none
                        );
                }
                //For other video frames, write video data to bitmap
                imageBitmap.WritePixels(
                    new Int32Rect(0, 0, colorFrame.Width, colorFrame.Height),
                    colorData,  //video data
                    colorFrame.Width * colorFrame.BytesPerPixel,      //stride
                    0   //offset to the array
                    );
                //set bitmap to image view
                kinectVideo.Source = imageBitmap;
            }
        }

        private void BlueSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            //get slider value
            blueOffset = (int)BlueSlider.Value;
        }

        private void GreenSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            //get slider value
            greenOffset = (int)GreenSlider.Value;
        }

        private void RedSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            //get slider value
            redOffset = (int)RedSlider.Value;
        }
    }
}

No comments:

Post a Comment