kinect2.0 基礎篇第3篇 用C#在Visual Studio上編寫把深度圖像轉換成彩色圖像


本示例實現的功能有:有兩個Radiobutton控件  選一個,點擊啟動按鈕,

第一個是將深度圖像轉換成彩色圖像

第二個是將深度圖像做一些簡單處理(例如太暗的調白一點)

 

涉及到一點遙感圖像處理知識,將深度數據值轉換為色調和飽和度

遙感圖像處理那塊不懂,有興趣的自己可以研究研究,代碼的基於kinect1的教程,慢慢嘗試出來的,雖然功能實現了,但是原理還不是很懂

<Window x:Class="EnhancedDepthWPF.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:EnhancedDepthWPF"
        mc:Ignorable="d"
        Title="MainWindow" Height="520" Width="525">
    <Grid Background="Gray"  Width="512" Height="500" >
        <Grid VerticalAlignment="Top">
            <Grid HorizontalAlignment="Left">
                <RadioButton x:Name="radioBtnColor" Content="彩色的深度圖像" />
            </Grid>
            <Grid HorizontalAlignment="Center">
                <RadioButton x:Name="radioBtnCommon" Content="普通的深度圖像" IsChecked="True"/>
                </Grid>
            <Button x:Name="btnStartSensor"  Click="btnStartSensor_Click" Content="啟動kinect" HorizontalAlignment="Right"/>
        </Grid>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="9*"/>
                <ColumnDefinition Width="5*"/>
            </Grid.ColumnDefinitions>
            <Image x:Name="EnhancedDepthImage" Width="512" Height="424" Grid.ColumnSpan="2" Margin="3,0,3.4,-104"/>
        </Grid>
    </Grid>
</Window>
xaml代碼

 

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 EnhancedDepthWPF
{
    /// <summary>
    /// MainWindow.xaml 的交互邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        private KinectSensor sensor;
        private DepthFrameReader depthReader;
        private FrameDescription depthDescription;
        private WriteableBitmap depthBitmap;
        private Int32Rect depthRect;
        private int depthStride;
        ushort[] pixelData;
        Int32 depth;
        Int32 loThreshold = 50;  //最近能測距離50mm
        Int32 hiThreshold = 450;  //最遠能測距離450mm
        Int32 bytesPerPixel = 4;  //32位彩色圖像,4字節
        byte[] enhPixelData;  //用於保存彩色圖像的數據

        public MainWindow()
        {
            InitializeComponent();
            sensor = KinectSensor.GetDefault();
            depthReader = sensor.DepthFrameSource.OpenReader();
            depthReader.FrameArrived += depthFrame_FrameArrived;
            depthDescription = sensor.DepthFrameSource.FrameDescription;
           
            enhPixelData = new byte[depthDescription.Width * depthDescription.Height * bytesPerPixel];
        }

        private void depthFrame_FrameArrived(object sender, DepthFrameArrivedEventArgs e)
        {
            using (DepthFrame depthFrame = e.FrameReference.AcquireFrame())
            {
                if (depthFrame != null)
                {                    
                    depthFrame.CopyFrameDataToArray(pixelData);
                    if (radioBtnColor.IsChecked == true)
                    {
                        enhPixelData= DepthToColorImage(ref pixelData);
                        depthBitmap.WritePixels(depthRect, enhPixelData, depthStride, 0);
                    }
                    else
                    {
                        DepthCommonImage(ref pixelData);
                        depthBitmap.WritePixels(depthRect, pixelData, depthStride, 0);
                    }                    
                }
            }
        }

        private void DepthCommonImage(ref ushort[] pixelData)
        {
            //在數字光譜中0代表黑色,65536(16位灰階)表示白色
            for (int i = 0; i < pixelData.Length; i++)
            {
                depth = pixelData[i] >> 3; //把像素數據轉換成深度數據
                if (depth < loThreshold || depth > hiThreshold)  //正常識別范圍0.5m-4.5
                {
                    pixelData[i] = 35000;
                }
                else
                {
                    pixelData[i] += 20000;  //太黑了,把顏色整體調白一點
                }
                //pixelData[i] = (ushort)~pixelData[i];  //按位翻轉像素值
            }
        }

        private byte[] DepthToColorImage(ref ushort[] pixelData)
        {            
            byte[] rgb = new byte[3];
            Double hue;

            for (int i = 0, j = 0; i < pixelData.Length; i++, j += bytesPerPixel)
            {
                depth = pixelData[i] >> 3;
                if (depth < loThreshold || depth > hiThreshold)
                {
                    enhPixelData[j] = 0x00;
                    enhPixelData[j + 1] = 0x00;
                    enhPixelData[j + 2] = 0x00;
                }
                else
                {
                    hue = ((360 * depth / 0xFF) + loThreshold);
                    ConvertHslToRgb(hue, 100, 100, rgb);

                    enhPixelData[j] = rgb[2]; //Blue
                    enhPixelData[j + 1] = rgb[1]; //Green
                    enhPixelData[j + 2] = rgb[0]; //Red
                }
            }
            return enhPixelData;
        }
        /// <summary>
        /// 遙感圖像處理,將深度數據值轉換為色調和飽和度
        /// </summary>
        /// <param name="hue">色調</param>
        /// <param name="saturation">飽和度</param>
        /// <param name="lightness">亮度</param>
        /// <param name="rgb"></param>
        private void ConvertHslToRgb(Double hue, Double saturation, Double lightness, byte[] rgb)
        {
            Double red = 0.0;
            Double green = 0.0;
            Double blue = 0.0;
            hue = hue % 360.0;
            saturation = saturation / 100.0;
            lightness = lightness / 100.0;
            if (saturation == 0.0)
            { red = lightness; green = lightness; blue = lightness; }
            else
            {
                Double huePrime = hue / 60.0;
                Int32 x = (Int32)huePrime;
                Double xPrime = huePrime - (Double)x;
                Double L0 = lightness * (1.0 - saturation);
                Double L1 = lightness * (1.0 - (saturation * xPrime));
                Double L2 = lightness * (1.0 - (saturation * (1.0 - xPrime)));

                switch (x)
                {
                    case 0: red = lightness; green = L2; blue = L0; break;
                    case 1: red = L1; green = lightness; blue = L0; break;
                    case 2: red = L0; green = lightness; blue = L2; break;
                    case 3: red = L0; green = L1; blue = lightness; break;
                    case 4: red = L2; green = L0; blue = lightness; break;
                    case 5: red = lightness; green = L0; blue = L1; break;
                }
            }
            rgb[0] = (byte)(255.0 * red);
            rgb[1] = (byte)(255.0 * green);
            rgb[2] = (byte)(255.0 * blue);
        }

        private void btnStartSensor_Click(object sender, RoutedEventArgs e)
        {
            //存放深度圖像的字節數組的長度=幀長度*幀高度
            pixelData = new ushort[depthDescription.LengthInPixels];
            if (radioBtnColor.IsChecked == true)
            {
                depthBitmap = new WriteableBitmap(depthDescription.Width, depthDescription.Height, 96.0, 96.0, PixelFormats.Bgr32, null);
                //根據數據幀的寬高創建colorBitmap的實例
                this.depthRect = new Int32Rect(0, 0, this.depthBitmap.PixelWidth, depthBitmap.PixelHeight);
                this.depthStride = this.depthDescription.Width * 4;
                EnhancedDepthImage.Source = this.depthBitmap;
            }
            else
            {
                //位圖初始化,寬度,高度,96.0表示分辨率,像素格式
                depthBitmap = new WriteableBitmap(depthDescription.Width, depthDescription.Height, 96.0, 96.0, PixelFormats.Gray16, null);
                //存放圖像像素的矩形框
                depthRect = new Int32Rect(0, 0, depthBitmap.PixelWidth, depthBitmap.PixelHeight);               
                //步長:寬度*2(字節/像素)
                depthStride = depthDescription.Width * 2;
                EnhancedDepthImage.Source = depthBitmap;
            }
            sensor.Open();
        }
    }
}

 運行結果如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM