2017-01-11 13 views
0

В настоящее время я пытаюсь объединить два отдельных изображения камеры в одно изображение как Anaglyph. Результат должен выглядеть примерно как this image here.Как смешивать стереоизображение с EmguCV?

Вот мой код, который я написал, чтобы захватить две камеры изображений и конвертирования их в черный & белый:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 
using Emgu.CV; 
using Emgu.CV.CvEnum; 
using Emgu.CV.Structure; 
using Emgu.Util; 

namespace CameraStereoCapture { 

    public partial class CameraStereoCapture : Form { 

     private bool captureInProgress; 

     private VideoCapture cameraLeft = null; 
     private VideoCapture cameraRight = null; 

     private Mat leftRawFrame; 
     private Mat rightRawFrame; 

     private Mat leftGrayFrame; 
     private Mat rightGrayFrame; 

     private Mat stereoFrame; 

     public CameraStereoCapture() { 
      InitializeComponent(); 
      CvInvoke.UseOpenCL = false; 
      try { 
       cameraLeft = new VideoCapture(1); 
       cameraLeft.ImageGrabbed += ProcessFrame; 
       cameraRight = new VideoCapture(0); 
       cameraRight.ImageGrabbed += ProcessFrame; 
      } catch (NullReferenceException ex) { 
       MessageBox.Show(ex.Message); 
      } 
      leftRawFrame = new Mat(); 
      rightRawFrame = new Mat(); 
      leftGrayFrame = new Mat(); 
      rightGrayFrame = new Mat(); 
      stereoFrame = new Mat(); 
     } 

     private void cmdCapture_Click(object sender, EventArgs e) { 
      if (cameraLeft != null) { 
       if (captureInProgress) { 
        // stop the capture 
        cmdCapture.Text = "Start Capture"; 
        cameraLeft.Pause(); 
        cameraRight.Pause(); 
       } else { 
        // start the capture 
        cmdCapture.Text = "Stop Capture"; 
        cameraLeft.Start(); 
        cameraRight.Start(); 
       } 
       captureInProgress = !captureInProgress; 
      } 
     } 

     private void ProcessFrame(object sender, EventArgs arg) { 
      // capture and cache image from left camera 
      if (cameraLeft != null && cameraLeft.Ptr != IntPtr.Zero) { 
       cameraLeft.Retrieve(leftRawFrame, 0); 
       imgLeft.Image = leftRawFrame; 
      } 
      // capture and cache image from right camera 
      if (cameraRight != null && cameraRight.Ptr != IntPtr.Zero) { 
       cameraRight.Retrieve(rightRawFrame, 0); 
       imgRight.Image = rightRawFrame; 
      } 
      // calculate stereo image by combining the left and right image 
      if (leftRawFrame != null && rightRawFrame!=null) { 
       CvInvoke.CvtColor(leftRawFrame, leftGrayFrame, ColorConversion.Bgr2Gray); 
       CvInvoke.CvtColor(rightRawFrame, rightGrayFrame, ColorConversion.Bgr2Gray); 
       // TODO: how to convert 'leftRawImage to Cyan' ??? 
       // TODO: how to convert 'rightRawImage to Magenta' ??? 
       CvInvoke.AddWeighted(leftGrayFrame, 0.5, rightGrayFrame, 0.5, 1.0, stereoFrame); 
       imgStereo.Image = stereoFrame; 
      } 
     } 

    } 

} 

Мой вопрос, как преобразовать серые изображения в Cyan и Magenta или Red и Blue (cp. Строки в фрагменте кода, которые обозначены как TODO:)?

ответ

0

Вот мое решение EmguCV для создания изображения Anaglyph с двух входов камеры. Два цветных изображения сначала преобразуются в серые изображения, а затем объединяются вместе с соответствующими цветовыми каналами конечного изображения RGB.

Преимущество этого метода заключается в том, что никакая информация не теряется по сравнению с методом, который извлекает только красный канал одного исходного изображения и зеленые/синие каналы другого исходного изображения.

#region Usings 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Emgu.CV; 
using Emgu.CV.CvEnum; 
using Emgu.CV.Structure; 
using Emgu.CV.Util; 
using Emgu.Util; 
#endregion 

namespace WallECtrl { 

    public delegate void ImageAvailable(Mat leftFrame, Mat rightFrame, Mat stereoFrame); 

    public class StereoEngine { 

     public event ImageAvailable ImageAvailableEvent; 

     private bool capturing; 
     private bool colorPreview; 

     private VideoCapture cameraLeft = null; 
     private VideoCapture cameraRight = null; 

     private Mat matLeftColourFrame; 
     private Mat matRightColourFrame; 
     private Mat matLeftGrayFrame; 
     private Mat matRightGrayFrame; 
     private Mat matStereoFrame; 

     public StereoEngine() { 
      CvInvoke.UseOpenCL = false; 
      cameraLeft = new VideoCapture(0); 
      cameraLeft.ImageGrabbed += ProcessFrame; 
      cameraRight = new VideoCapture(1); 
      cameraRight.ImageGrabbed += ProcessFrame; 
      matLeftColourFrame = new Mat(); 
      matRightColourFrame = new Mat(); 
      matLeftGrayFrame = new Mat(); 
      matRightGrayFrame = new Mat(); 
      matStereoFrame = new Mat(); 
     } 

     public bool Capturing { 
      get { 
       return capturing; 
      } 
     } 

     public bool ColorPreview { 
      get { 
       return colorPreview; 
      } 
      set { 
       colorPreview = value; 
      } 
     } 

     public void startCapture() { 
      if (cameraLeft != null && cameraRight != null) { 
       if (!capturing) { 
        cameraLeft.Start(); 
        cameraRight.Start(); 
        capturing = !capturing; 
       } 
      } 
     } 

     public void stopCapture() { 
      if (cameraLeft != null && cameraRight != null) { 
       if (capturing) { 
        cameraLeft.Pause(); 
        cameraRight.Pause(); 
        capturing = !capturing; 
       } 
      } 
     } 

     private void ProcessFrame(object sender, EventArgs arg) { 

      // capture and cache image from left camera 
      if (cameraLeft != null && cameraLeft.Ptr != IntPtr.Zero) { 
       cameraLeft.Retrieve(matLeftColourFrame, 0); 
      } 

      // capture and cache image from right camera 
      if (cameraRight != null && cameraRight.Ptr != IntPtr.Zero) { 
       cameraRight.Retrieve(matRightColourFrame, 0); 
      } 

      // calculate stereo image by combining the left and right image 
      if (matLeftColourFrame != null && matRightColourFrame!=null) { 

       CvInvoke.CvtColor(matLeftColourFrame, matLeftGrayFrame, ColorConversion.Bgr2Gray); 
       CvInvoke.CvtColor(matRightColourFrame, matRightGrayFrame, ColorConversion.Bgr2Gray); 

       using (VectorOfMat vm = new VectorOfMat(matRightGrayFrame, matRightGrayFrame, matLeftGrayFrame)) { 
        CvInvoke.Merge(vm, matStereoFrame); 
       } 

       // inform gui + network about new stereo image available 
       if(ImageAvailableEvent != null) { 
        if (colorPreview) { 
         ImageAvailableEvent(matLeftColourFrame, matRightColourFrame, matStereoFrame); 
        } else { 
         ImageAvailableEvent(matLeftGrayFrame, matRightGrayFrame, matStereoFrame); 
        } 
       } 

      } 

     } 

     public void exit() { 
      if(cameraLeft != null) { 
       cameraLeft.Stop(); 
       cameraLeft.Dispose(); 
      } 
      if (cameraRight != null) { 
       cameraRight.Stop(); 
       cameraRight.Dispose(); 
      } 
     } 

    } 

} 
1

Чтобы сделать Красно-Cyan Anaglyph стереоизображение, положить imgLeft в Красный канал imgStereo и imgRight до зеленого и синего каналов imgStereo

предполагая, что все три изображения (L, R, S) имеют одинаковый размер, код будет выглядят так:

for(i=0;i<imgStereo->height;i++) 
{ 
    for(j=0;j<imgStereo->width;j++) 
    { 
     imgStereo.at<Vec3b>(i,j)[0] = imgRight.at<uchar>(i,j); // B 
     imgStereo.at<Vec3b>(i,j)[1] = imgRight.at<uchar>(i,j); // G 
     imgStereo.at<Vec3b>(i,j)[2] = imgLeft.at<uchar>(i,j); // R 
    } 
} 
+0

Благодарим за предложение! Я реализовал это в C#/EmguCV, но преобразование матрицы-> изображения кажется слишком медленным и не может идти в ногу с событиями съемки. Я ищу матричное решение (см. Мой код в вопросе). Есть идеи? – salocinx

+0

Я не знаком с EmguCV. Но другим решением может быть не доступ к отдельному пикселю, как мой вышеприведенный код, а к копированию всего канала (например, скопировать весь imgLeft в R-канал imgStereo). Могут быть mixChannels или функции слияния, такие как [здесь] (http://stackoverflow.com/questions/20341910/opencv-taking-a-3-channel-rgb-image-splitting-channels-and-viewing-an-image-wi) и [здесь] (http://stackoverflow.com/questions/6699374/access-to-each-separate-channel-in-opencv) – Hardtack