【问题标题】:How to mix up a stereo image with EmguCV?如何将立体图像与 EmguCV 混合?
【发布时间】:2017-01-11 19:27:48
【问题描述】:

我目前正在尝试将两个单独的相机图像合并为一个图像Anaglyph。结果应该类似于this image here

这是我编写的用于捕获两个相机图像并将它们转换为黑白的代码:

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;
            }
        }

    }

}

我的问题是,如何将灰色图像转换为 CyanMagentaRedBlue(cp. 在代码 sn-p 中标记为 TODO: 的行)?

【问题讨论】:

    标签: opencv emgucv stereo-3d stereoscopy


    【解决方案1】:

    要制作 Red-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
        }
    }
    

    【讨论】:

    • 感谢您的建议!我已经在 C#/EmguCV 中实现了这个,但是矩阵->图像转换似乎太慢了,无法跟上触发的捕获事件。我正在寻找基于矩阵的解决方案(cp.我在问题中的代码)。有什么想法吗?
    • 我对 EmguCV 不熟悉。但其他解决方案可能不是像我上面的代码那样访问单个像素,而是处理整个通道(例如,将整个 imgLeft 复制到 imgStereo 的 R 通道)。可以是 mixChannels 或合并函数,例如 herehere
    【解决方案2】:

    这是我的 EmguCV 解决方案,用于从两个摄像头输入生成立体图像。两幅彩色图像先转换为灰度图像,然后合并到最终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();
                }
            }
    
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-27
      • 2014-11-29
      • 1970-01-01
      相关资源
      最近更新 更多