溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C#怎樣實現(xiàn)視頻監(jiān)控系統(tǒng)

發(fā)布時間:2021-02-03 11:33:04 來源:億速云 閱讀:280 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要介紹C#怎樣實現(xiàn)視頻監(jiān)控系統(tǒng),文中介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們一定要看完!

  本系統(tǒng)監(jiān)控系統(tǒng),主要核心是使用AForge.NET提供的接口和插件(dll),感興趣的朋友也可以去他們官網(wǎng)查看文檔http://www.aforgenet.com/framework/documentation.html

  Talk is cheap,show me the code!

  系統(tǒng)初始化時,首先檢查工位的機臺是否開啟了攝像頭,具體檢測代碼如下:

/// <summary>
/// 監(jiān)控bind
/// </summary>
private void bind()
{
  try
  {
    FilterInfoCollection videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
    if (videoDevices.Count <= 0)
    {
      MessageBox.Show("請連接攝像頭");
      return;
    }
    else
    {
      CloseCaptureDevice();
      if (!Directory.Exists(path)) Directory.CreateDirectory(path);
 
      videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString);
      videoSource.VideoResolution = videoSource.VideoCapabilities[0];
      sourcePlayer.VideoSource = videoSource;
      sourcePlayer.Start();
    }
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message);
  }
}

  好了,攝像頭沒問題,咱在檢查網(wǎng)絡(luò)是否正常(這事兒可以交給運維,當(dāng)然也可以通過程序控制,具體校驗網(wǎng)絡(luò)代碼比比皆是,此處忽略,如有興趣的朋友可以在公眾號Call我一起探討),至于為什么要校驗網(wǎng)絡(luò),一部分是用于機臺系統(tǒng)的數(shù)據(jù)采集,另一部分就是錄制的視頻文件不可能存儲在工位機臺上,不然流水線和工位足夠多,豈不是一個工位一個幾天的查看視頻監(jiān)控嘛!咱這都是智能化時代,錄制的視頻可以保存在本地,不過為了方便起見,需要定時清理,定時上傳到服務(wù)器便于領(lǐng)導(dǎo)審查。視頻上傳到服務(wù)器一般用到最多的莫非兩種情況,1.網(wǎng)絡(luò)足夠穩(wěn)定,足夠快的可以直接和服務(wù)器開個磁盤映射(共享目錄),視頻錄制完后系統(tǒng)直接剪切到服務(wù)器保存即可。2.把不同時段錄制的視頻先存儲到本地,然后單獨開發(fā)個定時任務(wù)FTP定時上傳即可。今天先跟大家分享下第一種方法,第二種方法也比較簡單,有興趣的朋友可以公眾號call我一起探討。

  不知不覺又扯了一堆廢話,都是實在人,直接上源碼吧:

/// <summary>
/// 開啟或者關(guān)閉程序后將多余文件copy到相應(yīng)目錄,并開啟磁盤映射上傳到共享目錄
/// </summary>
private void CopyFilesToServer()
{
  try
  {
    //遍歷 當(dāng)前PC文件夾外是否存在視頻文件,如存在,移動到目標(biāo)目錄 
    string newPath = path + MacAddressPath + @"-Video\";
    if (!Directory.Exists(newPath)) Directory.CreateDirectory(newPath);
    //將上一次最后一個視頻文件轉(zhuǎn)入目錄
    var files = Directory.GetFiles(path, "*.wmv");
    foreach (var file in files)
    {
      FileInfo fi = new FileInfo(file);
      string filesName = file.Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault();
      fi.MoveTo(newPath + filesName);
    } 
  }
  catch (Exception ex)
  {
    //TODO:異常拋出
  }
  finally
  {
    uint state = 0;
    if (!Directory.Exists("Z:"))
    {
      //計算機名
      string computerName = System.Net.Dns.GetHostName();
      //為網(wǎng)絡(luò)共享目錄添加磁盤映射 
      state = WNetHelper.WNetAddConnection(computerName + @"\" + netWorkUser, netWorkPwd, netWorkPath, "Z:");
    }
    if (state.Equals(0))
    {
      //本地磁盤視頻文件copy到網(wǎng)絡(luò)共享目錄
      CopyFolder(path + MacAddressPath + @"-Video\", zPath); 
    }
    else
    {
      WNetHelper.WinExec("NET USE * /DELETE /Y", 0);
      throw new Exception("添加網(wǎng)絡(luò)驅(qū)動器錯誤,錯誤號:" + state.ToString());
    }
  }
}

  其中CopyFolder方法代碼如下:

#region 通過共享網(wǎng)絡(luò)磁盤映射的方式,講文件copy到指定網(wǎng)盤
 /// <summary>
 /// 通過共享網(wǎng)絡(luò)磁盤映射的方式,講文件copy到指定網(wǎng)盤
 /// </summary>
 /// <param name="strFromPath"></param>
 /// <param name="strToPath"></param>
 public static void CopyFolder(string strFromPath, string strToPath)
 {
   //如果源文件夾不存在,則創(chuàng)建
   if (!Directory.Exists(strFromPath))
   {
     Directory.CreateDirectory(strFromPath);
   } 
   if (!Directory.Exists(strToPath))
   {
     Directory.CreateDirectory(strToPath);
   } 
   //直接剪切moveto,本地不留副本
   string[] strFiles = Directory.GetFiles(strFromPath);
   //循環(huán)剪切文件,此處循環(huán)是考慮每日工作站最后一個文件無法存儲到根目錄,導(dǎo)致出現(xiàn)兩個視頻文件的問題
   for (int i = 0; i < strFiles.Length; i++)
   {
     //取得文件名,只取文件名,地址截掉。
     string strFileName = strFiles[i].Substring(strFiles[i].LastIndexOf("\\") + 1, strFiles[i].Length - strFiles[i].LastIndexOf("\\") - 1);
     File.Move(strFiles[i], strToPath + "DT-" + strFileName);
   } 
 }
 #endregion

   做完機臺檢查工作,也做好了視頻傳輸?shù)墓ぷ鳎酉聛砭褪且曨l錄制的主角戲了,完整錄制視頻源碼如下

/// <summary>
    /// videosouceplayer 錄像
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="image"></param>
    private void sourcePlayer_NewFrame(object sender, ref Bitmap image)
    {
      try
      { 
        //寫到屏幕上的時間
        g = Graphics.FromImage(image);
        SolidBrush drawBrush = new SolidBrush(Color.Yellow);

        Font drawFont = new Font("Arial", 6, System.Drawing.FontStyle.Bold, GraphicsUnit.Millimeter);
        int xPos = image.Width - (image.Width - 15);
        int yPos = 10;

        string drawDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        g.DrawString(drawDate, drawFont, drawBrush, xPos, yPos);

        //save content
        string videoFileName = dt.ToString("yyyy-MM-dd HHmm") + ".wmv";

        if (TestDriveInfo(videoFileName)) //檢測硬盤空間足夠
        {
          if (!stopREC)
          {
            stopREC = true;
            createNewFile = true; //這里要設(shè)置為true表示要創(chuàng)建新文件
            if (videoWriter != null) videoWriter.Close();
          }
          else
          {
            //開始錄像
            if (createNewFile)
            {
              //第二次錄像不一定是第二次開啟軟件時間(比如:連續(xù)多小時錄制),所以應(yīng)該重新給新錄制視頻文件重新賦值命名
              dt = DateTime.Now;
              videoFileFullPath = path + dt.ToString("yyyy-MM-dd HHmm") + ".wmv";//videoFileName;

              createNewFile = false;
              if (videoWriter != null)
              {
                videoWriter.Close();
                videoWriter.Dispose();
              }

              videoWriter = new VideoFileWriter();
              //這里必須是全路徑,否則會默認(rèn)保存到程序運行根據(jù)錄下了
              videoWriter.Open(videoFileFullPath, image.Width, image.Height, 30, VideoCodec.WMV1);
              videoWriter.WriteVideoFrame(image);
            }
            else
            {
              if (videoWriter.IsOpen)
              {
                videoWriter.WriteVideoFrame(image);
              }
              if (dt.AddMinutes(1) <= DateTime.Now)
              { 
                createNewFile = true;
                //modify by stephen,每次寫入視頻文件后,即刻更新結(jié)束時間戳,并存入指定文件夾(目的:如果只有關(guān)閉的時候處理此操作,就會出現(xiàn)大于1小時的視頻文件無法更新結(jié)束時間戳,且無法轉(zhuǎn)入指定文件夾)
                if (videoWriter != null)
                {
                  videoWriter.Close();
                  videoWriter.Dispose();
                }
                string newPath = path + MacAddressPath + @"-Video\";
                if (!Directory.Exists(newPath)) Directory.CreateDirectory(newPath);
                string newStr = newPath + dt.ToString("yyyyMMddHHmm") + "-" + DateTime.Now.ToString("yyyyMMddHHmm") + ".wmv";
                FileInfo fi = new FileInfo(videoFileFullPath);
                fi.MoveTo(newStr); 
                ////轉(zhuǎn)移到網(wǎng)路目錄
                //CopyFilesToServer();
              }
            }
          }
        }

      }
      catch (Exception ex)
      {
        videoWriter.Close();
        videoWriter.Dispose();
      }
      finally
      {

        if (this.g != null) this.g.Dispose();
      }

    }

      其中TestDriveInfo方法是用來獲取保存視頻的磁盤信息的,具體代碼如下:

#region 獲取保存視頻的磁盤信息
 /// <summary>
 /// 獲取保存視頻的磁盤信息
 /// </summary>
 bool TestDriveInfo(string n)
 {
   try
   {
     DriveInfo D = DriveInfo.GetDrives().Where(a => a.Name == path.Substring(0, 3).ToUpper()).FirstOrDefault();
     Int64 i = D.TotalFreeSpace, ti = unchecked(50 * 1024 * 1024 * 1024);
     if (i < ti)
     {
       DirectoryInfo folder = new DirectoryInfo(path + MacAddressPath + @"-Video\");
       //modify by stephen,驗證當(dāng)前指定文件夾是否存在元素
       if (folder.Exists)
       { 
         var fisList = folder.GetFiles("*.wmv").OrderBy(a => a.CreationTime); 
         if (fisList.Any())
         {
           List<FileInfo> fis = fisList.ToList();
           if (fis.Count > 0 && fis[0].Name != n)
           {
             File.Delete(fis[0].FullName);
           }
         }
       } 
     }
   }
   catch (Exception ex)
   {
     MessageBox.Show(ex.Message, "處理硬盤信息出錯");
     return false;
   }
   return true;
 }
 #endregion

    當(dāng)然,如果工位師傅錄入產(chǎn)品信息有疑問的話,也可以利用系統(tǒng)截圖來保留證據(jù),這個是我自己畫蛇添足的功能,反正是為了方便嘛,別耽誤了工位師傅的辦事效率,利用攝像頭截圖代碼如下:

try
{ 
  string pathp = $@"{Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)}\";
  if (!Directory.Exists(pathp)) Directory.CreateDirectory(pathp);
  if (sourcePlayer.IsRunning)
  {
    BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
   sourcePlayer.GetCurrentVideoFrame().GetHbitmap(),
   IntPtr.Zero,
   Int32Rect.Empty,
   BitmapSizeOptions.FromEmptyOptions());
    PngBitmapEncoder pE = new PngBitmapEncoder();
    pE.Frames.Add(BitmapFrame.Create(bitmapSource));
    string picName = $"{pathp}{DateTime.Now.ToString("yyyyMMddHHmmssffffff")}.jpg";
    if (File.Exists(picName))
    {
      File.Delete(picName);
    }
    using (Stream stream = File.Create(picName))
    {
      pE.Save(stream);
    }
  }
}
catch (Exception ex)
{
  MessageBox.Show(ex.Message);
}

    代碼比較簡單,就不寫備注了。當(dāng)然部署系統(tǒng)的時候也不是一帆風(fēng)順,有的工廠或者倉庫會購買第三方的攝像頭,礙于工位環(huán)境,攝像頭有可能與機臺角度偏差較大,所以我又畫蛇添足的了校驗攝像頭的小功能,可以左右90°上下180°畫面翻轉(zhuǎn),具體代碼如下:

#region 設(shè)置攝像頭旋轉(zhuǎn)調(diào)整
 if (image != null)
 {
   RotateFlipType pType = RotateFlipType.RotateNoneFlipNone;
   if (dAngle == 0)
   {
     pType = RotateFlipType.RotateNoneFlipNone;
   }
   else if (dAngle == 90)
   {
     pType = RotateFlipType.Rotate90FlipNone;
   }
   else if (dAngle == 180)
   {
     pType = RotateFlipType.Rotate180FlipNone;
   }
   else if (dAngle == 270)
   {
     pType = RotateFlipType.Rotate270FlipNone;
   } 
   // 實時按角度繪制
   image.RotateFlip(pType);
 }
 #endregion

  當(dāng)然,站在公司角度,為了防止工位師傅手誤(誠心)關(guān)掉視頻監(jiān)控程序,我們也可以從程序的角度來防患于未然,比如禁用程序的關(guān)閉按鈕,禁用工具欄右鍵程序圖標(biāo)關(guān)閉程序的操作。

   我們可以重寫窗口句柄來防止,具體代碼如下:

#region 窗口句柄重寫,禁用窗體的關(guān)閉按鈕   
private const int CP_NOCLOSE_BUTTON = 0x200;
protected override CreateParams CreateParams
{
  get
  {
    CreateParams myCp = base.CreateParams;
    myCp.ClassStyle = myCp.ClassStyle | CP_NOCLOSE_BUTTON;
    return myCp;
  }
}

以上是“C#怎樣實現(xiàn)視頻監(jiān)控系統(tǒng)”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI