1.双目摄像头只能打开一个
这个和摄像头的参数有关,这种只有一个usb的双目摄像头只有在特定分辨率及特定的解码方式的时候才会启动双目摄像头,否则只会启动一个摄像头
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#include<opencv2/opencv.hpp> #include<iostream> using namespace cv; using namespace std; int main() { VideoCapture cap; cap.open(0); if (!cap.isOpened()) { std::cout << "open fail"; return 0; } cap.set(CAP_PROP_FRAME_WIDTH, 1280); cap.set(CAP_PROP_FRAME_HEIGHT, 240); cap.set(CAP_PROP_FOURCC, '2YUY'); int hw = cap.get(CAP_PROP_FRAME_WIDTH); int hh = cap.get(CV_CAP_PROP_FRAME_HEIGHT); Mat frame; while (1) { cap.retrieve(frame, 0);//这里采集为空 if (frame.empty()) break; imshow("video", frame); waitKey(5); } cap.release(); } |
2.imread()报错 Access violation reading location
把debug修改为release就可以了,没有看到其他解决方法,真是服了!
记录一下从视频采集图像的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
#if 1//运行前改成1 #include<opencv2/opencv.hpp> #include<stdlib.h> using namespace cv; using namespace std; void main() { VideoCapture cap; cap.open(0); // 打开摄像头 if (!cap.isOpened()) // 如果视频不能正常打开则返回 return; cvWaitKey(30); cap.set(CAP_PROP_FRAME_WIDTH, 1280); cap.set(CAP_PROP_FRAME_HEIGHT, 240); cap.set(CAP_PROP_FOURCC, '2YUY'); Mat frame;//用于保存每一帧图像 cap >> frame; imshow("【双目原始视图】", frame); cvWaitKey(300); //system("C:\\\"Program Files (x86)\"\\\"CHUSEI 3D Webcam\"\\\"CHUSEI 3D Webcam.exe\""); char buf[100] = { 0 }; // 保存路径变量 while (1) { cap >> frame; // 等价于cap.read(frame); if (frame.empty()) // 如果某帧为空则退出循环 break; imshow("【双目原始视图】", frame); // 显示双目原始图像 原始分辨率为 640*480 Mat DoubleImage; resize(frame, DoubleImage, Size(640, 240), (0, 0), (0, 0), INTER_AREA); // 纵向分辨率缩小一半 imshow("【双目缩小视图】", DoubleImage); //显示图像 Mat LeftImage = DoubleImage(Rect(0, 0, 320, 240)); // 分割得到左视图 Mat RightImage = DoubleImage(Rect(320, 0, 320, 240)); // 分割得到右视图 imshow("【左视图】", LeftImage); // 显示左视图 imshow("【右视图】", RightImage); // 显示右视图 char c = cvWaitKey(30); if (c == 27)// Esc键退出 { break; } static int i = 9; if (13 == char(c)) { sprintf(buf, ".\\picture\\left_%d.png", i); // 保存左视图 cout << buf; imwrite(buf, LeftImage); sprintf(buf, ".\\picture\\right_%d.png", i); // 保存右视图 imwrite(buf, RightImage); sprintf(buf, ".\\picture\\total_%d.png", i); //保存整体图像 imwrite(buf, DoubleImage); i++; } } cap.release();// 释放资源 } #endif |
3. 标定摄像头 cv::Exception at memory location
一定要保证在上一步添加的标定图片都是有效的图片,在程序中会打印出来,一共多少张图 那么多少张图就必须是有效的,否则就会报这个错误,真是服了!而且也硬顶要在release的环境下运行!还有一个错误是说fopen 不安全 加上下面的第一行就可以了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
#pragma warning(disable:4996) #if 1 //运行前改成1 #include <iostream> #include <stdio.h> #include <time.h> #include <iostream> #include <stdio.h> #include <string.h> #include<opencv2/opencv.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/calib3d/calib3d.hpp> #include <opencv2/calib3d/calib3d.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/core/core.hpp> #include<stdlib.h> #include<Windows.h> //此处参数需要根据棋盘格个数修改 //例如 黑白棋盘格 宽(w)为10个棋盘格 那么 w 为 10 -1 = 9 #define w 9 //棋盘格宽的黑白交叉点个数 #define h 6 //棋盘格高的黑白交叉点个数 const float chessboardSquareSize = 12.5f; //每个棋盘格方块的边长 单位 为 mm using namespace std; using namespace cv; //从 xml 文件中读取图片存储路径 static bool readStringList(const string& filename, vector<string>& list) { list.resize(0); FileStorage fs(filename, FileStorage::READ); if (!fs.isOpened()) return false; FileNode n = fs.getFirstTopLevelNode(); if (n.type() != FileNode::SEQ) return false; FileNodeIterator it = n.begin(), it_end = n.end(); for (; it != it_end; ++it) list.push_back((string)*it); return true; } //记录棋盘格角点个数 static void calcChessboardCorners(Size boardSize, float squareSize, vector<Point3f>& corners) { corners.resize(0); for (int i = 0; i < boardSize.height; i++) //height和width位置不能颠倒 for (int j = 0; j < boardSize.width; j++) { corners.push_back(Point3f(j*squareSize, i*squareSize, 0)); } } bool calibrate(Mat& intrMat, Mat& distCoeffs, vector<vector<Point2f>>& imagePoints, vector<vector<Point3f>>& ObjectPoints, Size& imageSize, const int cameraId, vector<string> imageList) { double rms = 0; //重投影误差 Size boardSize; boardSize.width = w; boardSize.height = h; vector<Point2f> pointBuf; float squareSize = chessboardSquareSize; vector<Mat> rvecs, tvecs; //定义两个摄像头的旋转矩阵 和平移向量 bool ok = false; int nImages = (int)imageList.size() / 2; cout << "图片张数" << nImages; namedWindow("View", 1); int nums = 0; //有效棋盘格图片张数 for (int i = 0; i < nImages; i++) { Mat view, viewGray; view = imread(imageList[i * 2 + cameraId], 1); //读取图片 imageSize = view.size(); cvtColor(view, viewGray, COLOR_BGR2GRAY); //转化成灰度图 bool found = findChessboardCorners(view, boardSize, pointBuf, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FAST_CHECK | CV_CALIB_CB_NORMALIZE_IMAGE); //寻找棋盘格角点 if (found) { nums++; cornerSubPix(viewGray, pointBuf, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1)); drawChessboardCorners(view, boardSize, Mat(pointBuf), found); bitwise_not(view, view); imagePoints.push_back(pointBuf); cout << '.'; } imshow("View", view); waitKey(50); } cout << "有效棋盘格张数" << nums << endl; //calculate chessboardCorners calcChessboardCorners(boardSize, squareSize, ObjectPoints[0]); ObjectPoints.resize(imagePoints.size(), ObjectPoints[0]); rms = calibrateCamera(ObjectPoints, imagePoints, imageSize, intrMat, distCoeffs, rvecs, tvecs); ok = checkRange(intrMat) && checkRange(distCoeffs); if (ok) { cout << "done with RMS error=" << rms << endl; return true; } else return false; } int main() { //initialize some parameters bool okcalib = false; Mat intrMatFirst, intrMatSec, distCoeffsFirst, distCoffesSec; Mat R, T, E, F, RFirst, RSec, PFirst, PSec, Q; vector<vector<Point2f>> imagePointsFirst, imagePointsSec; vector<vector<Point3f>> ObjectPoints(1); Rect validRoi[2]; Size imageSize; int cameraIdFirst = 0, cameraIdSec = 1; double rms = 0; //get pictures and calibrate vector<string> imageList; string filename = "stereo_calibration.xml"; bool okread = readStringList(filename, imageList); if (!okread || imageList.empty()) { cout << "can not open " << filename << " or the string list is empty" << endl; return false; } if (imageList.size() % 2 != 0) { cout << "Error: the image list contains odd (non-even) number of elements\n"; return false; } FileStorage fs("intrinsics.yml", FileStorage::WRITE); //calibrate cout << "calibrate left camera..." << endl; okcalib = calibrate(intrMatFirst, distCoeffsFirst, imagePointsFirst, ObjectPoints, imageSize, cameraIdFirst, imageList); if (!okcalib) { cout << "fail to calibrate left camera" << endl; return -1; } else { cout << "calibrate the right camera..." << endl; } okcalib = calibrate(intrMatSec, distCoffesSec, imagePointsSec, ObjectPoints, imageSize, cameraIdSec, imageList); fs << "M1" << intrMatFirst << "D1" << distCoeffsFirst << "M2" << intrMatSec << "D2" << distCoffesSec; if (!okcalib) { cout << "fail to calibrate the right camera" << endl; return -1; } destroyAllWindows(); //estimate position and orientation cout << "estimate position and orientation of the second camera" << endl << "relative to the first camera..." << endl; cout << intrMatFirst; cout << distCoeffsFirst; cout << intrMatSec; cout << distCoffesSec; rms = stereoCalibrate(ObjectPoints, imagePointsFirst, imagePointsSec, intrMatFirst, distCoeffsFirst, intrMatSec, distCoffesSec, imageSize, R, T, E, F, CALIB_USE_INTRINSIC_GUESS,//CV_CALIB_FIX_INTRINSIC, TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, 1e-6)); //计算重投影误差 cout << "done with RMS error=" << rms << endl; //stereo rectify cout << "stereo rectify..." << endl; stereoRectify(intrMatFirst, distCoeffsFirst, intrMatSec, distCoffesSec, imageSize, R, T, RFirst, RSec, PFirst, PSec, Q, CALIB_ZERO_DISPARITY, -1, imageSize, &validRoi[0], &validRoi[1]); cout << "Q" << Q << endl; cout << "P1" << PFirst << endl; cout << "P2" << PSec << endl; //read pictures for 3d-reconstruction if (fs.isOpened()) { cout << "in"; fs << "R" << R << "T" << T << "R1" << RFirst << "R2" << RSec << "P1" << PFirst << "P2" << PSec << "Q" << Q; fs.release(); } namedWindow("canvas", 1); cout << "read the picture for 3d-reconstruction..."; Mat canvas(imageSize.height, imageSize.width * 2, CV_8UC3), viewLeft, viewRight; Mat canLeft = canvas(Rect(0, 0, imageSize.width, imageSize.height)); Mat canRight = canvas(Rect(imageSize.width, 0, imageSize.width, imageSize.height)); viewLeft = imread(imageList[6], 1);//cameraIdFirst viewRight = imread(imageList[7], 1); //cameraIdSec viewLeft.copyTo(canLeft); viewRight.copyTo(canRight); cout << "done" << endl; imshow("canvas", canvas); waitKey(50); //必须要加waitKey ,否则可能存在无法显示图像问题 //stereoRectify Mat rmapFirst[2], rmapSec[2], rviewFirst, rviewSec; initUndistortRectifyMap(intrMatFirst, distCoeffsFirst, RFirst, PFirst, imageSize, CV_16SC2, rmapFirst[0], rmapFirst[1]);//CV_16SC2 initUndistortRectifyMap(intrMatSec, distCoffesSec, RSec, PSec,//CV_16SC2 imageSize, CV_16SC2, rmapSec[0], rmapSec[1]); remap(viewLeft, rviewFirst, rmapFirst[0], rmapFirst[1], INTER_LINEAR); imshow("remap", rviewFirst); waitKey(40); remap(viewRight, rviewSec, rmapSec[0], rmapSec[1], INTER_LINEAR); rviewFirst.copyTo(canLeft); rviewSec.copyTo(canRight); //rectangle(canLeft, validRoi[0], Scalar(255, 0, 0), 3, 8); //rectangle(canRight, validRoi[1], Scalar(255, 0, 0), 3, 8); Mat before_rectify = imread("./picture/total_0.png"); for (int j = 0; j <= canvas.rows; j += 16) //画绿线 line(canvas, Point(0, j), Point(canvas.cols, j), Scalar(0, 255, 0), 1, 8); for (int j = 0; j <= canvas.rows; j += 16) //画绿线 line(before_rectify, Point(0, j), Point(canvas.cols, j), Scalar(0, 255, 0), 1, 8); cout << "stereo rectify done" << endl; // imshow("校正前", before_rectify); //显示画绿线的校正后图像 // imshow("校正后", canvas); //显示画绿线的校正前图像 waitKey(400000);//必须要加waitKey ,否则可能存在无法显示图像问题 //必须要加waitKey ,否则可能存在无法显示图像问题 /* 官方解释 http://masikkk.com/article/OpenCV-imshow-waitkey/ A common mistake for OpenCV newcomers is to call cv::imshow() in a loop through video frames, without following up each draw with cv::waitKey(30).In this case, nothing appears on screen, because highgui is never given time to process the draw requests from cv::imshow(). */ return 0; } #endif |