Я новичок в области стереовидения с OpenCV с использованием C ++. Я работаю с парой разнородных камер (одинаковое разрешение, одинаковое соотношение сторон, но разная оптическая схема и поле зрения). Камеры очень дешевые, пара 640 * 480 трастовых камер с ручной фокусировкой.
Я написал программу для создания видео в реальном времени, отображающего карту диспаратности. У меня проблемы с калибровкой, которая всегда дает мне очень плохой результат, в частности, со стереокалибровкой и, как следствие, приводит к бесполезной карте диспаратности.
В первой части кода я собираю непосредственно с камер живые изображения, установленные для калибровки. Я использую чип-плату, так что я знаю, что не могу получить экстраординарную калибровку, но сейчас мне нужна только достойная калибровка, чтобы продолжить разработку (позже я увеличу качество калибровки).
Я запускаю калибровку одиночной камеры и получаю среднеквадратичное значение от 0,5 до 1,2 (с 10 изображениями они остаются неизменными даже с 20 изображениями). Получающаяся калибровка кажется хорошей с приличными результатами.
Когда дело доходит до стереокалибровки, я получаю rsm около 27 и 35; два видеопотока от левой и правой камер выглядят полностью искаженными, а видео с диспаратностью совершенно бесполезным.
Мой вопрос:
что-то не так в моем коде?
Я что-то забыл?
Какой правильный набор флагов для хорошей стереокалибровки?
Возможно, проблемы возникают из-за того, что я не использую две одинаковые камеры?
Мои камеры слишком плохого качества для хорошего стереозрения? (в этом случае камеры ведьм вы рекомендуете?)
вот мой код:
#include <iostream>
#include "opencv2/core/core.hpp"#include "opencv2/highgui/highgui.hpp"#include "opencv2/videoio.hpp"#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/calib3d/calib3d.hpp"#include <vector>
#include <stdio.h>
#include <opencv2/ml.hpp>
using namespace cv::ml;
using namespace std;
using namespace cv;
#define CV_CALIB_FIX_K5 4096
#define CV_CALIB_FIX_K4 2048
#define CV_L2 4//questa funzione rimanda ad un'eccezione trovare quale sia e correggere.
double computeReprojectionErrors(const vector< vector< Point3f > >& object_points, const vector< vector< Point2f > >& image_points, const vector< Mat >& rvecs, const vector< Mat >& tvecs,const Mat& cameraMatrix , const Mat& distCoeffs) {
cout<< "siamo entrati nella funzione"<< endl;vector< Point2f > image_points_cpy;
int i, totalPoints = 0;
double totalErr = 0, err;
vector< float > perViewErrors;
perViewErrors.resize(object_points.size());
int dim_obj_points= object_points.size();
cout<< "siamo alla fine delle dichiarazioni"<<endl;
for (i = 0; i < dim_obj_points; i++) {
int n= 0;
projectPoints(Mat(object_points[i]), rvecs[i], tvecs[i], cameraMatrix,distCoeffs, image_points_cpy);
err = norm(Mat(image_points[i]), Mat(image_points_cpy), CV_L2);
n = (int)object_points[i].size();
perViewErrors[i] = (float) std::sqrt(err*err/n);
totalErr += err*err;
totalPoints += n;
}
return std::sqrt(totalErr/totalPoints);
}int main()
{
//nuova parte
int count= 0;
int rows, cols; //dimensioni del frame, le leggo una sola volta
//Mat frame_to_print,frame_previous, frame_new;
int h, w, h1, w1;
//variabili per la calibrazione dell'immagine
int n_quadrati = 10; //questo è il numero di prove che fa per controllare le scacchiere
const int quadrati_dt = 20; //numero di frame da controllrare per trovare la scacchiera
int quadrati_w= 7;
int quadrati_h= 9;
int quadrati_n = (int)quadrati_w * quadrati_h;
float caselle_dimensione= 0.024; //(dimensione in metri) square_size deve essere inizializzato con un valore che non conosco ancora
Mat copy_temp; //usata come tampone per l'inizializzazione
//fine variabili per la calibrazione della camera//AVVIO E TEST DELLE VIDEOCMAERE
VideoCapture webcam_0(0); //apro la camera di destra
if(!webcam_0.isOpened())
{
cout << "errore non posso collegarmi alla camera destra" << endl;
waitKey(0);
return -1;
}
VideoCapture webcam_1(1); //apro la camera di sinistra
if(!webcam_0.isOpened())
{
cout << "Errore non posso collegarmi alla camera sinistra" << endl;
waitKey(0);
return -1;
}
Mat frame_l; //header per salvare i frame della camera sinistra
Mat frame_r; //header per salvare i frame della camera destra
int i = 0; //index, we use it for testing
//CAMERA DESTRA
while ((i++ < 100) && !webcam_0.read(frame_l)) //skip unread frames
{
cout << "frame " << i << " skipped" << endl;
}
if (i >= 100) //check webcam_0 failure
{
cout << "non arrivano frame" << endl;
waitKey(0);
return -1;
} else
{
cout << "camera destra pronta" << endl;
}
//CAMERA SINISTRA
while ((i++ < 100) && !webcam_1.read(frame_r)) //skip unread frames
{
cout << "frame " << i << " skipped" << endl;
}
if (i >= 100) //check webcam_0 failure
{
cout << "non arrivano frame" << endl;
waitKey(0);
return -1;
} else
{
cout << "camera destra pronta" << endl;
}
//CAMERE PRONTEcout<< "dimensioni immagine R colonne" << frame_r.cols<< " righe"<< frame_r.rows<<endl;
cout<< "dimensioni immagine L colonne" << frame_l.cols<< " righe"<< frame_l.rows<<endl;
//setto le dimensioni del frame
rows= frame_r.rows;//352;
cols= frame_r.cols;//288;
//FINE AVVIO E TEST DELLE CAMERE//CREO E SETTO LA DIMENSIONE DI FRAME_R_BN
cv::Mat frame_r_bn(cv::Size(cols, rows), CV_8UC1);
//CREO E SETTO LA DIMENSIONE DI FRAME_RESIZED_R
cv::Mat frame_l_bn(cv::Size(cols, rows), CV_8UC1);
//CREO E SETTO LA DIMENSIONE DI Dispraity
cv::Mat disparity16s(cv::Size(cols, rows), CV_16S);
//CREO E SETTO LA DIMENSIONE DI disparity_project
cv::Mat disparity_project(cv::Size(cols, rows), CV_8UC1);
//CREO E SETTO LA DIMENSIONE DEL frame di test per la distorsione
cv::Mat richiedi_frame_l(cv::Size(cols, rows), CV_8UC3);
//CREO E SETTO LA DIMENSIONE DEL frame di test per la distorsione
cv::Mat richiedi_frame_l_bn(cv::Size(cols, rows), CV_8UC1);
//CREO E SETTO LA DIMENSIONE DEL frame di test per la distorsione
cv::Mat richiedi_frame_r(cv::Size(cols, rows), CV_8UC3);
//CREO E SETTO LA DIMENSIONE DEL frame di test per la distorsione
cv::Mat richiedi_frame_r_bn(cv::Size(cols, rows), CV_8UC1);cout<<"cominciamo la calibrazione/n";//CALIBRAZIONE CAMERA CERCO LE SCACCHIERE//prendo setto la dimensione e prelevo una prima immagine
cv::Size quadrati_sz= Size(quadrati_h, quadrati_w);// = Size_( quadrati_w, quadrati_h );vector< vector< Point3f > > object_points_0, object_points_c0;
vector< vector< Point2f > > image_points_0, image_points_1;
vector< vector< Point2f > > image_points_c0, image_points_c1;
vector< vector< Point3f > > object_points_1, object_points_c1;
vector<Point2f> corners_0;
vector<Point2f> corners_1; //test
Mat point_counts_0(n_quadrati,1,CV_32SC1);
Mat point_counts_1(n_quadrati,1,CV_32SC1);
Mat intrinsic_matrix_0(3,3,CV_32FC1);
Mat distortion_coeffs_0(5,1,CV_32FC1);
Mat intrinsic_matrix_1(3,3,CV_32FC1);
Mat distortion_coeffs_1(5,1,CV_32FC1);int trovato= 0;
int angoli_count_0;
int angoli_count_1;
int passo; //step nell'originale
int frame = 0;
webcam_0.read(richiedi_frame_l); //capture nel codice precedente //chiedo un primo frame
webcam_1.read(richiedi_frame_r);
cvtColor(richiedi_frame_l,richiedi_frame_l_bn,COLOR_BGR2GRAY);
cvtColor(richiedi_frame_r,richiedi_frame_r_bn,COLOR_BGR2GRAY);
bool cerca_0= false;
bool cerca_1= false;
int calibrato_fatto;
cout<<"Hai già calibrato tutto, premi 0 per si altrimenti 1 per avviare la calibrazione";
cin>> calibrato_fatto;
if(calibrato_fatto){
while(trovato< n_quadrati) {
//permettiamo di muovere la scacchiera
if(frame++ % quadrati_dt == 0) {
Mat resized;
resize(richiedi_frame_l_bn, resized, Size(cols* 2, rows * 2), 0.0, 0.0, INTER_LINEAR);
//Find chessboard corners:
cerca_0 = findChessboardCorners(resized/*richiedi_frame_l_bn*/, quadrati_sz, corners_0, CALIB_CB_NORMALIZE_IMAGE |CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_FILTER_QUADS); //CALIB_CB_NOTRMALIZE_IMAGE
imshow("Calibrazione_l", richiedi_frame_l_bn);resize(richiedi_frame_r_bn, resized, Size(cols* 2, rows * 2), 0.0, 0.0, INTER_LINEAR);
cerca_1 = findChessboardCorners(resized /*richiedi_frame_r_bn*/, quadrati_sz, corners_1,CALIB_CB_NORMALIZE_IMAGE |CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_FILTER_QUADS); //CALIB_CB_NOTRMALIZE_IMAGE
imshow("Calibrazione_r", richiedi_frame_r_bn);
if(cerca_0){
for (int i = 0; i < corners_0.size(); ++i) {
corners_0[i].x /= 2.0;
corners_0[i].y /= 2.0;
}
cornerSubPix(richiedi_frame_l_bn, corners_0, Size(5,5),Size(-1,-1), TermCriteria(TermCriteria::EPS | TermCriteria::COUNT , 5000000, 0.00000001 /*30, DBL_EPSILON*/));
//Draw it
drawChessboardCorners(richiedi_frame_l_bn, quadrati_sz, corners_0, cerca_0);
imshow("Calibrazione_l", richiedi_frame_l_bn);
}
if(cerca_1){
for (int i = 0; i < corners_1.size(); ++i) {
corners_1[i].x /= 2.0;
corners_1[i].y /= 2.0;
}
cornerSubPix(richiedi_frame_r_bn, corners_1, Size(5,5),Size(-1,-1), TermCriteria(TermCriteria::EPS | TermCriteria::COUNT , 50000000, 0.00000001));
//Draw it
drawChessboardCorners(richiedi_frame_r_bn, quadrati_sz, corners_1, cerca_1);
imshow("Calibrazione_r", richiedi_frame_r_bn);
}/*imagePoints1.push_back(corners1);
imagePoints2.push_back(corners2);
object_points.push_back(obj);*/
//nota molto bene l'errore che faceva esplodere l'rms della cameracalibrate era dovuto all'inversione di quadrati_w e quadrati_h nello scorrimento successivo
vector< Point3f > obj;
for (int i = 0; i < quadrati_w; i++){
for (int j = 0; j < quadrati_h; j++){
obj.push_back(Point3f((float)(j * caselle_dimensione), (float)(i * caselle_dimensione), 0));
}
}vector< Point3f > obj2;
for (int i = 0; i < quadrati_w; i++){
for (int j = 0; j < quadrati_h; j++){
obj2.push_back(Point3f((float)(j * caselle_dimensione), (float)(i * caselle_dimensione), 0));
}
}
//se su entrambe le camere ho trovato gli angoli salvo i dati
if(cerca_0 && cerca_1){
image_points_0.push_back(corners_0);
image_points_1.push_back(corners_1);
object_points_c0.push_back(obj);
object_points_c1.push_back(obj2);
point_counts_0.at<int>(trovato,0) = quadrati_n;
point_counts_1.at<int>(trovato,0) = quadrati_n;
trovato++;
cout<<"Trovato\n";
}//fine if cerca_0 && cerca_1} //fine del salto dei frame
//gestione pausa/smetti
int c = waitKey(15);
if(c == 'p'){
c = 0;
while(c != 'p' && c != 27){
c = waitKey(250);
}
}
if(c == 27){
return 0;
}
webcam_0.read(richiedi_frame_l); // cheido la prossima immagine e la converto, sto ciclando
cvtColor(richiedi_frame_l,richiedi_frame_l_bn,COLOR_BGR2GRAY);
webcam_1.read(richiedi_frame_r); // cheido la prossima immagine e la converto, sto ciclando
cvtColor(richiedi_frame_r,richiedi_frame_r_bn,COLOR_BGR2GRAY);
} //ABBIAMO RACCOLTO TUTTI I DATI Della scacchieta possiamo compensare
cout<< "abbiamo raccolto tutti i dati della scacchiera\n";for (int i = 0; i < image_points_0.size(); i++) {
vector< Point2f > v1, v2;
for (int j = 0; j < image_points_0[i].size(); j++) {
v1.push_back(Point2f((double)image_points_0[i][j].x, (double)image_points_0[i][j].y));
v2.push_back(Point2f((double)image_points_1[i][j].x, (double)image_points_1[i][j].y));
}
image_points_c0.push_back(v1);
image_points_c1.push_back(v2);
}// abbiamo tutti gli angoli che necessitiamo
//
intrinsic_matrix_0.at<float>(0,0) = 1.0f;
intrinsic_matrix_0.at<float>(1,1) = 1.0f;
intrinsic_matrix_1.at<float>(0,0) = 1.0f;
intrinsic_matrix_1.at<float>(1,1) = 1.0f;
//ABBIAMO PRELEVATO TUTTI I DATI DELLE CAMERE
destroyWindow("Calibrazione_r");
destroyWindow("Calibrazione_l");
cout<<"Calibriamo la camera\n";
int a= 0;
cin>>a;
}//fine if calibrazione
//CALIBRIAMO LE SINGOLE CAMERE
int calibrazione_singole_camere_ok= 1;
cout<<"Hai già calibrato le singole camere? premi 0 per calibrare oppure 1 per non calibrare\n";
cin>>calibrazione_singole_camere_ok;
Mat rvecs0, tvecs0, rvecs1, tvecs1;
if(!calibrazione_singole_camere_ok){
//NOTA MOLTO BENE IL FLAGS CHE DETERMINIAMO QUI DETRO PONE DOVE METTIAMO IL CENTRO DELLA RETTIFICAZIONE MOLTO IMPORTANTE PER LA DISTANZA E IL CALCOLO DELLE POSIZIONI
int flags= 0; // valore di default
//flags |= CV_CALIB_FIX_K4;
//flags |= CV_CALIB_FIX_K5;
//flags |= CV_CALIB_FIX_K6;
flags |= CV_CALIB_FIX_INTRINSIC;
flags |= CV_CALIB_FIX_PRINCIPAL_POINT;
//flags |= CALIB_FIX_S1_S2_S3_S4;
//flags |= CV_CALIB_ZERO_TANGENT_DIST;
flags |= CV_CALIB_FIX_ASPECT_RATIO;
//flags= CALIB_FIX_PRINCIPAL_POINT; //nota molto bene sta facendo solo questo fixing
//flags= CALIB_FIX_PRINCIPAL_POINT | CALIB_FIX_ASPECT_RATIO | CALIB_ZERO_TANGENT_DIST | CALIB_RATIONAL_MODEL | CALIB_FIX_K3 | CALIB_FIX_K4 | CALIB_FIX_K5;
/*flags – Different flags that may be zero or a combination of the following values:
– CV_CALIB_USE_INTRINSIC_GUESS cameraMatrix contains valid initial values of
fx, fy, cx, cy that are optimized further. Otherwise, (cx, cy) is initially set to the
image center ( imageSize is used), and focal distances are computed in a least-squares
fashion. Note, that if intrinsic parameters are known, there is no need to use this function
just to estimate extrinsic parameters. Use solvePnP() instead.
– CV_CALIB_FIX_PRINCIPAL_POINT The principal point is not changed during the
global optimization. It stays at the center or at a different location specified when
CV_CALIB_USE_INTRINSIC_GUESS is set too.
– CV_CALIB_FIX_ASPECT_RATIO The functions considers only fy as a free parameter.
The ratio fx/fy stays the same as in the input cameraMatrix . When
CV_CALIB_USE_INTRINSIC_GUESS is not set, the actual input values of fx and fy are
ignored, only their ratio is computed and used further.
– CV_CALIB_ZERO_TANGENT_DIST Tangential distortion coefficients (p1; p2) are
set to zeros and stay zero.
– CV_CALIB_FIX_K1,...,CV_CALIB_FIX_K6 The corresponding radial distortion coefficient
is not changed during the optimization. If CV_CALIB_USE_INTRINSIC_GUESS is
set, the coefficient from the supplied distCoeffs matrix is used. Otherwise, it is set to
0.
– CV_CALIB_RATIONAL_MODEL Coefficients k4, k5, and k6 are enabled. To provide
the backward compatibility, this extra flag should be explicitly specified to make the
calibration function use the rational model and return 8 coefficients. If the flag is not set,
the function computes and returns only 5 distortion coefficients.
– CALIB_THIN_PRISM_MODEL Coefficients s1, s2, s3 and s4 are enabled. To provide
the backward compatibility, this extra flag should be explicitly specified to make the calibration
function use the thin prism model and return 12 coefficients. If the flag is not set,
the function computes and returns only 5 distortion coefficients.
– CALIB_FIX_S1_S2_S3_S4 The thin prism distortion coefficients are not changed during
the optimization. If CV_CALIB_USE_INTRINSIC_GUESS is set, the coefficient from
the supplied distCoeffs matrix is used. Otherwise, it is set to 0.*/cout<< "Dimensione di objpoints ="<< object_points_c0.size()<< "dimensione di image_points_c0= "<<image_points_c0.size()<<"\n";
double rms_sinistra=calibrateCamera(object_points_c0, image_points_c0, richiedi_frame_l_bn.size(), intrinsic_matrix_0, distortion_coeffs_0, rvecs0, tvecs0,flags ,TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 5000000, 0.00000000001/*DBL_EPSILON*/));
double rms_destra= calibrateCamera(object_points_c1/*nb unico per i due*/, image_points_c1, richiedi_frame_r_bn.size(), intrinsic_matrix_1, distortion_coeffs_1, rvecs1, tvecs1,flags ,TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 5000000, 0.00000000001/*DBL_EPSILON*/));cout<<"abbiamo calibrato la singole camere\n"<<endl<<"destra con rms="<<rms_destra<<endl<<"sinistra con rms="<<rms_sinistra<<endl<<endl;
FileStorage fsl("StereoCalibration_Left.xml", FileStorage::WRITE); //abbiamo creato il file intrinsic
fsl << "intinsic_matrix" << intrinsic_matrix_0;//intirinsic_file.write(intrinsic_matrix_0);//
fsl << "distortion_coeffs"<< distortion_coeffs_0;
fsl.release(); //chiudo il file
FileStorage fsr("StereoCalibration_Right.xml", FileStorage::WRITE); //abbiamo creato il file intrinsic
fsr << "intinsic_matrix" << intrinsic_matrix_1;//intirinsic_file.write(intrinsic_matrix_0);//
fsr << "distortion_coeffs"<< distortion_coeffs_1;
fsr.release(); //chiudo il file
/*cout<<"comincio il primo conto"<<endl;
double compute1=(computeReprojectionErrors( object_points_c0, image_points_c0, rvecs0, tvecs0, intrinsic_matrix_0 ,distortion_coeffs_0));
cout<<"finito il primo conto"<<endl;
double compute2= (computeReprojectionErrors( object_points_c0, image_points_c1, rvecs1, tvecs1, intrinsic_matrix_1 ,distortion_coeffs_1));
cout<<"abbiamo un errore di "<<compute1<<"pixel a sinistra"<<endl;
cout<<"abbiamo un errore di "<<compute2<<"pixel a destra"<<endl;*/
}
//carichiamo i dati precedenti
else{
FileStorage fsl("StereoCalibration_Left.xml", FileStorage::READ); //abbiamo creato il file intrinsic
fsl["intrinsic_matrix"]>>intrinsic_matrix_0;//intirinsic_file.write(intrinsic_matrix_0);//
fsl["distortion_coeffs"]>> distortion_coeffs_0;
fsl.release(); //chiudo il file
FileStorage fsr("StereoCalibration_Right.xml", FileStorage::READ); //abbiamo creato il file intrinsic
fsr["intrinsic_matrix"]>>intrinsic_matrix_1;//intirinsic_file.write(intrinsic_matrix_0);//
fsr["distortion_coeffs"]>> distortion_coeffs_1;
fsr.release(); //chiudo il file
}
//FINE CALIBRAZIONE SINGOLE CAMERE/*
//TEST IMMAGINI INDISTORTE
int test_exit;
namedWindow("immagine sinistra originale", WINDOW_AUTOSIZE );
//namedWindow("immagine destra originale", WINDOW_AUTOSIZE );
namedWindow("immagine sinistra raddrizzata", WINDOW_AUTOSIZE );
//namedWindow("immagine destra raddrizzata", WINDOW_AUTOSIZE );
int t_indist;
int ciao= 1;
Mat test_copy;
while(ciao){
webcam_0.read(richiedi_frame_l); // cheido la prossima immagine e la converto, sto ciclando
cvtColor(richiedi_frame_l,richiedi_frame_l_bn,COLOR_BGR2GRAY);
webcam_1.read(richiedi_frame_r); // cheido la prossima immagine e la converto, sto ciclando
cvtColor(richiedi_frame_r,richiedi_frame_r_bn,COLOR_BGR2GRAY);
imshow("immagine sinistra originale", richiedi_frame_l_bn);
//imshow ("immagine destra originale", richiedi_frame_r_bn);
richiedi_frame_l_bn.copyTo(test_copy);
undistort(test_copy, richiedi_frame_l_bn, intrinsic_matrix_0, distortion_coeffs_0);
richiedi_frame_r_bn.copyTo(test_copy);
undistort(test_copy, richiedi_frame_r_bn, intrinsic_matrix_1, distortion_coeffs_1);imshow("immagine sinistra raddrizzata", richiedi_frame_l_bn);
//imshow ("immagine destra raddrizzata", richiedi_frame_r_bn);
test_exit =waitKey(10)%256;
if(h == 27){
waitKey(0);
ciao= 0;
}}destroyWindow("immagine sinistra originale");
//destroyWindow("immagine destra originale");
destroyWindow("immagine sinistra raddrizzata");
//destroyWindow("immagine destra raddrizzata");
//FINE TEST IMMAGINI INDISTORTE
*/
//CALIBRIAMO LE CAMERE STEREO
Mat R,F, E;
Vec3d T;
int calibrazione_stereo_camere_ok= 1;
cout<<"Hai già calibrato le camere stereo? premi 0 per calibrare oppure 1 per non calibrare\n";
cin>>calibrazione_stereo_camere_ok;int flags2= 0; // valore di default
//flags2 |= CV_CALIB_FIX_K4;
//flags2 |= CV_CALIB_FIX_K5;
//flags2 |= CV_CALIB_FIX_K3;
//flags2 |= CV_CALIB_FIX_INTRINSIC;
flags2 |= CV_CALIB_FIX_PRINCIPAL_POINT;
//flags2 |= CALIB_FIX_S1_S2_S3_S4;
//flags2 |= CV_CALIB_ZERO_TANGENT_DIST;
flags2 |= CV_CALIB_FIX_ASPECT_RATIO;
flags2 |=CV_CALIB_USE_INTRINSIC_GUESS;
//CV_CALIB_FIX_PRINCIPAL_POINT,//+
//CALIB_FIX_ASPECT_RATIO +
//CALIB_ZERO_TANGENT_DIST +
//CV_CALIB_FIX_INTRINSIC +
//CALIB_SAME_FOCAL_LENGTH +
//CALIB_USE_INTRINSIC_GUESS+
//CALIB_RATIONAL_MODEL +
//CALIB_FIX_K3 + CALIB_FIX_K4 + CALIB_FIX_K5,
if(!calibrazione_stereo_camere_ok){
double rms= stereoCalibrate(object_points_c0, image_points_c0, image_points_c1, intrinsic_matrix_0, distortion_coeffs_0, intrinsic_matrix_1, distortion_coeffs_1, richiedi_frame_l_bn.size(), R, T, E, F, flags2,
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 5000000, 0.00000000001/*DBL_EPSILON*/) );
cout << "done with RMS error=" << rms << endl;cout<<"calibrata adesso salviamo\n";
//SALVIAMO LA CALIBRAZIONE DEL PAIO STEREO
FileStorage fs1("CalibrazioneStereo.yml", cv::FileStorage::WRITE);
fs1 << "intrinsic_matrix_0" << intrinsic_matrix_0;
fs1 << "intrinsic_matrix_1" << intrinsic_matrix_1;
fs1 << "distortion_coeffes_0" << distortion_coeffs_0;
fs1 << "distortion_coeffs_1" << distortion_coeffs_1;
fs1 << "R" << R;
fs1 << "T" << T;
fs1 << "E" << E;
fs1 << "F" << F;
fs1.release();
}
else{
FileStorage fs1("CalibrazioneStereo.yml", cv::FileStorage::WRITE);
fs1 ["intrinsic_matrix_0"] >> intrinsic_matrix_0;
fs1 ["intrinsic_matrix_1"] >> intrinsic_matrix_1;
fs1 ["distortion_coeffes_0"] >> distortion_coeffs_0;
fs1 ["distortion_coeffs_1"] >> distortion_coeffs_1;
fs1 ["R"] >> R;
fs1 ["T"] >> T;
fs1 ["E"] >> E;
fs1 ["F"] >> F;
fs1.release();
}//CAMERE CALIBRATE E DATI SALVATI E RICARICATI
//CALCOLIAMO LA STEREORECTIFY E SALVIAMO
Mat R1, R2, P1, P2, Q;
if(!calibrazione_stereo_camere_ok){
stereoRectify(intrinsic_matrix_0, distortion_coeffs_0, intrinsic_matrix_1, distortion_coeffs_1, richiedi_frame_l_bn.size(), R, T, R1, R2, P1, P2, Q);
//SALVIAMO I NOSTRI DATI FINALI
FileStorage fs2("CalibrazioneStereo.yml", cv::FileStorage::WRITE);
fs2 << "R1" << R1;
fs2 << "R2" << R2;
fs2 << "P1" << P1;
fs2 << "P2" << P2;
fs2 << "Q" << Q;
fs2.release();
}
else{
FileStorage fs2("CalibrazioneStereo.yml", cv::FileStorage::READ);
fs2 ["R1"] >> R1;
fs2 ["R2"] >> R2;
fs2 ["P1"] >> P1;
fs2 ["P2"] >> P2;
fs2 ["Q"] >> Q;
fs2.release();
}//ABBIAMO CALCAOLATO E SALVATO I DATI//////////////////////////////////////////////////////////////////////SIAMO QUI SI DEVE FARE LA UNDISTORT PER CREARE LE DUE MAPEP DA USARE CON REMAP
// COTRUIAMO LA MAPPA DI INDISTORSIONE DA USARE SU TUTTI I FRAME
Mat mappal_x, mappal_y, mappar_x, mappar_y;
initUndistortRectifyMap(intrinsic_matrix_0, distortion_coeffs_0, R1, P1, richiedi_frame_l_bn.size(), CV_32F, mappal_x, mappal_y);
initUndistortRectifyMap(intrinsic_matrix_1, distortion_coeffs_1, R2, P2, richiedi_frame_r_bn.size(), CV_32F, mappar_x, mappar_y);
//ABBIAMO LE MAPPE DI INDISTORSIONE POSSIAMO PROCEDERE CON LA REMAP//cout << "Calibration error_l: " << computeReprojectionErrors(object_points_c0, image_points_c0, rvecs0, tvecs0, intrinsic_matrix_0, distortion_coeffs_0) << endl;
//cout << "Calibration error_r: " << computeReprojectionErrors(object_points_c0, image_points_c1, rvecs1, tvecs1, intrinsic_matrix_1, distortion_coeffs_1) << endl;
char window_name[100] = "3D vision press n normal, b 3D \"ESC\" to exit";
namedWindow(window_name, WINDOW_AUTOSIZE);//creo la finestra//AVVIO RIPRODUZIONE DEL VIDEO 3D
while(1) //reading frames from webcam_0
{
if(!webcam_0.read(frame_r))
{
cout << "nessuna immagine dalla camera destra" << endl;
waitKey(0);
return -1;
}if(!webcam_1.read(frame_l))
{
cout << "nessuna immagine dalla camera sinistra" << endl;
waitKey(0);
return -1;
}//estremi da cotrollare
double minVal;
double maxVal;
//creiamo le strutture per il calcolo della disparità
int ndisparities = 16;//16*1; /**< Range of disparity */
int SADWindowSize = 9; /**< Size of the block window. Must be odd */ //dobbiamo controllare questi valori a modo
Ptr<StereoBM> sbm = StereoBM::create( ndisparities, SADWindowSize );//sbm->setSADWindowSize(9);
//sbm->setNumberOfDisparities(112);
sbm->setMinDisparity(0);
sbm->setPreFilterSize(21);//5/255
sbm->setPreFilterCap(31); //1/63
sbm->setTextureThreshold(10);
sbm->setUniquenessRatio(15);
sbm->setSpeckleRange(0);
sbm->setSpeckleWindowSize(0);
sbm->setDisp12MaxDiff(0);
//seleziono la modalità
switch(count){
//visione normale
case 0:imshow(window_name, frame_r); //riproduce il frame destro
break;//visione 3D
case 1:
cvtColor(frame_r,frame_r_bn,COLOR_RGB2GRAY);
cvtColor(frame_l, frame_l_bn,COLOR_RGB2GRAY);//raddriziamo le due immagini //AGGIUNTA ORA ADESSO GUARDIAMO COME SISTEMARLO
copy_temp= frame_l_bn.clone();
remap(copy_temp, frame_l_bn, mappal_x, mappal_y, cv::INTER_LINEAR);
copy_temp= frame_r_bn.clone();
remap(copy_temp, frame_r_bn, mappar_x, mappar_y, cv::INTER_LINEAR );
//raddrizza immagine
//cvReleaseMat(&t);//calcoliamo la disparità
sbm->compute( frame_l_bn, frame_r_bn, disparity16s); //calcoliamo l'immagine di disparità
//sbm(frame_r_bn, frame_l_bn, disparity16s);
//normalize(disparity16s, disparity_project, 0, 255, CV_MINMAX, CV_8U);//controlliamo i due estremi
//minMaxLoc( disparity16s, &minVal, &maxVal );
//converto l'immagine in una visibile
//disparity16s.convertTo( disparity_project, CV_8UC1);
normalize(disparity16s, disparity_project, 0.1, 255, NORM_MINMAX, CV_8U);//test
imshow(window_name, disparity_project);
imshow("immagine sinistra", frame_l_bn);
imshow ("imamgine destra", frame_r_bn);
break;
case 2:imshow(window_name, frame_l); //riproduce il frame destro
break;
//visione senza nessuna modifica
default:
imshow(window_name, frame_r); //riproduce il frame destro
break;
}
int w_ait = waitKey(10)%256;
if (w_ait == 27) //check if ESC is pressed
{
cout << "bye!" << endl;
waitKey(0);
return 0;
}
if (w_ait == 98) //check if b is pressed for black edge vision
{
count= 1;
}
if (w_ait == 107) //check if n is pressed for black edge vision
{
count= 0;
}
if (w_ait == 97) //check if n is pressed for black edge vision
{
count= 2;
}
}
return 0;
}
Спасибо за все время, которое вы потратите на мой вопрос
Задача ещё не решена.
Других решений пока нет …