WPF 的攝像頭控件VideoCaptureElement 淺談


最近有個小項目要求用wpf實現顯示攝像頭畫面,並且能拍照,標注,切換畫面等等。

看了一下wpf有個自帶的庫WPFMediaKit.dll,里面有個攝像頭控件VideoCaptureElement ,好吧,就用它了

 

1、能拍照能書寫的話,就是在攝像頭控件上面套一個InkCanvas了,這個寫成一個自定義控件,命名為:CameraControl。

<UserControl x:Class="MediaKit.CameraControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-MediaKit"
             xmlns:wpfmedia="clr-namespace:WPFMediaKit.DirectShow.Controls;assembly=WPFMediaKit"
             mc:Ignorable="d" 
             x:Name="window">
        <Canvas Height="{Binding Height, ElementName=window, Mode=OneWay}" Width="{Binding Width, ElementName=window, Mode=OneWay}"   HorizontalAlignment="Center">
            <InkCanvas Name="ink" Canvas.Left="0" Canvas.Top="0"  RenderTransformOrigin="0.5,0.5"  VerticalAlignment="Center" HorizontalAlignment="Center"  Height="{Binding ElementName=vce,Path=ActualHeight,Mode=OneWay}" Width="{Binding ElementName=vce,Path=ActualWidth,Mode=OneWay}">
                <InkCanvas.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform/>
                        <TranslateTransform/>
                    </TransformGroup>
                </InkCanvas.RenderTransform>
            <wpfmedia:VideoCaptureElement  Height="1080"  x:Name="vce" Stretch="Fill"   RenderTransformOrigin="0.5,0.5"  >
                    
                </wpfmedia:VideoCaptureElement>
            </InkCanvas>
        </Canvas>
</UserControl>

2、拍照后能書寫的話,就是在圖片控件上面套一個InkCanvas了,這個也寫成一個自定義控件,命名為:ImgControl。

<UserControl x:Class="MediaKit.ImgControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:MediaKit"
             mc:Ignorable="d" 
             x:Name="window">
    <Canvas Height="{Binding Height, ElementName=window, Mode=OneWay}" Width="{Binding Width, ElementName=window, Mode=OneWay}"   HorizontalAlignment="Center">
        <InkCanvas Name="ink" Canvas.Left="0" Canvas.Top="0"  RenderTransformOrigin="0.5,0.5"   VerticalAlignment="Center" HorizontalAlignment="Center"  Height="{Binding ElementName=img,Path=ActualHeight}" Width="{Binding ElementName=img,Path=ActualWidth}" >
            <InkCanvas.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform />
                    <TranslateTransform/>
                </TransformGroup>
            </InkCanvas.RenderTransform>
            <Image Name="img" VerticalAlignment="Center"  HorizontalAlignment="Center" Height="{Binding Height, ElementName=window, Mode=OneWay}"  Stretch="UniformToFill">
                
            </Image>
        </InkCanvas>
    </Canvas>
</UserControl>

3、需要切換攝像頭和拍出來的照片,那我用一個list將用戶控件丟進去,當然為了統一操作的話,我就寫一個Class1類將CameraControl和ImgControl放進去。你需要有什么操作直接寫在Class1里面就能通用了,比如移動,修改InkCanvas狀態(書寫,擦除等),放大縮小等等。

 

#region ------構造函數------
        /// <summary>
        /// 添加攝像頭頁面
        /// </summary>
        public Class1()
        {
            pageIndex = 0;
            camera = new CameraControl();
            camera.ink.DefaultDrawingAttributes = PageManager.GetInstance()._defaultAttribuate;
            camera.ink.EditingMode = PageManager.GetInstance().editingMode;
            _inkCanvas = camera.ink;
            _vce = camera.vce;
            InitCameraThumb();//初始化幻燈片縮略圖
            this.Children.Add(camera);

            _inkCanvas.IsManipulationEnabled = true;
            _inkCanvas.Focusable = true;
            _inkCanvas.PreviewMouseDown += _inkCanvas_PreviewMouseDown;
            (((TransformGroup)_inkCanvas.RenderTransform).Children[2] as RotateTransform).Angle = CommonMethod.s_angle;//初始化旋轉
        }/// <summary>
        /// 添加圖片頁面
        /// </summary>
        /// <param name="source"></param>
        public Class1(ImageSource source, int index)
        {
            pageIndex = index;
            pic = new ImgControl(source);
            pic.ink.DefaultDrawingAttributes = PageManager.GetInstance()._defaultAttribuate;
            pic.ink.EditingMode = PageManager.GetInstance().editingMode;
            _inkCanvas = pic.ink;
            InitPageThumb();  //初始化幻燈片縮略圖
            pageThumb.contentSource = source;
            this.Children.Add(pic);

            _inkCanvas.IsManipulationEnabled = true;
            _inkCanvas.Focusable = true;
            _inkCanvas.PreviewMouseDown += _inkCanvas_PreviewMouseDown;
            (((TransformGroup)_inkCanvas.RenderTransform).Children[2] as RotateTransform).Angle = CommonMethod.s_angle;//初始化旋轉
        }
        #endregion ------構造函數------

4、需要切換顯示哪個的時候就在主界面的Grid里面操作

Grid.Children.Clear();

Grid.Children.Add(list[你要顯示的頁]);

 

做到這里你以為就完成了么?然后你會發現切換到圖片后,在切回去攝像頭,攝像頭是空白的,因為VideoCaptureElement 這個控件是不能被Remove再Add的,不然就需要重新加載,而且它本身加載就是比較慢的,有時候沒釋放完全還沒發加載(VideoCaptureElement 控件只能加載一個空閑中的攝像頭)

解決方案目前有2個,一個就是換控件咯,就不用VideoCaptureElement 了嘛,用C#的AForge,雖然他是C#的控件,雖然AForge在wpf嵌進去比較丑(沒有wpf的特性了:穿透),並且嵌進去步驟比較麻煩。

另外一個解決方案,留言吧,有需要的丟過去,不是很完美的解決方案。

另外有其他解決方案的大神們歡迎留言討論!


免責聲明!

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



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