zoukankan      html  css  js  c++  java
  • WPF实现摄像头镜像翻转

    之前的项目需要镜像翻转摄像头视频,使用Aforge.Net来处理视频。

    一开始考虑直接从Aforge.Net读取没一帧视频图片,然后复制给WPF的Image控件,这种方法基本很卡,所以放弃了。

    考虑到Aforge.net 返回的图片是Bitmap的,所以打算直接在WPF中嵌入Winform的picturebox来实现视频。

    【注意】如果在WPF中嵌入Winform窗口是不可透明的。

    【Xaml】

    <Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" WindowState="Normal" Background="Black"
    WindowStyle="None" BorderThickness="0"
    Left="0" Top="0" WindowStartupLocation="Manual"
    xmlns:wfi ="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
    xmlns:winform="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
    >
    <wfi:WindowsFormsHost x:Name="video" >
    <winform:PictureBox x:Name="pb" SizeMode="StretchImage" BackColor="Black" ForeColor="Black"/>
    </wfi:WindowsFormsHost>
    </Window>

    【c#代码】

    #region << Field >>
    private VideoCaptureDevice VCD;
    private static double VideoResolutionWidth = 1280;
    #endregion
    [DllImport("user32.dll", EntryPoint = "SetWindowLongA", SetLastError = true)]
    private static extern int SetWindowLong(IntPtr hwnd, int nIndex, int dwNewLong);

    [System.Runtime.InteropServices.DllImport("User32.dll")]
    public static extern long GetWindowLong(IntPtr handle, int style);
    public const int GWL_STYLE = -16;
    public const int GWL_EXSTYLE = -20;
    public const long WS_CAPTION = 0x00C00000L;
    public const long WS_CAPTION_2 = 0X00C0000L;
    private static int VideoClipXPos = 0;
    private static int VideoClipWidth = 0;

    public static System.Drawing.Bitmap CurrentPhoto = null;
    public MainWindow()
    {
    InitializeComponent();
    this.Loaded += MainWindow_Loaded;
    this.Closing += MainWindow_Closing;
    }

    void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
      StopCamera(true);
    }

    private void StopCamera(bool flag)
    {
    if (flag)
    VCD.Stop();
    else
    VCD.Start();
    }

    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
    this.Width = 1080;
    this.Height = 1920;
    this.grid.Width = 809;
    this.grid.Height = 1082;
    SetPhotoView();
    //this.pb.Width = 3413;
    //this.pb.Height = 1920;
    // this.video.Margin = new Thickness(-666, 0, 0, 0);

    // this.Left = -(3413 - 1080) / 2;
    var videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);

    if (videoDevices.Count != 0)
    {
    VCD = new VideoCaptureDevice(videoDevices[0].MonikerString);
    foreach (var item in VCD.VideoCapabilities)
    {
    if (item.FrameSize.Width == VideoResolutionWidth)
    {
    VCD.VideoResolution = item;
    VCD.NewFrame += new AForge.Video.NewFrameEventHandler(videoSource1_NewFrame);
    VCD.VideoSourceError += new AForge.Video.VideoSourceErrorEventHandler(videoSource1_VideoSourceError);
    VCD.Start();
    break;
    }
    }
    }
    ///设置窗口无边框
    IntPtr windowHandle = new WindowInteropHelper(this).Handle;
    long oldstyle = GetWindowLong(windowHandle, GWL_STYLE);
    SetWindowLong(windowHandle, GWL_STYLE, (int)(oldstyle & (~(WS_CAPTION | WS_CAPTION_2))));
    }

    private void SetPhotoView()
    {
    VideoClipWidth = 536;
    VideoClipXPos = (1280 - VideoClipWidth) / 2;
    }

    void videoSource1_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
    {
    bool isGood = true;
    System.Drawing.Bitmap img = (System.Drawing.Bitmap)eventArgs.Frame.Clone(new System.Drawing.Rectangle(VideoClipXPos, 0, VideoClipWidth,
    eventArgs.Frame.Height),
    System.Drawing.Imaging.PixelFormat.Undefined);

    this.Dispatcher.BeginInvoke(new Action(() =>
    {

    try
    {
    img.RotateFlip(System.Drawing.RotateFlipType.RotateNoneFlipX);
    }
    catch (Exception e)
    {
    isGood = false;
    }

    if (isGood)
    {
    if (this.pb.Image != null)
    {
    this.pb.Image.Dispose();
    this.pb.Image = null;
    }
    this.pb.Image = img;
    CurrentPhoto = img;
    }
    else
    {
    img.Dispose();
    }

    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
    }));
    }

    void videoSource1_VideoSourceError(object sender, AForge.Video.VideoSourceErrorEventArgs eventArgs)
    {

    }
    }

    上诉代码是实现特定区域的视频截取,这种方法在1080p,和1920*2  1080 的分辨率下不卡,(测试机器是i5,4G内存的)

    为了不卡,肯定会丢帧,但是还是能接受的。

    其实最好的办法是将窗体的handle,传给c++来进行视频绘制。 但一般情况下,我觉得这种方法够用了。

  • 相关阅读:
    AWS EC2 优化 CPU 选项
    chrome 向群组中添加标签页
    Hadoop中TeraSort算法分析
    hadoop —— teragen & terasort
    spark本地读取写入s3文件
    将 Spark Streaming 的结果保存到 S3
    ipython notesbook 默认路径修改
    Python操作MongoDB
    python读取excel,数字都是浮点型,日期格式是数字的解决办法
    flask-profiler的使用
  • 原文地址:https://www.cnblogs.com/qiurideyun/p/4529263.html
Copyright © 2011-2022 走看看