双目摄像头与图像拼接
视频演示如下:
在本章节中给大家演示对双目摄像头图像进行图像拼接操作,当前demo为博主经过网上到处搜寻并整理的。
当前系列所有demo下载地址:
https://github.com/GaoRenBao/OpenCv4-Demo
不同编程语言对应的OpenCv版本以及开发环境信息如下:
语言 | OpenCv版本 | IDE |
C# | OpenCvSharp4.4.8.0.20230708 | Visual Studio 2022 |
C++ | OpenCv-4.5.5-vc14_vc15 | Visual Studio 2022 |
Python | OpenCv-Python (4.6.0.66) | PyCharm Community Edition 2022.1.3 |
这是博主在网上购买的一个双目摄像头,USB免驱的。
他出来的图像是下面这个样子的,分为左右两个部分,所以我们在做图像拼接的时候,需要将这个大图像进行裁剪成左右两个单独图片才行。
在这里,C#版本博客提供了两种操作,一种是直接使用摄像头的图像进行图像拼接,另一种是直接读取本地预留的图像进行图像拼接,拼接效果如下:
C#版本支持摄像头操作,C++和Python版本通过读取两张图片,来实现图像拼接。
C#版本代码如下:
using OpenCvSharp;
using System;
using static OpenCvSharp.Stitcher;
using System.Collections.Generic;
namespace demo
{
internal class Program
{
/// <summary>
/// 视频操作
/// </summary>
public static VideoCapture Cap = new VideoCapture();
static void Main(string[] args)
{
//demo1();
demo2();
Cv2.WaitKey();
}
/// <summary>
/// 调用双目摄像头
/// </summary>
private static void demo1()
{
// 打开ID为0的摄像头
Cap.Open(0);
// 判断摄像头是否成功打开
if (!Cap.IsOpened())
{
Console.WriteLine("摄像头打开失败.");
Console.Read();
return;
}
Cap.Set(VideoCaptureProperties.FrameWidth, 3040);
Cap.Set(VideoCaptureProperties.FrameHeight, 1080);
Mat Image = new Mat();
List<Mat> images;
Mat panoMat = new Mat();
Stitcher stitcher;
while (true)
{
if (Cap.Read(Image))
{
Cv2.Resize(Image, Image, new Size(Image.Cols * 0.5, Image.Rows * 0.5), 0, 0, InterpolationFlags.Area);
// 将双目摄像头读取到的图像裁剪成左右两张图
Rect faces1 = new Rect()
{
X = 0,
Y = 0,
Width = (int)(Image.Width * 0.5),
Height = Image.Height
};
Rect faces2 = new Rect()
{
X = (int)(Image.Width * 0.5),
Y = 0,
Width = (int)(Image.Width * 0.5),
Height = Image.Height
};
Mat img_1 = new Mat(Image, faces1);
Mat img_2 = new Mat(Image, faces2);
Cv2.ImShow("img_1", img_1);
Cv2.ImShow("img_2", img_2);
// 对两张图像进行图像拼接
images = new List<Mat>() { img_2, img_1 };
stitcher = Stitcher.Create(Mode.Scans);
if (stitcher.Stitch(images, panoMat) != Stitcher.Status.OK)
{
Cv2.WaitKey(1);
continue;
}
Cv2.ImWrite("1.jpg", img_1);
Cv2.ImWrite("2.jpg", img_2);
//Cv2.ImWrite("拼接结果.jpg", panoMat);
Cv2.ImShow("拼接结果", panoMat);
return;
}
}
}
/// <summary>
/// 读取图片
/// </summary>
private static void demo2()
{
Mat img_1 = new Mat("../../../images/orb (1).jpg");
Mat img_2 = new Mat("../../../images/orb (2).jpg");
Cv2.ImShow("img_1", img_1);
Cv2.ImShow("img_2", img_2);
Mat panoMat = new Mat();
List<Mat> images = new List<Mat>() { img_2, img_1 };
Stitcher stitcher = Stitcher.Create(Mode.Scans);
if (stitcher.Stitch(images, panoMat) != Stitcher.Status.OK)
{
Console.WriteLine("拼接失败.");
Console.Read();
return;
}
Cv2.ImShow("拼接结果", panoMat);
}
}
}
C++版本代码如下:
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/Stitching.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat img_1 = imread("../images/orb (1).jpg");
Mat img_2 = imread("../images/orb (2).jpg");
imshow("img_1", img_1);
imshow("img_2", img_2);
vector<Mat> imgs;
imgs.push_back(img_1);
imgs.push_back(img_2);
Mat panoMat;
Stitcher::Mode mode = Stitcher::SCANS;
Ptr<Stitcher> stitcher = Stitcher::create(mode);
Stitcher::Status status = stitcher->stitch(imgs, panoMat);
if (status != Stitcher::OK)
{
cout << "拼接失败" << endl;
waitKey(0);
return 0;
}
imshow("拼接结果", panoMat);
waitKey(0);
return 0;
}
Python版本代码如下:
import cv2
img_1 = cv2.imread('../images/orb (1).jpg')
img_2 = cv2.imread('../images/orb (2).jpg')
cv2.imshow("img_1", img_1)
cv2.imshow("img_2", img_2)
stitcher = cv2.Stitcher_create(cv2.Stitcher_SCANS)
(retval, pano) = stitcher.stitch([img_1, img_2])
if retval != cv2.Stitcher_OK:
print("Error.")
cv2.waitKey(0)
exit(-1)
cv2.imshow("pano", pano)
cv2.waitKey(0)