91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

opencv雙目標(biāo)定操作完整版

QQ475400555 ? 來(lái)源:CSDN ? 作者:CSDN ? 2022-12-12 10:20 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

一、首先說(shuō)明幾個(gè)情況:

1、完成雙目標(biāo)定必須是自個(gè)拿棋盤(pán)圖擺拍,網(wǎng)上涉及用opencv自帶的標(biāo)定圖完成雙目標(biāo)定僅僅是提供個(gè)參考流程。我原來(lái)還以為用自帶的圖標(biāo)定就行,但想不通的是咱們實(shí)際擺放的雙目攝像頭和人家當(dāng)時(shí)擺放的肯定不一樣,那用人家的標(biāo)定圖怎么能反應(yīng)自己攝像頭的實(shí)際情況;后來(lái)問(wèn)了大神,才知道用opencv自帶的標(biāo)定圖(或者說(shuō)別人提供的圖)進(jìn)行標(biāo)定,這是完全沒(méi)有意義的。

2、進(jìn)行雙目標(biāo)定必須是左右相機(jī)同時(shí)進(jìn)行拍攝,再把圖保存下來(lái)。這點(diǎn)我是看opencv自帶的圖發(fā)現(xiàn)的,左右相機(jī)對(duì)應(yīng)的圖擺拍的姿勢(shì)是一模一樣的,除了左右相機(jī)視角帶來(lái)的影響。

3、我是先完成單目標(biāo)定,再完成雙目標(biāo)定。記得把理論看看,要不然有些概念不清楚。

二、

1、先固定好左右相機(jī),拿棋盤(pán)標(biāo)定圖擺拍并保存,我左右相機(jī)各15張,網(wǎng)上看的說(shuō)是總共30~40張為宜,這個(gè)大家隨意。

棋盤(pán)標(biāo)定圖在我另發(fā)的一個(gè)博客里免費(fèi)下載,當(dāng)時(shí)找了好久,下載的、程序生成的都或多或少有那么一些問(wèn)題。知識(shí)是得有價(jià),但棋盤(pán)圖這種最最基本的工具,博客里基本都需要拿幣下載,真是服。

程序:

// 同時(shí)調(diào)用兩個(gè)攝像頭,暫停并保存左右相機(jī)的標(biāo)定棋盤(pán)圖

#include

#include

#include

using namespace cv;

using namespace std; //開(kāi)頭我是從教程學(xué)的,一般不變,直接用

int main(int argc, char* argv[])

{

VideoCapture cap(0);

VideoCapture cap1(1); //打開(kāi)兩個(gè)攝像頭

if(!cap.isOpened())

{

printf("Could not open camera0... ");

return -1;

}

if (!cap1.isOpened())

{

printf("Could not open camera1... ");

return -2;

} //判斷還是加上為好,便于調(diào)程序

Mat frame, frame1;

bool stop = false;

while (!stop)

{

cap.read(frame);

cap1.read(frame1);

imshow("camera0", frame);

imshow("camera1", frame1);

int delay = 30;

if (delay >= 0 && waitKey(delay) >= 0)

{

waitKey(0); //實(shí)時(shí)拍攝暫停的程序

}

imwrite("C:/Users/Administrator/Desktop/11/left1.jpg", frame1);

imwrite("C:/Users/Administrator/Desktop/11/right1.jpg", frame); //給個(gè)位置保存圖片,注意圖片到底是左相機(jī)還是右相機(jī)的(用手在攝像頭前晃晃),我用的笨方法,保存一下,再把(left1.jpg/right1.jpg)+1,接著保存

}

cap.release();

cap1.release(); //兩個(gè)攝像頭數(shù)據(jù)釋放

return 0;

}

2、完成單目標(biāo)定,程序我是借鑒網(wǎng)上的,修改的不多。

//左右單目相機(jī)分別標(biāo)定

#include "opencv2/core/core.hpp"

#include "opencv2/imgproc/imgproc.hpp"

#include "opencv2/calib3d/calib3d.hpp"

#include "opencv2/highgui/highgui.hpp"

#include

#include "cv.h"

#include

#include

using namespace std;

using namespace cv; //人家這開(kāi)頭都長(zhǎng),遇到有紅線標(biāo)記的就刪了,把你知道的開(kāi)頭加上,沒(méi)問(wèn)題

const int boardWidth = 9; //橫向的角點(diǎn)數(shù)目

const int boardHeight = 6; //縱向的角點(diǎn)數(shù)據(jù)

const int boardCorner = boardWidth * boardHeight; //總的角點(diǎn)數(shù)據(jù)

const int frameNumber = 15; //相機(jī)標(biāo)定時(shí)需要采用的圖像幀數(shù)

const int squareSize = 25; //標(biāo)定板黑白格子的大小 單位mm

const Size boardSize = Size(boardWidth, boardHeight); //總的內(nèi)角點(diǎn)

Mat intrinsic; //相機(jī)內(nèi)參數(shù)

Mat distortion_coeff; //相機(jī)畸變參數(shù)

vectorrvecs; //旋轉(zhuǎn)向量

vectortvecs; //平移向量

vector corners; //各個(gè)圖像找到的角點(diǎn)的集合 和objRealPoint 一一對(duì)應(yīng)

vector objRealPoint; //各副圖像的角點(diǎn)的實(shí)際物理坐標(biāo)集合

vectorcorner; //某一副圖像找到的角點(diǎn)

/*計(jì)算標(biāo)定板上模塊的實(shí)際物理坐標(biāo)*/

void calRealPoint(vector& obj, int boardwidth, int boardheight, int imgNumber, int squaresize)

{

vectorimgpoint;

for (int rowIndex = 0; rowIndex < boardheight; rowIndex++)

{

for (int colIndex = 0; colIndex < boardwidth; colIndex++)

{

imgpoint.push_back(Point3f(rowIndex * squaresize, colIndex * squaresize, 0));

}

}

for (int imgIndex = 0; imgIndex < imgNumber; imgIndex++)

{

obj.push_back(imgpoint);

}

}

/*設(shè)置相機(jī)的初始參數(shù) 也可以不估計(jì)*/

void guessCameraParam(void)

{

/*分配內(nèi)存*/

intrinsic.create(3, 3, CV_64FC1); //相機(jī)內(nèi)參數(shù)

distortion_coeff.create(5, 1, CV_64FC1); //畸變參數(shù)

/*

fx 0 cx

0 fy cy

0 0 1 內(nèi)參數(shù)

*/

intrinsic.at(0, 0) = 256.8093262; //fx

intrinsic.at(0, 2) = 160.2826538; //cx

intrinsic.at(1, 1) = 254.7511139; //fy

intrinsic.at(1, 2) = 127.6264572; //cy

intrinsic.at(0, 1) = 0;

intrinsic.at(1, 0) = 0;

intrinsic.at(2, 0) = 0;

intrinsic.at(2, 1) = 0;

intrinsic.at(2, 2) = 1;

/*

k1 k2 p1 p2 p3 畸變參數(shù)

*/

distortion_coeff.at(0, 0) = -0.193740; //k1

distortion_coeff.at(1, 0) = -0.378588; //k2

distortion_coeff.at(2, 0) = 0.028980; //p1

distortion_coeff.at(3, 0) = 0.008136; //p2

distortion_coeff.at(4, 0) = 0; //p3

}

void outputCameraParam(void)

{

/*保存數(shù)據(jù)*/

//cvSave("cameraMatrix.xml", &intrinsic);

//cvSave("cameraDistoration.xml", &distortion_coeff);

//cvSave("rotatoVector.xml", &rvecs);

//cvSave("translationVector.xml", &tvecs);

/*輸出數(shù)據(jù)*/

//cout << "fx :" << intrinsic.at(0, 0) << endl << "fy :" << intrinsic.at(1, 1) << endl;

//cout << "cx :" << intrinsic.at(0, 2) << endl << "cy :" << intrinsic.at(1, 2) << endl;//內(nèi)參數(shù)

printf("fx:%lf... ", intrinsic.at(0, 0));

printf("fy:%lf... ", intrinsic.at(1, 1));

printf("cx:%lf... ", intrinsic.at(0, 2));

printf("cy:%lf... ", intrinsic.at(1, 2)); //我學(xué)的是printf,就試著改了一下,都能用

//cout << "k1 :" << distortion_coeff.at(0, 0) << endl;

//cout << "k2 :" << distortion_coeff.at(1, 0) << endl;

//cout << "p1 :" << distortion_coeff.at(2, 0) << endl;

//cout << "p2 :" << distortion_coeff.at(3, 0) << endl;

//cout << "p3 :" << distortion_coeff.at(4, 0) << endl; ? //畸變參數(shù)

printf("k1:%lf... ", distortion_coeff.at(0, 0));

printf("k2:%lf... ", distortion_coeff.at(1, 0));

printf("p1:%lf... ", distortion_coeff.at(2, 0));

printf("p2:%lf... ", distortion_coeff.at(3, 0));

printf("p3:%lf... ", distortion_coeff.at(4, 0));

}

int main()

{

int imageHeight; //圖像高度

int imageWidth; //圖像寬度

int goodFrameCount = 0; //有效圖像的數(shù)目

Mat rgbImage,grayImage;

Mat tImage = imread("C:/Users/Administrator/Desktop/11/right1.jpg");

if (tImage.empty())

{

printf("Could not load tImage... ");

return -1;

}

imageHeight = tImage.rows;

imageWidth = tImage.cols;

grayImage = Mat::ones(tImage.size(), CV_8UC1);

while (goodFrameCount < frameNumber)

{

char filename[100];

sprintf_s(filename, "C:/Users/Administrator/Desktop/11/right%d.jpg", goodFrameCount + 1);

rgbImage = imread(filename);

if (rgbImage.empty())

{

printf("Could not load grayImage... ");

return -2;

}

cvtColor(rgbImage, grayImage, CV_BGR2GRAY);

imshow("Camera", grayImage);

bool isFind = findChessboardCorners(rgbImage, boardSize, corner, CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE);

//bool isFind = findChessboardCorners( rgbImage, boardSize, corner,

//CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FAST_CHECK | CV_CALIB_CB_NORMALIZE_IMAGE);

if (isFind == true) //所有角點(diǎn)都被找到 說(shuō)明這幅圖像是可行的

{

//精確角點(diǎn)位置,亞像素角點(diǎn)檢測(cè)

cornerSubPix(grayImage, corner, Size(5, 5), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 20, 0.1));

//繪制角點(diǎn)

drawChessboardCorners(rgbImage, boardSize, corner, isFind);

imshow("chessboard", rgbImage);

corners.push_back(corner);

goodFrameCount++;

/*cout << "The image" << goodFrameCount << " is good" << endl;*/

printf("The image %d is good... ", goodFrameCount);

}

else

{

printf("The image is bad please try again... ");

}

if (waitKey(10) == 'q')

{

break;

}

}

/*

圖像采集完畢 接下來(lái)開(kāi)始攝像頭的校正

calibrateCamera()

輸入?yún)?shù) objectPoints 角點(diǎn)的實(shí)際物理坐標(biāo)

imagePoints 角點(diǎn)的圖像坐標(biāo)

imageSize 圖像的大小

輸出參數(shù)

cameraMatrix 相機(jī)的內(nèi)參矩陣

distCoeffs 相機(jī)的畸變參數(shù)

rvecs 旋轉(zhuǎn)矢量(外參數(shù))

tvecs 平移矢量(外參數(shù))

*/

/*設(shè)置實(shí)際初始參數(shù) 根據(jù)calibrateCamera來(lái) 如果flag = 0 也可以不進(jìn)行設(shè)置*/

guessCameraParam();

printf("guess successful... ");

/*計(jì)算實(shí)際的校正點(diǎn)的三維坐標(biāo)*/

calRealPoint(objRealPoint, boardWidth, boardHeight, frameNumber, squareSize);

printf("calculate real successful... ");

/*標(biāo)定攝像頭*/

calibrateCamera(objRealPoint, corners, Size(imageWidth, imageHeight), intrinsic, distortion_coeff, rvecs, tvecs, 0);

printf("calibration successful... ");

/*保存并輸出參數(shù)*/

outputCameraParam();

printf("output successful... ");

/*顯示畸變校正效果*/

Mat cImage;

undistort(rgbImage, cImage, intrinsic, distortion_coeff); //矯正相機(jī)鏡頭變形

imshow("Corret Image", cImage);

printf("Corret Image.... ");

printf("Wait for Key.... ");

waitKey(0);

return 0;

}

注意:(1)把你得到的左右相機(jī)標(biāo)定完的參數(shù)記下來(lái),雙目標(biāo)定的時(shí)候會(huì)用;

(2)如果遇到cvtColor出問(wèn)題,那就查一下構(gòu)造一個(gè)新圖像的Mat類使用方法;

(3)如果遇到結(jié)果一閃而過(guò)的問(wèn)題,可以先用網(wǎng)上提供的兩種方法試一下(一搜就有),但是我用這兩種方法都沒(méi)解決,最后才知道是frameNumber 的問(wèn)題,我設(shè)的值比現(xiàn)有的圖多一張。到時(shí)候具體問(wèn)題具體分析吧,都是應(yīng)該經(jīng)歷的過(guò)程。

3、完成雙目標(biāo)定,程序也是借鑒網(wǎng)上的,稍加修改。

// 雙目相機(jī)標(biāo)定

#include "opencv2/core/core.hpp"

#include "opencv2/imgproc/imgproc.hpp"

#include "opencv2/calib3d/calib3d.hpp"

#include "opencv2/highgui/highgui.hpp"

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "cv.h"

#include

using namespace std;

using namespace cv; //依舊很長(zhǎng)的開(kāi)頭

const int imageWidth = 640; //攝像頭的分辨率

const int imageHeight = 480;

const int boardWidth = 9; //橫向的角點(diǎn)數(shù)目

const int boardHeight = 6; //縱向的角點(diǎn)數(shù)據(jù)

const int boardCorner = boardWidth * boardHeight; //總的角點(diǎn)數(shù)據(jù)

const int frameNumber = 15; //相機(jī)標(biāo)定時(shí)需要采用的圖像幀數(shù)

const int squareSize = 25; //標(biāo)定板黑白格子的大小 單位mm

const Size boardSize = Size(boardWidth, boardHeight); //標(biāo)定板的總內(nèi)角點(diǎn)

Size imageSize = Size(imageWidth, imageHeight);

Mat R, T, E, F; //R 旋轉(zhuǎn)矢量 T平移矢量 E本征矩陣 F基礎(chǔ)矩陣

vectorrvecs; //旋轉(zhuǎn)向量

vectortvecs; //平移向量

vector imagePointL; //左邊攝像機(jī)所有照片角點(diǎn)的坐標(biāo)集合

vector imagePointR; //右邊攝像機(jī)所有照片角點(diǎn)的坐標(biāo)集合

vector objRealPoint; //各副圖像的角點(diǎn)的實(shí)際物理坐標(biāo)集合

vectorcornerL; //左邊攝像機(jī)某一照片角點(diǎn)坐標(biāo)集合

vectorcornerR; //右邊攝像機(jī)某一照片角點(diǎn)坐標(biāo)集合

Mat rgbImageL, grayImageL;

Mat rgbImageR, grayImageR;

Mat Rl, Rr, Pl, Pr, Q; //校正旋轉(zhuǎn)矩陣R,投影矩陣P 重投影矩陣Q (下面有具體的含義解釋)

Mat mapLx, mapLy, mapRx, mapRy; //映射表

Rect validROIL, validROIR; //圖像校正之后,會(huì)對(duì)圖像進(jìn)行裁剪,這里的validROI就是指裁剪之后的區(qū)域

/*

事先標(biāo)定好的左相機(jī)的內(nèi)參矩陣

fx 0 cx

0 fy cy

0 0 1

*/

Mat cameraMatrixL = (Mat_(3, 3) << 462.279595, 0, 312.781587,

0, 460.220741, 208.225803,

0, 0, 1); //這時(shí)候就需要你把左右相機(jī)單目標(biāo)定的參數(shù)給寫(xiě)上

//獲得的畸變參數(shù)

Mat distCoeffL = (Mat_(5, 1) << -0.054929, 0.224509, 0.000386, 0.001799, -0.302288);

/*

事先標(biāo)定好的右相機(jī)的內(nèi)參矩陣

fx 0 cx

0 fy cy

0 0 1

*/

Mat cameraMatrixR = (Mat_(3, 3) << 463.923124, 0, 322.783959,

0, 462.203276, 256.100655,

0, 0, 1);

Mat distCoeffR = (Mat_(5, 1) << -0.049056, 0.229945, 0.001745, -0.001862, -0.321533);

/*計(jì)算標(biāo)定板上模塊的實(shí)際物理坐標(biāo)*/

void calRealPoint(vector& obj, int boardwidth, int boardheight, int imgNumber, int squaresize)

{

vectorimgpoint;

for (int rowIndex = 0; rowIndex < boardheight; rowIndex++)

{

for (int colIndex = 0; colIndex < boardwidth; colIndex++)

{

imgpoint.push_back(Point3f(rowIndex * squaresize, colIndex * squaresize, 0));

}

}

for (int imgIndex = 0; imgIndex < imgNumber; imgIndex++)

{

obj.push_back(imgpoint);

}

}

void outputCameraParam(void)

{

/*保存數(shù)據(jù)*/

/*輸出數(shù)據(jù)*/

FileStorage fs("intrinsics.yml", FileStorage::WRITE); //文件存儲(chǔ)器的初始化

if (fs.isOpened())

{

fs << "cameraMatrixL" << cameraMatrixL << "cameraDistcoeffL" << distCoeffL << "cameraMatrixR" << cameraMatrixR << "cameraDistcoeffR" << distCoeffR;

fs.release();

cout << "cameraMatrixL=:" << cameraMatrixL << endl << "cameraDistcoeffL=:" << distCoeffL << endl << "cameraMatrixR=:" << cameraMatrixR << endl << "cameraDistcoeffR=:" << distCoeffR << endl;

}

else

{

cout << "Error: can not save the intrinsics!!!!!" << endl;

}

fs.open("extrinsics.yml", FileStorage::WRITE);

if (fs.isOpened())

{

fs << "R" << R << "T" << T << "Rl" << Rl << "Rr" << Rr << "Pl" << Pl << "Pr" << Pr << "Q" << Q;

cout << "R=" << R << endl << "T=" << T << endl << "Rl=" << Rl << endl << "Rr=" << Rr << endl << "Pl=" << Pl << endl << "Pr=" << Pr << endl << "Q=" << Q << endl;

fs.release();

}

else

cout << "Error: can not save the extrinsic parameters ";

}

int main(int argc, char* argv[])

{

Mat img;

int goodFrameCount = 0;

while (goodFrameCount < frameNumber)

{

char filename[100];

/*讀取左邊的圖像*/

sprintf_s(filename, "C:/Users/Administrator/Desktop/11/left%d.jpg", goodFrameCount + 1);

rgbImageL = imread(filename, CV_LOAD_IMAGE_COLOR);

cvtColor(rgbImageL, grayImageL, CV_BGR2GRAY);

/*讀取右邊的圖像*/

sprintf_s(filename, "C:/Users/Administrator/Desktop/11/right%d.jpg", goodFrameCount + 1);

rgbImageR = imread(filename, CV_LOAD_IMAGE_COLOR);

cvtColor(rgbImageR, grayImageR, CV_BGR2GRAY);

bool isFindL, isFindR;

isFindL = findChessboardCorners(rgbImageL, boardSize, cornerL);

isFindR = findChessboardCorners(rgbImageR, boardSize, cornerR);

if (isFindL == true && isFindR == true) //如果兩幅圖像都找到了所有的角點(diǎn) 則說(shuō)明這兩幅圖像是可行的

{

/*

Size(5,5) 搜索窗口的一半大小

Size(-1,-1) 死區(qū)的一半尺寸

TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 20, 0.1)迭代終止條件

*/

cornerSubPix(grayImageL, cornerL, Size(5, 5), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 20, 0.1));

drawChessboardCorners(rgbImageL, boardSize, cornerL, isFindL);

imshow("chessboardL", rgbImageL);

imagePointL.push_back(cornerL);

cornerSubPix(grayImageR, cornerR, Size(5, 5), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 20, 0.1));

drawChessboardCorners(rgbImageR, boardSize, cornerR, isFindR);

imshow("chessboardR", rgbImageR);

imagePointR.push_back(cornerR);

//string filename = "res\image\calibration";

//filename += goodFrameCount + ".jpg";

//cvSaveImage(filename.c_str(), &IplImage(rgbImage)); //把合格的圖片保存起來(lái)

goodFrameCount++;

cout << "The image" << goodFrameCount << " is good" << endl;

}

else

{

cout << "The image is bad please try again" << endl;

}

if (waitKey(10) == 'q')

{

break;

}

}

/*

計(jì)算實(shí)際的校正點(diǎn)的三維坐標(biāo)

根據(jù)實(shí)際標(biāo)定格子的大小來(lái)設(shè)置

*/

calRealPoint(objRealPoint, boardWidth, boardHeight, frameNumber, squareSize);

cout << "cal real successful" << endl;

/*

標(biāo)定攝像頭

由于左右攝像機(jī)分別都經(jīng)過(guò)了單目標(biāo)定

所以在此處選擇flag = CALIB_USE_INTRINSIC_GUESS

*/

double rms = stereoCalibrate(objRealPoint, imagePointL, imagePointR,

cameraMatrixL, distCoeffL,

cameraMatrixR, distCoeffR,

Size(imageWidth, imageHeight),R, T,E, F, CALIB_USE_INTRINSIC_GUESS,

TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, 1e-5)); //需要注意,應(yīng)該是版本的原因,該函數(shù)最后兩個(gè)參數(shù),我是調(diào)換過(guò)來(lái)后才顯示不出錯(cuò)的

cout << "Stereo Calibration done with RMS error = " << rms << endl;

/*

立體校正的時(shí)候需要兩幅圖像共面并且行對(duì)準(zhǔn) 以使得立體匹配更加的可靠

使得兩幅圖像共面的方法就是把兩個(gè)攝像頭的圖像投影到一個(gè)公共成像面上,這樣每幅圖像從本圖像平面投影到公共圖像平面都需要一個(gè)旋轉(zhuǎn)矩陣R

stereoRectify 這個(gè)函數(shù)計(jì)算的就是從圖像平面投影到公共成像平面的旋轉(zhuǎn)矩陣Rl,Rr。Rl,Rr即為左右相機(jī)平面行對(duì)準(zhǔn)的校正旋轉(zhuǎn)矩陣。

左相機(jī)經(jīng)過(guò)Rl旋轉(zhuǎn),右相機(jī)經(jīng)過(guò)Rr旋轉(zhuǎn)之后,兩幅圖像就已經(jīng)共面并且行對(duì)準(zhǔn)了。

其中Pl,Pr為兩個(gè)相機(jī)的投影矩陣,其作用是將3D點(diǎn)的坐標(biāo)轉(zhuǎn)換到圖像的2D點(diǎn)的坐標(biāo):P*[X Y Z 1]' =[x y w]

Q矩陣為重投影矩陣,即矩陣Q可以把2維平面(圖像平面)上的點(diǎn)投影到3維空間的點(diǎn):Q*[x y d 1] = [X Y Z W]。其中d為左右兩幅圖像的時(shí)差

*/

//對(duì)標(biāo)定過(guò)的圖像進(jìn)行校正

stereoRectify(cameraMatrixL, distCoeffL, cameraMatrixR, distCoeffR, imageSize, R, T, Rl, Rr, Pl, Pr, Q,

CALIB_ZERO_DISPARITY, -1, imageSize, &validROIL, &validROIR);

/*

根據(jù)stereoRectify 計(jì)算出來(lái)的R 和 P 來(lái)計(jì)算圖像的映射表 mapx,mapy

mapx,mapy這兩個(gè)映射表接下來(lái)可以給remap()函數(shù)調(diào)用,來(lái)校正圖像,使得兩幅圖像共面并且行對(duì)準(zhǔn)

ininUndistortRectifyMap()的參數(shù)newCameraMatrix就是校正后的攝像機(jī)矩陣。在openCV里面,校正后的計(jì)算機(jī)矩陣Mrect是跟投影矩陣P一起返回的。

所以我們?cè)谶@里傳入投影矩陣P,此函數(shù)可以從投影矩陣P中讀出校正后的攝像機(jī)矩陣

*/

//攝像機(jī)校正映射

initUndistortRectifyMap(cameraMatrixL, distCoeffL, Rl, Pr, imageSize, CV_32FC1, mapLx, mapLy);

initUndistortRectifyMap(cameraMatrixR, distCoeffR, Rr, Pr, imageSize, CV_32FC1, mapRx, mapRy);

Mat rectifyImageL, rectifyImageR;

cvtColor(grayImageL, rectifyImageL, CV_GRAY2BGR);

cvtColor(grayImageR, rectifyImageR, CV_GRAY2BGR);

imshow("Rectify Before", rectifyImageL);

cout << "按Q1退出 ..." << endl;

/*

經(jīng)過(guò)remap之后,左右相機(jī)的圖像已經(jīng)共面并且行對(duì)準(zhǔn)了

*/

Mat rectifyImageL2, rectifyImageR2;

remap(rectifyImageL, rectifyImageL2, mapLx, mapLy, INTER_LINEAR);

remap(rectifyImageR, rectifyImageR2, mapRx, mapRy, INTER_LINEAR);

cout << "按Q2退出 ..." << endl;

imshow("rectifyImageL", rectifyImageL2);

imshow("rectifyImageR", rectifyImageR2);

/*保存并輸出數(shù)據(jù)*/

outputCameraParam();

/*

把校正結(jié)果顯示出來(lái)

把左右兩幅圖像顯示到同一個(gè)畫(huà)面上

這里只顯示了最后一副圖像的校正結(jié)果。并沒(méi)有把所有的圖像都顯示出來(lái)

*/

Mat canvas;

double sf;

int w, h;

sf = 600. / MAX(imageSize.width, imageSize.height);

w = cvRound(imageSize.width * sf);

h = cvRound(imageSize.height * sf);

canvas.create(h, w * 2, CV_8UC3);

/*左圖像畫(huà)到畫(huà)布上*/

Mat canvasPart = canvas(Rect(w * 0, 0, w, h)); //得到畫(huà)布的一部分

resize(rectifyImageL2, canvasPart, canvasPart.size(), 0, 0, INTER_AREA); //把圖像縮放到跟canvasPart一樣大小

Rect vroiL(cvRound(validROIL.x*sf), cvRound(validROIL.y*sf), //獲得被截取的區(qū)域

cvRound(validROIL.width*sf), cvRound(validROIL.height*sf));

rectangle(canvasPart, vroiL, Scalar(0, 0, 255), 3, 8); //畫(huà)上一個(gè)矩形

cout << "Painted ImageL" << endl;

/*右圖像畫(huà)到畫(huà)布上*/

canvasPart = canvas(Rect(w, 0, w, h)); //獲得畫(huà)布的另一部分

resize(rectifyImageR2, canvasPart, canvasPart.size(), 0, 0, INTER_LINEAR);

Rect vroiR(cvRound(validROIR.x * sf), cvRound(validROIR.y*sf),

cvRound(validROIR.width * sf), cvRound(validROIR.height * sf));

rectangle(canvasPart, vroiR, Scalar(0, 255, 0), 3, 8);

cout << "Painted ImageR" << endl;

/*畫(huà)上對(duì)應(yīng)的線條*/

for (int i = 0; i < canvas.rows; i += 16)

line(canvas, Point(0, i), Point(canvas.cols, i), Scalar(0, 255, 0), 1, 8);

imshow("rectified", canvas);

cout << "wait key" << endl;

waitKey(0);

//system("pause");

return 0;

}

附上最后效果圖:

4056ff88-79be-11ed-8abf-dac502259ad0.png

審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 攝像頭
    +關(guān)注

    關(guān)注

    61

    文章

    5097

    瀏覽量

    103203
  • OpenCV
    +關(guān)注

    關(guān)注

    33

    文章

    652

    瀏覽量

    44865

原文標(biāo)題:opencv 雙目標(biāo)定操作完整版

文章出處:【微信號(hào):機(jī)器視覺(jué)沙龍,微信公眾號(hào):機(jī)器視覺(jué)沙龍】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    IMU+多相機(jī)高速聯(lián)合自動(dòng)標(biāo)定方案

    目、雙目、魚(yú)眼、長(zhǎng)焦、TOF任意混搭,模組更換后自動(dòng)識(shí)別。 標(biāo)定結(jié)果可一鍵推送至MES/ERP,JSON/YAML/TXT格式全開(kāi)放,后續(xù)OTA升級(jí)直接調(diào)用。 無(wú)需獨(dú)立氣源或冷卻水;年維護(hù)費(fèi)僅為進(jìn)口設(shè)備的1/10。
    發(fā)表于 10-23 14:04

    RTT完整版,DAP無(wú)法燒錄怎么解決?

    使用正點(diǎn)ATK-NANO-F103開(kāi)發(fā)板,測(cè)試完整版例程,DAP-LINK無(wú)法燒錄,顯示如下提示信息,怎么辦? D
    發(fā)表于 09-24 07:57

    【開(kāi)發(fā)實(shí)例】基于GM-3568JHF開(kāi)發(fā)板安裝OpenCV并使用視頻目標(biāo)跟蹤 ( CamShift)

    在計(jì)算機(jī)視覺(jué)領(lǐng)域,視頻目標(biāo)跟蹤是一個(gè)非常重要的任務(wù)。視頻目標(biāo)跟蹤廣泛應(yīng)用于監(jiān)控、自動(dòng)駕駛、人機(jī)交互等多個(gè)領(lǐng)域。OpenCV提供了多種目標(biāo)跟蹤算法,其中MeanShift和CamShif
    的頭像 發(fā)表于 09-02 08:04 ?819次閱讀
    【開(kāi)發(fā)實(shí)例】基于GM-3568JHF開(kāi)發(fā)板安裝<b class='flag-5'>OpenCV</b>并使用視頻<b class='flag-5'>目標(biāo)</b>跟蹤 ( CamShift)

    【GM-3568JHF開(kāi)發(fā)板免費(fèi)體驗(yàn)】OpenCV 視頻目標(biāo)跟蹤 ( CamShift)

    一、基本理論 在計(jì)算機(jī)視覺(jué)領(lǐng)域,視頻目標(biāo)跟蹤是一個(gè)非常重要的任務(wù)。視頻目標(biāo)跟蹤廣泛應(yīng)用于監(jiān)控、自動(dòng)駕駛、人機(jī)交互等多個(gè)領(lǐng)域。OpenCV 提供了多種目標(biāo)跟蹤算法,其中 MeanShif
    發(fā)表于 08-09 13:19

    光伏逆變器簡(jiǎn)介(57頁(yè)P(yáng)PT完整版)

    獲取完整文檔資料可下載附件哦?。。?!如果內(nèi)容有幫助可以關(guān)注、點(diǎn)贊、評(píng)論支持一下哦~
    發(fā)表于 06-13 17:41

    永磁同步電機(jī)磁場(chǎng)定向控制

    需要完整版資料可下載附件查看哦!
    發(fā)表于 05-30 16:10

    華為硬件工程師手冊(cè)(完整版

    獲取完整文檔資料可下載附件哦!?。。∪绻麅?nèi)容有幫助可以關(guān)注、點(diǎn)贊、評(píng)論支持一下哦~
    發(fā)表于 05-27 16:24

    電源完整性設(shè)計(jì)指導(dǎo)

    需要完整版資料可下載附件查看哦!
    發(fā)表于 05-07 17:00

    全系列電源供應(yīng)器測(cè)試解決方案(完整版)

    需要完整版資料可下載附件查看哦!
    發(fā)表于 04-21 15:24

    尋求AFE4960P芯片的完整資料

    各位大佬,我是一名研究生,目前在做基于ECG和PPG信號(hào)的可穿戴設(shè)設(shè)備的項(xiàng)目,經(jīng)過(guò)調(diào)研發(fā)現(xiàn),AFE4960P這款芯片比較符合需求。由于沒(méi)有企業(yè)郵箱,被TI官方拒絕提供完整資料。大佬們有沒(méi)有完整版的資料,分享一下,感謝。
    發(fā)表于 04-17 16:20

    完整版—單片機(jī)編程思想(推薦下載!)

    單片機(jī)的編程思想,希望能幫助大家寫(xiě)出簡(jiǎn)明的代碼 內(nèi)容簡(jiǎn)介 以單片機(jī)裸環(huán)境為基礎(chǔ),為編程者定義了一個(gè)微操作系統(tǒng)(MOS)的編程環(huán)境,并面向應(yīng)用中不斷提高的需求對(duì)編程策略進(jìn)行了深度剖析與研究,從而分離
    發(fā)表于 04-16 15:06

    華為2024年?duì)I收8621億凈利潤(rùn)626億 華為2024年年報(bào)完整版免費(fèi)下載

    華為2024年?duì)I收8621億凈利潤(rùn)626億 華為2024年年報(bào)完整版免費(fèi)下載
    的頭像 發(fā)表于 03-31 18:01 ?6667次閱讀
    華為2024年?duì)I收8621億凈利潤(rùn)626億  華為2024年年報(bào)<b class='flag-5'>完整版</b>免費(fèi)下載

    傳感器應(yīng)用設(shè)計(jì)141例(完整版

    介紹了光敏、紅外、熱敏電阻器、鉑電阻、熱電偶、濕度、氣體、磁敏、超聲波、振動(dòng)與加速度、電流、壓力、應(yīng)變、風(fēng)速、位置等傳感器的應(yīng)用技巧,具有很強(qiáng)的實(shí)用性。 純分享貼,有需要可以直接下載附件獲取完整資料! (如果內(nèi)容有幫助可以關(guān)注、點(diǎn)贊、評(píng)論支持一下哦~)
    發(fā)表于 03-27 14:04

    開(kāi)關(guān)穩(wěn)壓電源的設(shè)計(jì)與應(yīng)用——完整版

    純分享貼,有需要可以直接下載附件獲取完整資料! (如果內(nèi)容有幫助可以關(guān)注、點(diǎn)贊、評(píng)論支持一下哦~)
    發(fā)表于 03-25 15:07

    開(kāi)關(guān)電源設(shè)計(jì)指南(完整版

    了功率因數(shù)校正、印制電路設(shè)計(jì)、熱設(shè)計(jì)、噪聲控制和電磁干擾抑制等內(nèi)容。 可供從事開(kāi)關(guān)電源開(kāi)發(fā)的工程技術(shù)人員參考使用,也可作為高等院校電力電子技術(shù)專業(yè)及相關(guān)專業(yè)高年級(jí)大學(xué)生、碩士生、博士生和教師的參考書(shū)使用。 (如果內(nèi)容有幫助可以關(guān)注、點(diǎn)贊、評(píng)論支持一下哦~) 獲取完整文檔資料可下載附件哦?。。?!
    發(fā)表于 03-17 14:18