相機(jī)已經(jīng)存在了很長時間。然而,隨著 20 世紀(jì)后期廉價針孔相機(jī)的推出,它們在我們的日常生活中變得司空見慣。不幸的是,這種廉價是有代價的:嚴(yán)重的失真。幸運(yùn)的是,這些是常數(shù),通過校準(zhǔn)和一些重新映射,我們可以糾正這一點(diǎn)。此外,通過校準(zhǔn),您還可以確定相機(jī)的自然單位(像素)與現(xiàn)實(shí)世界單位(例如毫米)之間的關(guān)系。
理論
對于畸變,OpenCV 考慮了徑向和切向因素。對于徑向因子,使用以下公式:
因此,對于 (x,y) 坐標(biāo)處未失真的像素點(diǎn),它在失真圖像上的位置將為 (x_{distorted} y_{distorted})。徑向畸變的存在以“桶”或“魚眼”效應(yīng)的形式表現(xiàn)出來。(x,y)(xdIS T ORTEdydIS T ORTEd)
切向畸變的發(fā)生是因?yàn)榕臄z圖像的鏡頭與成像平面不完全平行。它可以通過以下公式表示:
因此,我們有五個失真參數(shù),在 OpenCV 中,這些參數(shù)表示為具有 5 列的一行矩陣:
現(xiàn)在對于單位轉(zhuǎn)換,我們使用以下公式:
在這里,w 的存在通過使用單調(diào)坐標(biāo)系(和 w=Z)來解釋。未知參數(shù)是 f_x 和 f_y(相機(jī)焦距)和 (c_x, c_y),它們是以像素坐標(biāo)表示的光學(xué)中心。如果對于兩個軸,使用具有給定縱橫比(通常為 1)的公共焦距,則 f_y=f_xa,在上面的公式中,我們將有一個焦距 f。包含這四個參數(shù)的矩陣稱為相機(jī)矩陣*。雖然無論使用何種相機(jī)分辨率,失真系數(shù)都是相同的,但這些失真系數(shù)應(yīng)與校準(zhǔn)分辨率的當(dāng)前分辨率一起縮放。ww=Zfxfy(cx,cy)一個fy=fx?af
確定這兩個矩陣的過程就是校準(zhǔn)。這些參數(shù)的計算是通過基本的幾何方程完成的。使用的方程式取決于所選的校準(zhǔn)對象。目前 OpenCV 支持三種類型的對象進(jìn)行校準(zhǔn):
- 經(jīng)典黑白棋盤
- ChArUco板圖案
- 對稱圓形圖案
- 不對稱圓形圖案
基本上,您需要用相機(jī)拍攝這些模式的快照,并讓 OpenCV 找到它們。每個找到的模式都會產(chǎn)生一個新方程。要求解方程,您至少需要預(yù)定數(shù)量的模式快照來形成一個適配方程組。這個數(shù)字對于棋盤模式來說較高,而對于圓盤模式來說,這個數(shù)字較小。例如,從理論上講,棋盤模式至少需要兩個快照。然而,在實(shí)踐中,我們的輸入圖像中存在大量的噪點(diǎn),因此為了獲得良好的效果,您可能需要至少 10 張不同位置的輸入模式的良好快照。
目標(biāo)
示例應(yīng)用程序?qū)ⅲ?/p>
- 確定失真矩陣
- 確定相機(jī)矩陣
- 從相機(jī)、視頻和圖像文件列表中獲取輸入
- 從 XML/YAML 文件讀取配置
- 將結(jié)果保存到 XML/YAML 文件中
- 計算重投影誤差
源代碼
您也可以在 OpenCV 源代碼庫的文件夾中找到源代碼或從此處下載。對于程序的用法,請使用參數(shù)運(yùn)行它。該程序有一個基本參數(shù):其配置文件的名稱。如果沒有給出,那么它將嘗試打開名為“default.xml”的那個。下面是 XML 格式的示例配置文件。在配置文件中,您可以選擇使用相機(jī)作為輸入、視頻文件或圖像列表。如果選擇最后一個,則需要創(chuàng)建一個配置文件,在其中枚舉要使用的映像。下面是一個示例。要記住的重要部分是,需要使用應(yīng)用程序工作目錄中的絕對路徑或相對路徑來指定圖像。您可以在上面提到的示例目錄中找到所有這些內(nèi)容。samples/cpp/tutorial_code/calib3d/camera_calibration/``-h
應(yīng)用程序從配置文件中讀取設(shè)置后啟動。雖然這是其中的一個重要部分,但它與本教程的主題無關(guān):相機(jī)校準(zhǔn)。因此,我選擇不在此處發(fā)布該部分的代碼。有關(guān)如何執(zhí)行此操作的技術(shù)背景,請參閱使用 XML 和 YAML 文件的文件輸入和輸出教程。
解釋
-
閱讀設(shè)置
設(shè)置 s;
? const string inputSettingsFile = parser.get(0);
FileStorage fs(inputSettingsFile, FileStorage::READ);讀取設(shè)置
? 如果 (!fs.isOpened())
? {
cout << “無法打開配置文件:\”“ << inputSettingsFile << ”\“” << endl;
解析器.printMessage();
? 返回 -1;
? }
fs[“設(shè)置”] >> s;
fs.release();關(guān)閉設(shè)置文件
為此,我使用了簡單的 OpenCV 類輸入操作。閱讀文件后,我有一個額外的后處理功能來檢查輸入的有效性。只有當(dāng)所有輸入都良好時,goodInput 變量才會為 true。
-
獲取下一個輸入,如果它失敗了,或者我們有足夠的輸入 - 校準(zhǔn)
在此之后,我們有一個大循環(huán),我們在其中執(zhí)行以下操作:從圖像列表、相機(jī)或視頻文件中獲取下一張圖像。如果這失敗了,或者我們有足夠的圖像,那么我們就會運(yùn)行校準(zhǔn)過程。在圖像的情況下,我們跳出循環(huán),否則,通過從檢測模式更改為校準(zhǔn)模式,剩余的幀將不會失真(如果設(shè)置了選項(xiàng))。
? 為(;??
? {
墊子視圖;
? bool blinkOutput = 假;
視圖 = s.nextImage();
? ----- 如果沒有更多的圖像,或者沒有足夠的圖像,則停止校準(zhǔn)并顯示結(jié)果-------------
? if( mode == CAPTURING && imagePoints.size() >= (size_t)s.nrFrames )
? {
? if(runCalibrationAndSave(s, imageSize, cameraMatrix, distCoeffs, imagePoints, grid_width,
release_object))
模式 = 校準(zhǔn);
? 還
模式 = 檢測;
? }
? if(view.empty()) // 如果沒有更多的圖片,請停止循環(huán)
? {
? 如果尚未達(dá)到校準(zhǔn)閾值,請立即校準(zhǔn)
? if( mode != 校準(zhǔn) && !imagePoints.empty() )
runCalibrationAndSave(s, imageSize, cameraMatrix, distCoeffs, imagePoints, grid_width,
release_object);
? 破;
? }
對于某些相機(jī),我們可能需要翻轉(zhuǎn)輸入圖像。在這里,我們也這樣做。
-
在當(dāng)前輸入中查找模式
我上面提到的方程式的形成旨在找到輸入中的主要模式:在棋盤的情況下,這是正方形的角,對于圓來說,嗯,圓本身。ChArUco 棋盤相當(dāng)于棋盤,但角由 ArUco 標(biāo)記進(jìn)行加工。它們的位置將形成結(jié)果,該結(jié)果將被寫入 pointBuf 向量。
vector pointBuf;
? 發(fā)現(xiàn)布爾;
? int chessBoardFlags = CALIB_CB_ADAPTIVE_THRESH |CALIB_CB_NORMALIZE_IMAGE;
? 如果(!s.useFisheye) {
? 快速檢查錯誤地失敗,出現(xiàn)魚眼等高失真
chessBoardFlags |= CALIB_CB_FAST_CHECK;
? }
? switch( s.calibrationPattern ) // 在輸入格式上查找特征點(diǎn)
? {
? 箱設(shè)置::CHESSBOARD:
found = findChessboardCorners( view, s.boardSize, pointBuf, chessBoardFlags);
? 破;
? 箱設(shè)置::CHARUCOBOARD:
ch_detector.detectBoard( view, pointBuf, markerIds);
found = pointBuf.size() == (size_t)((s.boardSize.height - 1)*(s.boardSize.width - 1));
? 破;
? 箱設(shè)置::CIRCLES_GRID:
found = findCirclesGrid( view, s.boardSize, pointBuf );
? 破;
? 箱設(shè)置::ASYMMETRIC_CIRCLES_GRID:
found = findCirclesGrid( view, s.boardSize, pointBuf, CALIB_CB_ASYMMETRIC_GRID );
? 破;
? 默認(rèn)值:
發(fā)現(xiàn) = 假;
? 破;
? }
根據(jù)輸入模式的類型,您可以使用 cv::findChessboardCorners 或 cv::findCirclesGrid 函數(shù)或 cv::aruco::CharucoDetector::d etectBoard 方法。對于所有這些,您傳遞當(dāng)前圖像和電路板的大小,您將獲得圖案的位置。cv::findChessboardCorners 和 cv::findCirclesGrid 返回一個布爾變量,該變量說明是否在輸入中找到了模式(我們只需要考慮那些確實(shí)如此的圖像! 可以檢測部分可見的圖案,并返回可見內(nèi)角的坐標(biāo)和 ID。
CharucoDetector::detectBoard
-
注意
棋盤大小和匹配點(diǎn)數(shù)對于棋盤、圓圈網(wǎng)格和 ChArUco 是不同的。所有與棋盤相關(guān)的算法都期望內(nèi)角的數(shù)量作為棋盤的寬度和高度。圓網(wǎng)格的板大小只是兩個網(wǎng)格尺寸的圓數(shù)。ChArUco 板尺寸以正方形為單位定義,但檢測結(jié)果是內(nèi)角列表,這就是為什么在兩個尺寸中都小 1 的原因。
再說一次,對于相機(jī),我們只在輸入延遲時間過后才拍攝相機(jī)圖像。這樣做是為了讓用戶移動棋盤并獲得不同的圖像。相似的圖像會產(chǎn)生相似的方程,而校準(zhǔn)步驟中的相似方程將形成一個病態(tài)問題,因此校準(zhǔn)將失敗。對于正方形圖像,角的位置只是近似值。我們可以通過調(diào)用 cv::cornerSubPix 函數(shù)來改進(jìn)這一點(diǎn)。( 用于控制搜索窗口的邊長。其默認(rèn)值為 11。 可以通過命令行參數(shù)進(jìn)行更改。它將產(chǎn)生更好的校準(zhǔn)結(jié)果。在此之后,我們將有效的輸入結(jié)果添加到 imagePoints 向量中,以將所有方程收集到一個容器中。最后,出于可視化反饋目的,我們將使用 cv::findChessboardCorners 函數(shù)在輸入圖像上繪制找到的點(diǎn)。
winSize``winSize``--winSize=<number>
? if (found) // 如果成功完成,
? {
? 提高棋盤找到的角坐標(biāo)精度
? if( s.calibrationPattern == 設(shè)置::CHESSBOARD)
? {
墊子視圖灰色;
? cvtColor(視圖, 視圖灰色, COLOR_BGR2GRAY);
? cornerSubPix( viewGray, pointBuf, Size(winSize,winSize),
? Size(-1,-1), TermCriteria( TermCriteria::EPS+TermCriteria::COUNT, 30, 0.0001 ));
? }
? if( mode == CAPTURING && // 對于相機(jī),只在延遲時間后拍攝新樣本
(!s.inputCapture.isOpened() || clock() - prevTimestamp > s.delay1e-3CLOCKS_PER_SEC) ) )
? {
imagePoints.push_back(點(diǎn));
prevTimestamp = 時鐘();
blinkOutput = s.inputCapture.isOpened();
? }
? 畫出角落。
? if(s.calibrationPattern == 設(shè)置::CHARUCOBOARD)
? drawChessboardCorners( view, cv::Size(s.boardSize.width-1, s.boardSize.height-1), Mat(pointBuf), 找到 );
? 還
? drawChessboardCorners( view, s.boardSize, Mat(pointBuf), 找到 );
? }
-
-
向用戶顯示狀態(tài)和結(jié)果,以及應(yīng)用程序的命令行控制
此部分顯示圖像上的文本輸出。
? string msg = (mode == CAPTURING) ?“100/100”:
模式 == 校準(zhǔn) ?“Calibrated” : “按’g’開始”;
? int 基線 = 0;
? 尺寸 textSize = getTextSize(msg, 1, 1, 1, &baseLine);
? 點(diǎn) textOrigin(view.cols - 2textSize.width - 10, view.rows - 2baseLine - 10);
? if( 模式 == 捕獲 )
? {
? if(s.showUndistorted)
msg = cv::format( “%d/%d Undist”, (int)imagePoints.size(), s.nrFrames );
? 還
msg = cv::format( “%d/%d”, (int)imagePoints.size(), s.nrFrames );
? }
? putText( view, msg, textOrigin, 1, 1, mode == 校準(zhǔn) ?綠色:紅色);
? 如果( blink輸出 )
? bitwise_not(視圖,視圖);
如果我們運(yùn)行校準(zhǔn)并得到帶有失真系數(shù)的相機(jī)矩陣,我們可能需要使用 cv::undistort 函數(shù)校正圖像:
? if( mode == 校準(zhǔn) && s.showUndistorted )
? {
墊溫度 = view.clone();
? 如果 (s.useFisheye)
? {
墊子 newCamMat;
? fisheye::estimateNewCameraMatrixForUndistortRectify(cameraMatrix, distCoeffs, imageSize,
Matx33d::eye(), newCamMat, 1);
? cv::fisheye::undistortImage(temp, view, cameraMatrix, distCoeffs, newCamMat);
? }
? 還
? undistort(temp, view, cameraMatrix, distCoeffs);
? }
然后我們顯示圖像并等待輸入鍵,如果這是 u,我們切換失真消除,如果是 g,我們再次開始檢測過程,最后對于 ESC 鍵,我們退出應(yīng)用程序:
? imshow(“圖像視圖”, 視圖);
? char key = (char)waitKey(s.inputCapture.isOpened() ? 50 : s.delay);
? if( 鍵 == ESC_KEY )
? 破;
? if( key == ‘u’ && mode == 校準(zhǔn) )
s.showUndistorted = !s.showUndistorted;
? if( s.inputCapture.isOpened() && 鍵 == ‘g’ )
? {
mode = 捕獲;
imagePoints.clear();
? }
-
同時顯示圖像的失真消除
使用圖像列表時,無法消除循環(huán)內(nèi)部的失真。因此,您必須在循環(huán)之后執(zhí)行此操作?,F(xiàn)在,我將利用這一點(diǎn)來擴(kuò)展 cv::undistort 函數(shù),該函數(shù)實(shí)際上首先調(diào)用 cv::initUndistortRectifyMap 來查找變換矩陣,然后使用 cv::remap 函數(shù)執(zhí)行變換。因?yàn)椋诔晒π?zhǔn)圖計算后,只需執(zhí)行一次,因此通過使用此擴(kuò)展表單,您可以加快應(yīng)用速度:
? if( s.inputType == Settings::IMAGE_LIST && s.showUndistorted && !cameraMatrix.empty())
? {
墊視圖、rview、map1、map2;
? 如果 (s.useFisheye)
? {
墊子 newCamMat;
? fisheye::estimateNewCameraMatrixForUndistortRectify(cameraMatrix, distCoeffs, imageSize,
Matx33d::eye(), newCamMat, 1);
? fisheye::initUndistortRectifyMap(cameraMatrix, distCoeffs, Matx33d::eye(), newCamMat, imageSize,
? CV_16SC2, map1, map2);
? }
? 還
? {
? initUndistortRectifyMap(
cameraMatrix、distCoeffs、Mat()、
? getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0), imageSize,
? CV_16SC2, map1, map2);
? }
? for(size_t i = 0; i < s.imageList.size(); i++ )
? {
視圖 = imread(s.imageList[i], IMREAD_COLOR);
? 如果(view.empty())
? 繼續(xù);
? remap(view, rview, map1, map2, INTER_LINEAR);
? imshow(“圖像視圖”, rview);
? char c = (char)waitKey();
? if( c == ESC_KEY || c == ‘q’ || c == ‘Q’ )
? 破;
? }
? }
校準(zhǔn)和保存
由于每臺相機(jī)只需進(jìn)行一次校準(zhǔn),因此在校準(zhǔn)成功后保存校準(zhǔn)是有意義的。這樣,以后您就可以將這些值加載到程序中。因此,我們首先進(jìn)行校準(zhǔn),如果校準(zhǔn)成功,我們將結(jié)果保存到 OpenCV 樣式的 XML 或 YAML 文件中,具體取決于您在配置文件中提供的擴(kuò)展名。
因此,在第一個函數(shù)中,我們只是拆分了這兩個進(jìn)程。由于我們想要保存許多校準(zhǔn)變量,因此我們將在此處創(chuàng)建這些變量,并將這兩個變量傳遞給校準(zhǔn)和保存函數(shù)。同樣,我不會顯示保存部分,因?yàn)檫@與校準(zhǔn)幾乎沒有共同之處。瀏覽源文件,以了解如何以及內(nèi)容:
bool runCalibrationAndSave(Settings&s, Size imageSize, Mat&cameraMatrix, Mat&distCoeffs,
vector<vector >imagePoints、float grid_width、bool release_object)
{
vectorrvecs、tvecs;
vector reprojErrs;
? 雙倍總計AvgErr = 0;
vector newObjPoints;
? bool ok = runCalibration(s, imageSize, cameraMatrix, distCoeffs, imagePoints, rvecs, tvecs, reprojErrs,
totalAvgErr, newObjPoints, grid_width, release_object);
cout << (好嗎?“Calibration succeeds” : “校準(zhǔn)失敗”)
? << “。avg re projection error = “ << totalAvgErr << endl;
? 如果(確定)
saveCameraParams(s, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, reprojErrs, imagePoints,
totalAvgErr, newObjPoints);
? 返回 OK;
}
我們在 cv::calibrateCameraRO 函數(shù)的幫助下進(jìn)行校準(zhǔn)。它具有以下參數(shù):
-
對象指向。這是 Point3f 向量的向量,對于每個輸入圖像,它描述了圖案的外觀。如果我們有一個平面圖案(如棋盤),那么我們可以簡單地將所有 Z 坐標(biāo)設(shè)置為零。這是存在這些重要點(diǎn)的點(diǎn)的集合。因?yàn)?,我們對所有輸入圖像使用單一模式,因此我們只需計算一次,然后將其乘以所有其他輸入視圖。我們使用 calcBoardCornerPositions 函數(shù)計算角點(diǎn),如下所示:
static void calcBoardCornerPositions(Size boardSize, float squareSize, vector& corners,
設(shè)置:?? attern patternType /= 設(shè)置::CHESSBOARD/)
{
corners.clear();
? 開關(guān)(模式類型)
? {
? 箱設(shè)置::CHESSBOARD:
? 箱設(shè)置::CIRCLES_GRID:
? for (int i = 0; i < boardSize.height; ++i) {
? for (int j = 0; j < boardSize.width; ++j) {
corners.push_back(Point3f(jsquareSize, isquareSize, 0));
? }
? }
? 破;
? 箱設(shè)置::CHARUCOBOARD:
? for (int i = 0; i < boardSize.height - 1; ++i) {
? for (int j = 0; j < boardSize.width - 1; ++j) {
corners.push_back(Point3f(jsquareSize, isquareSize, 0));
? }
? }
? 破;
? 箱設(shè)置::ASYMMETRIC_CIRCLES_GRID:
? for (int i = 0; i < boardSize.height; i++) {
? for (int j = 0; j < boardSize.width; j++) {
corners.push_back(Point3f((2 * j + i % 2)squareSize, isquareSize, 0));
? }
? }
? 破;
? 默認(rèn)值:
? 破;
? }
}
然后乘以:
vector<vector > objectPoints(1);
calcBoardCornerPositions(s.boardSize, s.squareSize, objectPoints[0], s.calibrationPattern);
objectPoints[0][s.boardSize.width - 1].x = objectPoints[0][0].x + grid_width;
newObjPoints = objectPoints[0];
objectPoints.resize(imagePoints.size(),objectPoints[0]);
-
注意
如果您的校準(zhǔn)板不準(zhǔn)確、未測量、大致是平面目標(biāo)(使用現(xiàn)成打印機(jī)在紙上的棋盤圖案是最方便的校準(zhǔn)目標(biāo),但大多數(shù)都不夠準(zhǔn)確),可以使用[250]中的方法來顯著提高估計相機(jī)內(nèi)在參數(shù)的精度。如果提供了命令行參數(shù),則將調(diào)用此新的校準(zhǔn)方法。在上面的代碼片段中,實(shí)際上是由 設(shè)置的值。它是圖案網(wǎng)格點(diǎn)的左上角 (0, 0, 0) 和右上角 (s.squareSize*(s.boardSize.width-1), 0, 0) 之間的測量距離。它應(yīng)該用尺子或游標(biāo)卡尺精確測量。校準(zhǔn)后,newObjPoints 將更新為對象點(diǎn)的優(yōu)化 3D 坐標(biāo)。
-d=<number>``grid_width``-d=<number>
-
-
圖像指向。這是 Point2f 向量的向量,對于每個輸入圖像,它包含重要點(diǎn)的坐標(biāo)(棋盤的角和圓圖案的圓心)。我們已經(jīng)從 cv::findChessboardCorners 或 cv::findCirclesGrid 函數(shù)中收集了它。我們只需要傳遞它。
-
從相機(jī)、視頻文件或圖像獲取的圖像的大小。
-
要固定的對象點(diǎn)的索引。我們將其設(shè)置為 -1 以請求標(biāo)準(zhǔn)校準(zhǔn)方法。如果要使用新的對象釋放方法,請將其設(shè)置為校準(zhǔn)板網(wǎng)格右上角點(diǎn)的索引。有關(guān)詳細(xì)說明,請參見 cv::calibrateCameraRO。
int iFixedPoint = -1;
如果 (release_object)
iFixedPoint = s.boardSize.width - 1;
-
相機(jī)矩陣。如果我們使用固定縱橫比選項(xiàng),我們需要設(shè)置:
fx
cameraMatrix = Mat::eye(3, 3, CV_64F);
? if( !s.useFisheye && s.flag & CALIB_FIX_ASPECT_RATIO )
cameraMatrix.at(0,0) = s.aspectRatio;
-
失真系數(shù)矩陣。使用零初始化。
distCoeffs = Mat::zeros(8, 1, CV_64F);
-
對于所有視圖,該函數(shù)將計算旋轉(zhuǎn)和平移向量,這些向量將對象點(diǎn)(在模型坐標(biāo)空間中給出)轉(zhuǎn)換為圖像點(diǎn)(在世界坐標(biāo)空間中給出)。第 7 個和第 8 個參數(shù)是矩陣的輸出向量,在第 i 個位置包含第 i 個對象點(diǎn)到第 i 個圖像點(diǎn)的旋轉(zhuǎn)和平移向量。
-
校準(zhǔn)模式點(diǎn)的更新輸出向量。使用標(biāo)準(zhǔn)校準(zhǔn)方法忽略此參數(shù)。
-
最后一個參數(shù)是標(biāo)志。您需要在此處指定選項(xiàng),例如固定焦距的縱橫比、假設(shè)切向失真為零或固定主點(diǎn)。在這里,我們使用CALIB_USE_LU來獲得更快的校準(zhǔn)速度。
rms = calibrateCameraRO(objectPoints, imagePoints, imageSize, iFixedPoint,
cameraMatrix、distCoeffs、rvecs、tvecs、newObjPoints、
s.flag旗 |CALIB_USE_LU);
-
該函數(shù)返回平均重新投影誤差。這個數(shù)字可以很好地估計所找到參數(shù)的精度。這應(yīng)該盡可能接近于零。給定固有矩陣、失真矩陣、旋轉(zhuǎn)矩陣和平移矩陣,我們可以通過使用 cv::p rojectPoints 首先將對象點(diǎn)轉(zhuǎn)換為圖像點(diǎn)來計算一個視圖的誤差。然后,我們計算變換得到的絕對范數(shù)與角/圓查找算法之間的絕對范數(shù)。為了找到平均誤差,我們計算了所有校準(zhǔn)圖像計算的誤差的算術(shù)平均值。
靜態(tài)雙精度 computeReprojectionErrors( const vector<vector >& objectPoints,
? const vector<vector >& imagePoints,
? const vector& rvecs, const vector& tvecs,
? 常量Mat& cameraMatrix , const Mat& distCoeffs,
vector&perViewErrors,bool fisheye)
{
vectorimagePoints2;
? size_t 總積分 = 0;
? double totalErr = 0, 錯誤;
perViewErrors.resize(objectPoints.size());
? for(size_t i = 0; i < objectPoints.size(); ++i )
? {
? if(魚眼)
? {
? fisheye::p rojectPoints(objectPoints[i], imagePoints2, rvecs[i], tvecs[i], cameraMatrix,
distCoeffs);
? }
? 還
? {
? projectPoints(objectPoints[i], rvecs[i], tvecs[i], cameraMatrix, distCoeffs, imagePoints2);
? }
err = norm(imagePoints[i], imagePoints2, NORM_L2);
? size_t n = objectPoints[i].size();
perViewErrors[i] = (float) std::sqrt(err*err/n);
totalErr += 錯誤*錯誤;
總積分 += n;
? }
? 返回 std::sqrt(totalErr/totalPoints);
}
然后作為配置文件中的輸入傳遞。下面是在應(yīng)用程序運(yùn)行時發(fā)現(xiàn)的棋盤模式:images/CameraCalibration/VID5/VID5.XML
應(yīng)用失真去除后,我們得到:
通過將輸入寬度設(shè)置為 4,將高度設(shè)置為 11,這同樣適用于這種不對稱圓形圖案。這一次,我通過為輸入指定其 ID(“1”)來使用實(shí)時攝像機(jī)源。下面是檢測到的模式的外觀:
在這兩種情況下,在指定的輸出 XML/YAML 文件中,您都會找到相機(jī)和失真系數(shù)矩陣:
如何學(xué)習(xí)大模型 AI ?
由于新崗位的生產(chǎn)效率,要優(yōu)于被取代崗位的生產(chǎn)效率,所以實(shí)際上整個社會的生產(chǎn)效率是提升的。
但是具體到個人,只能說是:
“最先掌握AI的人,將會比較晚掌握AI的人有競爭優(yōu)勢”。
這句話,放在計算機(jī)、互聯(lián)網(wǎng)、移動互聯(lián)網(wǎng)的開局時期,都是一樣的道理。
我在一線互聯(lián)網(wǎng)企業(yè)工作十余年里,指導(dǎo)過不少同行后輩。幫助很多人得到了學(xué)習(xí)和成長。
我意識到有很多經(jīng)驗(yàn)和知識值得分享給大家,也可以通過我們的能力和經(jīng)驗(yàn)解答大家在人工智能學(xué)習(xí)中的很多困惑,所以在工作繁忙的情況下還是堅(jiān)持各種整理和分享。但苦于知識傳播途徑有限,很多互聯(lián)網(wǎng)行業(yè)朋友無法獲得正確的資料得到學(xué)習(xí)提升,故此將并將重要的AI大模型資料包括AI大模型入門學(xué)習(xí)思維導(dǎo)圖、精品AI大模型學(xué)習(xí)書籍手冊、視頻教程、實(shí)戰(zhàn)學(xué)習(xí)等錄播視頻免費(fèi)分享出來。
??有需要的小伙伴,可以點(diǎn)擊下方鏈接免費(fèi)領(lǐng)取或者V掃描下方二維碼免費(fèi)領(lǐng)取??
?
第一階段(10天):初階應(yīng)用
該階段讓大家對大模型 AI有一個最前沿的認(rèn)識,對大模型 AI 的理解超過 95% 的人,可以在相關(guān)討論時發(fā)表高級、不跟風(fēng)、又接地氣的見解,別人只會和 AI 聊天,而你能調(diào)教 AI,并能用代碼將大模型和業(yè)務(wù)銜接。
- 大模型 AI 能干什么?
- 大模型是怎樣獲得「智能」的?
- 用好 AI 的核心心法
- 大模型應(yīng)用業(yè)務(wù)架構(gòu)
- 大模型應(yīng)用技術(shù)架構(gòu)
- 代碼示例:向 GPT-3.5 灌入新知識
- 提示工程的意義和核心思想
- Prompt 典型構(gòu)成
- 指令調(diào)優(yōu)方法論
- 思維鏈和思維樹
- Prompt 攻擊和防范
- …
第二階段(30天):高階應(yīng)用
該階段我們正式進(jìn)入大模型 AI 進(jìn)階實(shí)戰(zhàn)學(xué)習(xí),學(xué)會構(gòu)造私有知識庫,擴(kuò)展 AI 的能力。快速開發(fā)一個完整的基于 agent 對話機(jī)器人。掌握功能最強(qiáng)的大模型開發(fā)框架,抓住最新的技術(shù)進(jìn)展,適合 Python 和 JavaScript 程序員。
- 為什么要做 RAG
- 搭建一個簡單的 ChatPDF
- 檢索的基礎(chǔ)概念
- 什么是向量表示(Embeddings)
- 向量數(shù)據(jù)庫與向量檢索
- 基于向量檢索的 RAG
- 搭建 RAG 系統(tǒng)的擴(kuò)展知識
- 混合檢索與 RAG-Fusion 簡介
- 向量模型本地部署
- …
第三階段(30天):模型訓(xùn)練
恭喜你,如果學(xué)到這里,你基本可以找到一份大模型 AI相關(guān)的工作,自己也能訓(xùn)練 GPT 了!通過微調(diào),訓(xùn)練自己的垂直大模型,能獨(dú)立訓(xùn)練開源多模態(tài)大模型,掌握更多技術(shù)方案。
到此為止,大概2個月的時間。你已經(jīng)成為了一名“AI小子”。那么你還想往下探索嗎?
- 為什么要做 RAG
- 什么是模型
- 什么是模型訓(xùn)練
- 求解器 & 損失函數(shù)簡介
- 小實(shí)驗(yàn)2:手寫一個簡單的神經(jīng)網(wǎng)絡(luò)并訓(xùn)練它
- 什么是訓(xùn)練/預(yù)訓(xùn)練/微調(diào)/輕量化微調(diào)
- Transformer結(jié)構(gòu)簡介
- 輕量化微調(diào)
- 實(shí)驗(yàn)數(shù)據(jù)集的構(gòu)建
- …
第四階段(20天):商業(yè)閉環(huán)
對全球大模型從性能、吞吐量、成本等方面有一定的認(rèn)知,可以在云端和本地等多種環(huán)境下部署大模型,找到適合自己的項(xiàng)目/創(chuàng)業(yè)方向,做一名被 AI 武裝的產(chǎn)品經(jīng)理。
- 硬件選型
- 帶你了解全球大模型
- 使用國產(chǎn)大模型服務(wù)
- 搭建 OpenAI 代理
- 熱身:基于阿里云 PAI 部署 Stable Diffusion
- 在本地計算機(jī)運(yùn)行大模型
- 大模型的私有化部署
- 基于 vLLM 部署大模型
- 案例:如何優(yōu)雅地在阿里云私有部署開源大模型
- 部署一套開源 LLM 項(xiàng)目
- 內(nèi)容安全
- 互聯(lián)網(wǎng)信息服務(wù)算法備案
- …
學(xué)習(xí)是一個過程,只要學(xué)習(xí)就會有挑戰(zhàn)。天道酬勤,你越努力,就會成為越優(yōu)秀的自己。
如果你能在15天內(nèi)完成所有的任務(wù),那你堪稱天才。然而,如果你能完成 60-70% 的內(nèi)容,你就已經(jīng)開始具備成為一名大模型 AI 的正確特征了。文章來源:http://www.zghlxwxcb.cn/news/detail-848969.html
這份完整版的大模型 AI 學(xué)習(xí)資料已經(jīng)上傳CSDN,朋友們?nèi)绻枰梢晕⑿艗呙柘路紺SDN官方認(rèn)證二維碼免費(fèi)領(lǐng)取【保證100%免費(fèi)
】
??有需要的小伙伴,可以點(diǎn)擊下方鏈接免費(fèi)領(lǐng)取或者V掃描下方二維碼免費(fèi)領(lǐng)取??
?文章來源地址http://www.zghlxwxcb.cn/news/detail-848969.html
到了這里,關(guān)于使用 OpenCV 進(jìn)行相機(jī)校準(zhǔn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!