如何将立体图像与 EmguCV 混合?
How to mix up a stereo image with EmguCV?
我目前正在尝试将两个单独的相机图像合并为一个图像 Anaglyph. The result should look something like 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;
}
}
}
}
我的问题是,如何将灰色图像转换为 Cyan
和 Magenta
或 Red
和 Blue
(代码片段中的 cp. 行标记为 TODO:
) ?
要制作 Red-Cyan 立体立体图像,请将 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
}
}
这是我的 EmguCV 解决方案,用于从两个相机输入生成立体图像。两幅彩色图像首先转换为灰度图像,然后合并到最终 RGB 图像的适当颜色通道。
这种方法的优点是,与仅提取一个源图像的红色通道和另一个源图像的 green/blue 通道的方法相比,不会丢失任何信息。
#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();
}
}
}
}
我目前正在尝试将两个单独的相机图像合并为一个图像 Anaglyph. The result should look something like 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;
}
}
}
}
我的问题是,如何将灰色图像转换为 Cyan
和 Magenta
或 Red
和 Blue
(代码片段中的 cp. 行标记为 TODO:
) ?
要制作 Red-Cyan 立体立体图像,请将 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
}
}
这是我的 EmguCV 解决方案,用于从两个相机输入生成立体图像。两幅彩色图像首先转换为灰度图像,然后合并到最终 RGB 图像的适当颜色通道。
这种方法的优点是,与仅提取一个源图像的红色通道和另一个源图像的 green/blue 通道的方法相比,不会丢失任何信息。
#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();
}
}
}
}