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

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

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

opencv雙目標定操作完整版

QQ475400555 ? 來源:CSDN ? 作者:CSDN ? 2022-12-12 10:20 ? 次閱讀

一、首先說明幾個情況:

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

2、進行雙目標定必須是左右相機同時進行拍攝,再把圖保存下來。這點我是看opencv自帶的圖發(fā)現(xiàn)的,左右相機對應的圖擺拍的姿勢是一模一樣的,除了左右相機視角帶來的影響。

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

二、

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

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

程序:

// 同時調(diào)用兩個攝像頭,暫停并保存左右相機的標定棋盤圖

#include

#include

#include

using namespace cv;

using namespace std; //開頭我是從教程學的,一般不變,直接用

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

{

VideoCapture cap(0);

VideoCapture cap1(1); //打開兩個攝像頭

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); //實時拍攝暫停的程序

}

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

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

}

cap.release();

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

return 0;

}

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

//左右單目相機分別標定

#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; //人家這開頭都長,遇到有紅線標記的就刪了,把你知道的開頭加上,沒問題

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

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

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

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

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

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

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

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

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

vectortvecs; //平移向量

vector corners; //各個圖像找到的角點的集合 和objRealPoint 一一對應

vector objRealPoint; //各副圖像的角點的實際物理坐標集合

vectorcorner; //某一副圖像找到的角點

/*計算標定板上模塊的實際物理坐標*/

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ù) 也可以不估計*/

void guessCameraParam(void)

{

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

intrinsic.create(3, 3, CV_64FC1); //相機內(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)); //我學的是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) //所有角點都被找到 說明這幅圖像是可行的

{

//精確角點位置,亞像素角點檢測

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

//繪制角點

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;

}

}

/*

圖像采集完畢 接下來開始攝像頭的校正

calibrateCamera()

輸入?yún)?shù) objectPoints 角點的實際物理坐標

imagePoints 角點的圖像坐標

imageSize 圖像的大小

輸出參數(shù)

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

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

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

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

*/

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

guessCameraParam();

printf("guess successful... ");

/*計算實際的校正點的三維坐標*/

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

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

/*標定攝像頭*/

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); //矯正相機鏡頭變形

imshow("Corret Image", cImage);

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

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

waitKey(0);

return 0;

}

注意:(1)把你得到的左右相機標定完的參數(shù)記下來,雙目標定的時候會用;

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

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

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

// 雙目相機標定

#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; //依舊很長的開頭

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

const int imageHeight = 480;

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

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

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

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

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

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

Size imageSize = Size(imageWidth, imageHeight);

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

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

vectortvecs; //平移向量

vector imagePointL; //左邊攝像機所有照片角點的坐標集合

vector imagePointR; //右邊攝像機所有照片角點的坐標集合

vector objRealPoint; //各副圖像的角點的實際物理坐標集合

vectorcornerL; //左邊攝像機某一照片角點坐標集合

vectorcornerR; //右邊攝像機某一照片角點坐標集合

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; //圖像校正之后,會對圖像進行裁剪,這里的validROI就是指裁剪之后的區(qū)域

/*

事先標定好的左相機的內(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ù)給寫上

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

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

/*

事先標定好的右相機的內(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);

/*計算標定板上模塊的實際物理坐標*/

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); //文件存儲器的初始化

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) //如果兩幅圖像都找到了所有的角點 則說明這兩幅圖像是可行的

{

/*

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)); //把合格的圖片保存起來

goodFrameCount++;

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

}

else

{

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

}

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

{

break;

}

}

/*

計算實際的校正點的三維坐標

根據(jù)實際標定格子的大小來設置

*/

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

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

/*

標定攝像頭

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

所以在此處選擇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)); //需要注意,應該是版本的原因,該函數(shù)最后兩個參數(shù),我是調(diào)換過來后才顯示不出錯的

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

/*

立體校正的時候需要兩幅圖像共面并且行對準 以使得立體匹配更加的可靠

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

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

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

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

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

*/

//對標定過的圖像進行校正

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

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

/*

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

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

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

所以我們在這里傳入投影矩陣P,此函數(shù)可以從投影矩陣P中讀出校正后的攝像機矩陣

*/

//攝像機校正映射

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)過remap之后,左右相機的圖像已經(jīng)共面并且行對準了

*/

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é)果顯示出來

把左右兩幅圖像顯示到同一個畫面上

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

*/

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

/*左圖像畫到畫布上*/

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

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); //畫上一個矩形

cout << "Painted ImageL" << endl;

/*右圖像畫到畫布上*/

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

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;

/*畫上對應的線條*/

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)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 攝像頭
    +關(guān)注

    關(guān)注

    59

    文章

    4752

    瀏覽量

    94405
  • OpenCV
    +關(guān)注

    關(guān)注

    29

    文章

    622

    瀏覽量

    41091

原文標題:opencv 雙目標定操作完整版

文章出處:【微信號:機器視覺沙龍,微信公眾號:機器視覺沙龍】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    第19.1 章-星瞳科技 OpenMV視覺循跡功能 超詳細OpenMV與STM32單片機通信

    第19.1 章-[星瞳科技]OpenMV視覺循跡功能 超詳細OpenMV與STM32單片機通信 (有完整版源碼) 【星曈科技】OpenMv筆記——利用OpenMV與STM32進行串口通信
    的頭像 發(fā)表于 08-20 11:41 ?527次閱讀
    第19.1 章-星瞳科技 OpenMV視覺循跡功能 超詳細OpenMV與STM32單片機通信

    opencv-python和opencv一樣嗎

    不一樣。OpenCV(Open Source Computer Vision Library)是一個開源的計算機視覺和機器學習軟件庫,它提供了大量的圖像和視頻處理功能。OpenCV
    的頭像 發(fā)表于 07-16 10:38 ?449次閱讀

    opencv的主要功能有哪些

    OpenCV提供了豐富的圖像處理功能,包括圖像的讀取、顯示、保存、轉(zhuǎn)換等。此外,OpenCV還支持圖像的濾波、邊緣檢測、形態(tài)學操作、圖像金字塔等高級圖像處理技術(shù)。 特征檢測與描述:OpenC
    的頭像 發(fā)表于 07-16 10:35 ?803次閱讀

    以色列人工智能目標定位系統(tǒng)實力如何

    2019年,以色列政府宣布成立“目標定位局”,旨在為以色列國防軍(IDF),特別是以色列空軍(IAF)生成打擊目標
    的頭像 發(fā)表于 04-16 11:13 ?285次閱讀

    工業(yè)相機單目和雙目的區(qū)別

    工業(yè)相機標定的方法根據(jù)工業(yè)相機的數(shù)目可分為單目標定、雙目標定Q以及多目標定。
    的頭像 發(fā)表于 03-26 16:26 ?1387次閱讀
    工業(yè)相機單目和<b class='flag-5'>雙目</b>的區(qū)別

    ez-usb_hx3pd_configuration_utility_1.0_b37_SetupOnlyPackage安裝失敗的原因?

    ez-usb_hx3pd_configuration_utility_1.0_b37_SetupOnlyPackage在windows10安裝失敗 哪里可以下載到提示說的完整版本?
    發(fā)表于 02-28 08:24

    用stm32cubemx生成一個3.1.5版本的nano工程,移植fal內(nèi)核無法啟動怎么解決?

    用stm32cubemx生成一個3.1.5版本的nano工程,試圖移植FAL庫用來做bootloader升級用戶程序,在f1平臺完整版RTT上實現(xiàn)了bootloader引導升級,在nano工程中下
    發(fā)表于 02-26 06:17

    鴻蒙開發(fā)南向環(huán)境搭建教學

    南向開發(fā)環(huán)境搭建教學,更多鴻蒙開發(fā)資料可以前往高清完整版 《鴻蒙開發(fā)4.0基礎-高階文檔》找保存。(附鴻蒙文檔)
    發(fā)表于 01-05 16:38

    如何確定目標阻抗以實現(xiàn)電源完整性?

    如何確定目標阻抗以實現(xiàn)電源完整性?
    的頭像 發(fā)表于 11-27 16:49 ?1170次閱讀
    如何確定<b class='flag-5'>目標</b>阻抗以實現(xiàn)電源<b class='flag-5'>完整</b>性?

    OpenCV對openEuler提供上游原生支持

    2023年11月17日,OpenCV社區(qū)正式接納openEuler作為持續(xù)集成(Continuous Integration,CI)系統(tǒng)的操作系統(tǒng)之一,對openEuler提供上游原生支持
    的頭像 發(fā)表于 11-20 09:14 ?683次閱讀

    為何程序下載時搜索不到CPU?

    產(chǎn)生此問題的原因有很多,比如安裝了360安全衛(wèi)士、金山衛(wèi)士以及QQ管家等第三方殺毒軟件;或者Windows 操作系統(tǒng)非完整版操作系統(tǒng),例如安裝了GHOST版本的操作系統(tǒng),其他定制化的
    的頭像 發(fā)表于 11-02 14:15 ?751次閱讀
    為何程序下載時搜索不到CPU?

    c語言面試題集(完整版)

    電子發(fā)燒友網(wǎng)站提供《c語言面試題集(完整版).pdf》資料免費下載
    發(fā)表于 10-20 11:20 ?2次下載
    c語言面試題集(<b class='flag-5'>完整版</b>)

    SD卡協(xié)議學習點滴(完整版本)

    電子發(fā)燒友網(wǎng)站提供《SD卡協(xié)議學習點滴(完整版本).pdf》資料免費下載
    發(fā)表于 10-13 09:31 ?0次下載
    SD卡協(xié)議學習點滴(<b class='flag-5'>完整版</b>本)

    常用視覺的三種相機標定總結(jié)

    選中Export Camera Parameters按鈕,將計算得到的相關(guān)參數(shù)導入到Matlab中;若要進行更精確的標定,可在標定時考慮畸變誤差或采用雙目相機標定方法。
    發(fā)表于 10-09 10:51 ?1481次閱讀
    常用視覺的三種相機<b class='flag-5'>標定</b>總結(jié)

    完整版Raspberry Pi樹莓派電路圖

    完整版Raspberry Pi樹莓派電路圖大全
    發(fā)表于 09-25 08:00